common.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Common code for all backends
  2. #include "platform.h"
  3. #include "common.h"
  4. #include "c_string.h"
  5. #include "c_stdio.h"
  6. void cmn_platform_init(void)
  7. {
  8. }
  9. // ****************************************************************************
  10. // Internal flash support functions
  11. // This symbol must be exported by the linker command file and must reflect the
  12. // TOTAL size of flash used by the eLua image (not only the code and constants,
  13. // but also .data and whatever else ends up in the eLua image). FS will start
  14. // at the next usable (aligned to a flash sector boundary) address after
  15. // flash_used_size.
  16. // extern char flash_used_size[];
  17. extern char _flash_used_end[];
  18. // Helper function: find the flash sector in which an address resides
  19. // Return the sector number, as well as the start and end address of the sector
  20. static uint32_t flash_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
  21. {
  22. #ifdef INTERNAL_FLASH_SECTOR_SIZE
  23. // All the sectors in the flash have the same size, so just align the address
  24. uint32_t sect_id = address / INTERNAL_FLASH_SECTOR_SIZE;
  25. if( pstart )
  26. *pstart = sect_id * INTERNAL_FLASH_SECTOR_SIZE ;
  27. if( pend )
  28. *pend = ( sect_id + 1 ) * INTERNAL_FLASH_SECTOR_SIZE - 1;
  29. return sect_id;
  30. #else // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  31. // The flash has blocks of different size
  32. // Their size is decribed in the INTERNAL_FLASH_SECTOR_ARRAY macro
  33. const uint32_t flash_sect_size[] = INTERNAL_FLASH_SECTOR_ARRAY;
  34. uint32_t total = 0, i = 0;
  35. while( ( total <= address ) && ( i < sizeof( flash_sect_size ) / sizeof( uint32_t ) ) )
  36. total += flash_sect_size[ i ++ ];
  37. if( pstart )
  38. *pstart = ( total - flash_sect_size[ i - 1 ] );
  39. if( pend )
  40. *pend = total - 1;
  41. return i - 1;
  42. #endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  43. }
  44. uint32_t platform_flash_get_sector_of_address( uint32_t addr )
  45. {
  46. return flash_find_sector( addr, NULL, NULL );
  47. }
  48. uint32_t platform_flash_get_num_sectors(void)
  49. {
  50. #ifdef INTERNAL_FLASH_SECTOR_SIZE
  51. return INTERNAL_FLASH_SIZE / INTERNAL_FLASH_SECTOR_SIZE;
  52. #else // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  53. const uint32_t flash_sect_size[] = INTERNAL_FLASH_SECTOR_ARRAY;
  54. return sizeof( flash_sect_size ) / sizeof( uint32_t );
  55. #endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  56. }
  57. uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
  58. {
  59. // Round the total used flash size to the closest flash block address
  60. uint32_t start, end, sect;
  61. NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
  62. if(_flash_used_end>0){ // find the used sector
  63. sect = flash_find_sector( platform_flash_mapped2phys ( (uint32_t)_flash_used_end - 1), NULL, &end );
  64. if( psect )
  65. *psect = sect + 1;
  66. return end + 1;
  67. } else {
  68. sect = flash_find_sector( 0, &start, NULL ); // find the first free sector
  69. if( psect )
  70. *psect = sect;
  71. return start;
  72. }
  73. }
  74. uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size )
  75. {
  76. #ifndef INTERNAL_FLASH_WRITE_UNIT_SIZE
  77. return platform_s_flash_write( from, toaddr, size );
  78. #else // #ifindef INTERNAL_FLASH_WRITE_UNIT_SIZE
  79. uint32_t temp, rest, ssize = size;
  80. unsigned i;
  81. char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ];
  82. const uint8_t *pfrom = ( const uint8_t* )from;
  83. const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE;
  84. const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
  85. // Align the start
  86. if( toaddr & blkmask )
  87. {
  88. rest = toaddr & blkmask;
  89. temp = toaddr & ~blkmask; // this is the actual aligned address
  90. // c_memcpy( tmpdata, ( const void* )temp, blksize );
  91. platform_s_flash_read( tmpdata, temp, blksize );
  92. for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ )
  93. tmpdata[ i ] = *pfrom;
  94. platform_s_flash_write( tmpdata, temp, blksize );
  95. if( size == 0 )
  96. return ssize;
  97. toaddr = temp + blksize;
  98. }
  99. // The start address is now a multiple of blksize
  100. // Compute how many bytes we can write as multiples of blksize
  101. rest = size & blkmask;
  102. temp = size & ~blkmask;
  103. // Program the blocks now
  104. if( temp )
  105. {
  106. platform_s_flash_write( pfrom, toaddr, temp );
  107. toaddr += temp;
  108. pfrom += temp;
  109. }
  110. // And the final part of a block if needed
  111. if( rest )
  112. {
  113. // c_memcpy( tmpdata, ( const void* )toaddr, blksize );
  114. platform_s_flash_read( tmpdata, toaddr, blksize );
  115. for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ )
  116. tmpdata[ i ] = *pfrom;
  117. platform_s_flash_write( tmpdata, toaddr, blksize );
  118. }
  119. return ssize;
  120. #endif // #ifndef INTERNAL_FLASH_WRITE_UNIT_SIZE
  121. }
  122. uint32_t platform_flash_read( void *to, uint32_t fromaddr, uint32_t size )
  123. {
  124. #ifndef INTERNAL_FLASH_READ_UNIT_SIZE
  125. return platform_s_flash_read( to, fromaddr, size );
  126. #else // #ifindef INTERNAL_FLASH_READ_UNIT_SIZE
  127. uint32_t temp, rest, ssize = size;
  128. unsigned i;
  129. char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ] __attribute__ ((aligned(INTERNAL_FLASH_READ_UNIT_SIZE)));
  130. uint8_t *pto = ( uint8_t* )to;
  131. const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE;
  132. const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1;
  133. // Align the start
  134. if( fromaddr & blkmask )
  135. {
  136. rest = fromaddr & blkmask;
  137. temp = fromaddr & ~blkmask; // this is the actual aligned address
  138. platform_s_flash_read( tmpdata, temp, blksize );
  139. for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ )
  140. *pto = tmpdata[ i ];
  141. if( size == 0 )
  142. return ssize;
  143. fromaddr = temp + blksize;
  144. }
  145. // The start address is now a multiple of blksize
  146. // Compute how many bytes we can read as multiples of blksize
  147. rest = size & blkmask;
  148. temp = size & ~blkmask;
  149. // Program the blocks now
  150. if( temp )
  151. {
  152. platform_s_flash_read( pto, fromaddr, temp );
  153. fromaddr += temp;
  154. pto += temp;
  155. }
  156. // And the final part of a block if needed
  157. if( rest )
  158. {
  159. platform_s_flash_read( tmpdata, fromaddr, blksize );
  160. for( i = 0; size && ( i < rest ); i ++, size --, pto ++ )
  161. *pto = tmpdata[ i ];
  162. }
  163. return ssize;
  164. #endif // #ifndef INTERNAL_FLASH_READ_UNIT_SIZE
  165. }