common.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. // GPIO functions
  11. int platform_gpio_exists( unsigned pin )
  12. {
  13. return pin < NUM_GPIO;
  14. }
  15. // ****************************************************************************
  16. // CAN functions
  17. int platform_can_exists( unsigned id )
  18. {
  19. return id < NUM_CAN;
  20. }
  21. // ****************************************************************************
  22. // SPI functions
  23. int platform_spi_exists( unsigned id )
  24. {
  25. return id < NUM_SPI;
  26. }
  27. // ****************************************************************************
  28. // PWM functions
  29. int platform_pwm_exists( unsigned id )
  30. {
  31. return ((id < NUM_PWM) && (id > 0));
  32. }
  33. // ****************************************************************************
  34. // ADC functions
  35. int platform_adc_exists( unsigned id )
  36. {
  37. return id < NUM_ADC;
  38. }
  39. // ****************************************************************************
  40. // UART functions
  41. int platform_uart_exists( unsigned id )
  42. {
  43. return id < NUM_UART;
  44. }
  45. // ****************************************************************************
  46. // OneWire functions
  47. int platform_ow_exists( unsigned id )
  48. {
  49. return ((id < NUM_OW) && (id > 0));
  50. }
  51. // ****************************************************************************
  52. // Timer functions
  53. int platform_tmr_exists( unsigned id )
  54. {
  55. return id < NUM_TMR;
  56. }
  57. // ****************************************************************************
  58. // I2C support
  59. int platform_i2c_exists( unsigned id )
  60. {
  61. #ifndef NUM_I2C
  62. return 0;
  63. #else
  64. return id < NUM_I2C;
  65. #endif
  66. }
  67. // ****************************************************************************
  68. // Internal flash support functions
  69. // This symbol must be exported by the linker command file and must reflect the
  70. // TOTAL size of flash used by the eLua image (not only the code and constants,
  71. // but also .data and whatever else ends up in the eLua image). FS will start
  72. // at the next usable (aligned to a flash sector boundary) address after
  73. // flash_used_size.
  74. // extern char flash_used_size[];
  75. extern char _flash_used_end[];
  76. // Helper function: find the flash sector in which an address resides
  77. // Return the sector number, as well as the start and end address of the sector
  78. static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
  79. {
  80. address -= INTERNAL_FLASH_START_ADDRESS;
  81. #ifdef INTERNAL_FLASH_SECTOR_SIZE
  82. // All the sectors in the flash have the same size, so just align the address
  83. uint32_t sect_id = address / INTERNAL_FLASH_SECTOR_SIZE;
  84. if( pstart )
  85. *pstart = sect_id * INTERNAL_FLASH_SECTOR_SIZE + INTERNAL_FLASH_START_ADDRESS;
  86. if( pend )
  87. *pend = ( sect_id + 1 ) * INTERNAL_FLASH_SECTOR_SIZE + INTERNAL_FLASH_START_ADDRESS - 1;
  88. return sect_id;
  89. #else // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  90. // The flash has blocks of different size
  91. // Their size is decribed in the INTERNAL_FLASH_SECTOR_ARRAY macro
  92. const uint32_t flash_sect_size[] = INTERNAL_FLASH_SECTOR_ARRAY;
  93. uint32_t total = 0, i = 0;
  94. while( ( total <= address ) && ( i < sizeof( flash_sect_size ) / sizeof( uint32_t ) ) )
  95. total += flash_sect_size[ i ++ ];
  96. if( pstart )
  97. *pstart = ( total - flash_sect_size[ i - 1 ] ) + INTERNAL_FLASH_START_ADDRESS;
  98. if( pend )
  99. *pend = total + INTERNAL_FLASH_START_ADDRESS - 1;
  100. return i - 1;
  101. #endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  102. }
  103. uint32_t platform_flash_get_sector_of_address( uint32_t addr )
  104. {
  105. return flashh_find_sector( addr, NULL, NULL );
  106. }
  107. uint32_t platform_flash_get_num_sectors(void)
  108. {
  109. #ifdef INTERNAL_FLASH_SECTOR_SIZE
  110. return INTERNAL_FLASH_SIZE / INTERNAL_FLASH_SECTOR_SIZE;
  111. #else // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  112. const uint32_t flash_sect_size[] = INTERNAL_FLASH_SECTOR_ARRAY;
  113. return sizeof( flash_sect_size ) / sizeof( uint32_t );
  114. #endif // #ifdef INTERNAL_FLASH_SECTOR_SIZE
  115. }
  116. uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
  117. {
  118. // Round the total used flash size to the closest flash block address
  119. uint32_t start, end, sect;
  120. NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
  121. if(_flash_used_end>0){ // find the used sector
  122. // sect = flashh_find_sector( ( uint32_t )flash_used_size + INTERNAL_FLASH_START_ADDRESS - 1, NULL, &end );
  123. sect = flashh_find_sector( ( uint32_t )_flash_used_end - 1, NULL, &end );
  124. if( psect )
  125. *psect = sect + 1;
  126. return end + 1;
  127. }else{
  128. sect = flashh_find_sector( INTERNAL_FLASH_START_ADDRESS, &start, NULL ); // find the first free sector
  129. if( psect )
  130. *psect = sect;
  131. return start;
  132. }
  133. }
  134. uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size )
  135. {
  136. #ifndef INTERNAL_FLASH_WRITE_UNIT_SIZE
  137. return platform_s_flash_write( from, toaddr, size );
  138. #else // #ifindef INTERNAL_FLASH_WRITE_UNIT_SIZE
  139. uint32_t temp, rest, ssize = size;
  140. unsigned i;
  141. char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ];
  142. const uint8_t *pfrom = ( const uint8_t* )from;
  143. const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE;
  144. const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1;
  145. // Align the start
  146. if( toaddr & blkmask )
  147. {
  148. rest = toaddr & blkmask;
  149. temp = toaddr & ~blkmask; // this is the actual aligned address
  150. // c_memcpy( tmpdata, ( const void* )temp, blksize );
  151. platform_s_flash_read( tmpdata, temp, blksize );
  152. for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ )
  153. tmpdata[ i ] = *pfrom;
  154. platform_s_flash_write( tmpdata, temp, blksize );
  155. if( size == 0 )
  156. return ssize;
  157. toaddr = temp + blksize;
  158. }
  159. // The start address is now a multiple of blksize
  160. // Compute how many bytes we can write as multiples of blksize
  161. rest = size & blkmask;
  162. temp = size & ~blkmask;
  163. // Program the blocks now
  164. if( temp )
  165. {
  166. platform_s_flash_write( pfrom, toaddr, temp );
  167. toaddr += temp;
  168. pfrom += temp;
  169. }
  170. // And the final part of a block if needed
  171. if( rest )
  172. {
  173. // c_memcpy( tmpdata, ( const void* )toaddr, blksize );
  174. platform_s_flash_read( tmpdata, toaddr, blksize );
  175. for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ )
  176. tmpdata[ i ] = *pfrom;
  177. platform_s_flash_write( tmpdata, toaddr, blksize );
  178. }
  179. return ssize;
  180. #endif // #ifndef INTERNAL_FLASH_WRITE_UNIT_SIZE
  181. }
  182. uint32_t platform_flash_read( void *to, uint32_t fromaddr, uint32_t size )
  183. {
  184. #ifndef INTERNAL_FLASH_READ_UNIT_SIZE
  185. return platform_s_flash_read( to, fromaddr, size );
  186. #else // #ifindef INTERNAL_FLASH_READ_UNIT_SIZE
  187. uint32_t temp, rest, ssize = size;
  188. unsigned i;
  189. char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ];
  190. uint8_t *pto = ( uint8_t* )to;
  191. const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE;
  192. const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1;
  193. // Align the start
  194. if( fromaddr & blkmask )
  195. {
  196. rest = fromaddr & blkmask;
  197. temp = fromaddr & ~blkmask; // this is the actual aligned address
  198. platform_s_flash_read( tmpdata, temp, blksize );
  199. for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ )
  200. *pto = tmpdata[ i ];
  201. if( size == 0 )
  202. return ssize;
  203. fromaddr = temp + blksize;
  204. }
  205. // The start address is now a multiple of blksize
  206. // Compute how many bytes we can read as multiples of blksize
  207. rest = size & blkmask;
  208. temp = size & ~blkmask;
  209. // Program the blocks now
  210. if( temp )
  211. {
  212. platform_s_flash_read( pto, fromaddr, temp );
  213. fromaddr += temp;
  214. pto += temp;
  215. }
  216. // And the final part of a block if needed
  217. if( rest )
  218. {
  219. platform_s_flash_read( tmpdata, fromaddr, blksize );
  220. for( i = 0; size && ( i < rest ); i ++, size --, pto ++ )
  221. *pto = tmpdata[ i ];
  222. }
  223. return ssize;
  224. #endif // #ifndef INTERNAL_FLASH_READ_UNIT_SIZE
  225. }