common.c 6.5 KB

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