Kiibohd Controller
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

main.c 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* Copyright (c) 2011,2012 Simon Schubert <[email protected]>.
  2. * Modifications by Jacob Alexander 2014-2016 <[email protected]>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. // ----- Includes -----
  18. // Project Includes
  19. #include <delay.h>
  20. // Local Includes
  21. #include "mchck.h"
  22. #include "dfu.desc.h"
  23. #include "debug.h"
  24. #include "usb-internal.h"
  25. // ----- Variables -----
  26. /**
  27. * Unfortunately we can't DMA directly to FlexRAM, so we'll have to stage here.
  28. */
  29. static char staging[ USB_DFU_TRANSFER_SIZE ];
  30. // ----- Functions -----
  31. int sector_print( void* buf, size_t sector, size_t chunks )
  32. {
  33. uint8_t* start = (uint8_t*)buf + sector * USB_DFU_TRANSFER_SIZE;
  34. uint8_t* end = (uint8_t*)buf + (sector + 1) * USB_DFU_TRANSFER_SIZE;
  35. uint8_t* pos = start;
  36. // Verify if sector erased
  37. FTFL.fccob.read_1s_section.fcmd = FTFL_FCMD_READ_1s_SECTION;
  38. FTFL.fccob.read_1s_section.addr = (uintptr_t)start;
  39. FTFL.fccob.read_1s_section.margin = FTFL_MARGIN_NORMAL;
  40. FTFL.fccob.read_1s_section.num_words = 250; // 2000 kB / 64 bits
  41. int retval = ftfl_submit_cmd();
  42. #ifdef FLASH_DEBUG
  43. print( NL );
  44. print("Block ");
  45. printHex( sector );
  46. print(" ");
  47. printHex( (size_t)start );
  48. print(" -> ");
  49. printHex( (size_t)end );
  50. print(" Erased: ");
  51. printHex( retval );
  52. print( NL );
  53. #endif
  54. // Display sector
  55. for ( size_t line = 0; pos < end - 24; line++ )
  56. {
  57. // Each Line
  58. printHex_op( (size_t)pos, 4 );
  59. print(": ");
  60. // Each 2 byte chunk
  61. for ( size_t chunk = 0; chunk < chunks; chunk++ )
  62. {
  63. // Print out the two bytes (second one first)
  64. printHex_op( *(pos + 1), 2 );
  65. printHex_op( *pos, 2 );
  66. print(" ");
  67. pos += 2;
  68. }
  69. print( NL );
  70. }
  71. return retval;
  72. }
  73. static enum dfu_status setup_read( size_t off, size_t *len, void **buf )
  74. {
  75. // Calculate starting address from offset
  76. *buf = (void*)&_app_rom + (USB_DFU_TRANSFER_SIZE / 4) * off;
  77. // Calculate length of transfer
  78. /*
  79. *len = *buf > (void*)(&_app_rom_end) - USB_DFU_TRANSFER_SIZE
  80. ? 0 : USB_DFU_TRANSFER_SIZE;
  81. */
  82. // Check for error
  83. /*
  84. if ( *buf > (void*)&_app_rom_end )
  85. return (DFU_STATUS_errADDRESS);
  86. */
  87. return (DFU_STATUS_OK);
  88. }
  89. static enum dfu_status setup_write( size_t off, size_t len, void **buf )
  90. {
  91. static int last = 0;
  92. #ifdef FLASH_DEBUG
  93. // Debug
  94. print("Setup Write: offset(");
  95. printHex( off );
  96. print(") len(");
  97. printHex( len );
  98. print(") last(");
  99. printHex( last );
  100. printNL(")");
  101. #endif
  102. if ( len > sizeof(staging) )
  103. return (DFU_STATUS_errADDRESS);
  104. // We only allow the last write to be less than one sector size.
  105. if ( off == 0 )
  106. last = 0;
  107. if ( last && len != 0 )
  108. return (DFU_STATUS_errADDRESS);
  109. if ( len != USB_DFU_TRANSFER_SIZE )
  110. {
  111. last = 1;
  112. memset( staging, 0xff, sizeof(staging) );
  113. }
  114. *buf = staging;
  115. return (DFU_STATUS_OK);
  116. }
  117. static enum dfu_status finish_write( void *buf, size_t off, size_t len )
  118. {
  119. void *target;
  120. if ( len == 0 )
  121. return (DFU_STATUS_OK);
  122. target = flash_get_staging_area( off + (uintptr_t)&_app_rom, USB_DFU_TRANSFER_SIZE );
  123. if ( !target )
  124. return (DFU_STATUS_errADDRESS);
  125. memcpy( target, buf, len );
  126. // Depending on the error return a different status
  127. switch ( flash_program_sector( off + (uintptr_t)&_app_rom, USB_DFU_TRANSFER_SIZE ) )
  128. {
  129. /*
  130. case FTFL_FSTAT_RDCOLERR: // Flash Read Collision Error
  131. case FTFL_FSTAT_ACCERR: // Flash Access Error
  132. case FTFL_FSTAT_FPVIOL: // Flash Protection Violation Error
  133. return (DFU_STATUS_errADDRESS);
  134. case FTFL_FSTAT_MGSTAT0: // Memory Controller Command Completion Error
  135. return (DFU_STATUS_errADDRESS);
  136. */
  137. case 0:
  138. default: // No error
  139. return (DFU_STATUS_OK);
  140. }
  141. }
  142. static struct dfu_ctx dfu_ctx;
  143. void init_usb_bootloader( int config )
  144. {
  145. dfu_init( setup_read, setup_write, finish_write, &dfu_ctx );
  146. // Make sure SysTick counter is disabled
  147. SYST_CSR = 0;
  148. }
  149. void main()
  150. {
  151. #if defined(_mk20dx128vlf5_) // Kiibohd-dfu / Infinity
  152. // XXX McHCK uses B16 instead of A19
  153. // Enabling LED to indicate we are in the bootloader
  154. GPIOA_PDDR |= (1<<19);
  155. // Setup pin - A19 - See Lib/pin_map.mchck for more details on pins
  156. PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  157. GPIOA_PSOR |= (1<<19);
  158. #elif defined(_mk20dx256vlh7_) // Kiibohd-dfu
  159. // Enabling LED to indicate we are in the bootloader
  160. GPIOA_PDDR |= (1<<5);
  161. // Setup pin - A5 - See Lib/pin_map.mchck for more details on pins
  162. PORTA_PCR5 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  163. GPIOA_PSOR |= (1<<5);
  164. // TODO Add CMake configuration for disabling
  165. // Set LCD backlight on ICED to Red
  166. GPIOC_PDDR |= (1<<1);
  167. PORTC_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  168. GPIOC_PCOR |= (1<<1);
  169. #else
  170. #error "Incompatible chip for bootloader"
  171. #endif
  172. uart_serial_setup();
  173. printNL( NL "Bootloader DFU-Mode" );
  174. // Bootloader Enter Reasons
  175. print(" RCM_SRS0 - ");
  176. printHex( RCM_SRS0 & 0x60 );
  177. print( NL " RCM_SRS1 - ");
  178. printHex( RCM_SRS1 & 0x02 );
  179. print( NL " _app_rom - ");
  180. printHex( (uint32_t)_app_rom );
  181. print( NL " Soft Rst - " );
  182. printHex( memcmp( (uint8_t*)&VBAT, sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic) ) == 0 );
  183. print( NL );
  184. #ifdef FLASH_DEBUG
  185. for ( uint8_t sector = 0; sector < 3; sector++ )
  186. sector_print( &_app_rom, sector, 16 );
  187. print( NL );
  188. #endif
  189. flash_prepare_flashing();
  190. usb_init( &dfu_device );
  191. #if defined(_mk20dx256vlh7_) // Kiibohd-dfu
  192. // PTA4 - USB Swap
  193. // Start, disabled
  194. GPIOA_PDDR |= (1<<4);
  195. PORTA_PCR4 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
  196. GPIOA_PCOR |= (1<<4);
  197. #define USBPortSwapDelay_ms 1000
  198. #define USBPortSwapIncrement_ms 100
  199. // For keyboards with dual usb ports, doesn't do anything on keyboards without them
  200. // If a USB connection is not detected in 1 second, switch to the other port to see if it's plugged in there
  201. // Incremement the delay by 100 ms each attempt, just in case the device is slow
  202. uint32_t attempt = 0;
  203. uint32_t last_ms = systick_millis_count;
  204. for (;;)
  205. {
  206. usb_poll();
  207. // Only check for swapping after delay
  208. uint32_t wait_ms = systick_millis_count - last_ms;
  209. if ( wait_ms < USBPortSwapDelay_ms + attempt / 2 * USBPortSwapIncrement_ms )
  210. {
  211. continue;
  212. }
  213. last_ms = systick_millis_count;
  214. // USB not initialized, attempt to swap
  215. if ( usb.state != USBD_STATE_ADDRESS )
  216. {
  217. print("USB not initializing, port swapping (if supported)");
  218. GPIOA_PTOR |= (1<<4);
  219. attempt++;
  220. }
  221. }
  222. #else
  223. for (;;)
  224. {
  225. usb_poll();
  226. }
  227. #endif
  228. }