usb_application_flash.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. #include "usbapp/usb_application_flash.h"
  2. #include "usb/usb_bridge.h"
  3. #include "usb/usb_config.h"
  4. #include "usbd_vendor.h"
  5. #include "drivers/flash/base/extmem_flash.h"
  6. #include "core/csect.h"
  7. #include "core/config.h"
  8. #include "app/nfm/nfm_base.h"
  9. #define PROTO_REQ_READ_DATA_FLASH 0x02 // ïðî÷èòàòü äàííûå èç ôëåø (ðåæèì ýìóëÿöèè áàíêîâ)
  10. #define PROTO_REQ_WRITE_DATA_FLASH 0x03 // çàïèñàòü äàííûå âî ôëåø (ðåæèì ýìóëÿöèè áàíêîâ)
  11. #define PROTO_REQ_GET_FLAG_FLASH_STATUS 0x06 // ñ÷èòàòü ñîñòîÿíèå ñòàòóñà çàïèñè ôëåøà
  12. #define PROTO_REQ_SET_PROTECT_FLASH 0x07 // óñòàíîâèòü çàùèòó ôëåøà
  13. #define PROTO_REQ_READ_DATA_FLASH_EX 0xA3 // ïðî÷èòàòü äàííûå èç ôëåøè (ëèíåéíûé ýêñïåðòíûé ðåæèì)
  14. #define PROTO_REQ_READ_INFO 0xA4 // ÷òåíèå ñëóæåáíîé èíôîðìàöèè
  15. #define PROTO_REQ_WRITE_DATA_FLASH_LIN 0xA5 // çàïèñàòü äàííûå âî ôëåø (ëèíåéíûé ðåæèì)
  16. #define PROTO_REQ_READ_DATA_FLASH_LIN 0xA6 // ïðî÷èòàòü äàííûå èç ôëåø (ëèíåéíûé ðåæèì)
  17. static int8_t fFlashAppInit();
  18. static int8_t fFlashAppDeInit();
  19. static void fFlashAppReset();
  20. static bool fFlashAppSetup( const tUSBSetupPacket_t * pSetup, bool bFirstStage, bool success );
  21. static size_t fFlashAppControlRx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining );
  22. static size_t fFlashAppControlTx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining );
  23. const sUSBAppEntry_Control_t usbapplication_ACM_planarproto_flash = {
  24. .fUsbInit = fFlashAppInit,
  25. .fUsbDeInit = fFlashAppDeInit,
  26. .fUsbSetup = fFlashAppSetup,
  27. .fUsbCtlEpRx = fFlashAppControlRx,
  28. .fUsbCtlEpTx = fFlashAppControlTx,
  29. .fResetEvent = fFlashAppReset,
  30. };
  31. //-----------------------------------------------------
  32. static sUSBTransfer_t transf_write_flash;
  33. static flash_address_t WritingAddress = 0;
  34. static volatile bool bFlagWritingInProgress = false;
  35. static inline bool fGetWritingFlag()
  36. {
  37. bool flag;
  38. __DI__ flag = bFlagWritingInProgress; __EI__
  39. return flag;
  40. }
  41. bool usb_application_flash_fGetWritingFlag()
  42. {
  43. return fGetWritingFlag();
  44. }
  45. /*
  46. static inline void fSetWritingFlag()
  47. {
  48. __DI__ bFlagWritingInProgress = true; __EI__
  49. }
  50. */
  51. static inline void fClrWritingFlag()
  52. {
  53. __DI__ bFlagWritingInProgress = false; __EI__
  54. }
  55. static inline bool fTrySetWritingFlag()
  56. {
  57. bool flag = false;
  58. __DI__
  59. if( ! bFlagWritingInProgress )
  60. {
  61. bFlagWritingInProgress = flag = true;
  62. }
  63. __EI__
  64. return flag;
  65. }
  66. //-----------------------------------------------------
  67. static size_t fFlashApp_ReadDataFlash( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining );
  68. static size_t fFlashApp_WriteDataFlash( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining );
  69. static size_t fFlashApp_ReadReadyFlash( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining );
  70. static bool fFlashApp_SetProtectionFlash( const tUSBSetupPacket_t * pSetup );
  71. // &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&& &&&&
  72. static int8_t fFlashAppInit()
  73. {
  74. return 0;
  75. }
  76. // &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ----
  77. static int8_t fFlashAppDeInit()
  78. {
  79. return 0;
  80. }
  81. // &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ----
  82. static void fFlashAppReset()
  83. {
  84. }
  85. // &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ----
  86. static bool fFlashAppSetup( const tUSBSetupPacket_t * pSetup, bool bFirstStage, bool success )
  87. {
  88. switch ( pSetup->bRequest )
  89. {
  90. case PROTO_REQ_READ_DATA_FLASH:
  91. {
  92. // check device ready
  93. if( fGetWritingFlag() )
  94. {
  95. return false; // device busy
  96. }
  97. else
  98. {
  99. return (bool)fFlashApp_ReadDataFlash( pSetup, NULL, 0, 0 );
  100. }
  101. }
  102. break;
  103. case PROTO_REQ_WRITE_DATA_FLASH:
  104. {
  105. // check device ready
  106. if( fGetWritingFlag() )
  107. {
  108. return false; // device busy
  109. }
  110. else
  111. {
  112. return (bool)fFlashApp_WriteDataFlash( pSetup, NULL, 0, 0 );;
  113. }
  114. }
  115. break;
  116. case PROTO_REQ_GET_FLAG_FLASH_STATUS:
  117. {
  118. return true; // accept
  119. }
  120. break;
  121. case PROTO_REQ_SET_PROTECT_FLASH:
  122. {
  123. // perform factory-memory bank protection: inside this IRQ routine
  124. switch( pSetup->wValue )
  125. {
  126. case 0x0000:
  127. case 0x0001:
  128. {
  129. // 0x0000, 0x0001
  130. return fFlashApp_SetProtectionFlash( pSetup );
  131. }
  132. }
  133. }
  134. break;
  135. }
  136. return false;
  137. }
  138. // &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ----
  139. static size_t fFlashAppControlRx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining )
  140. {
  141. switch ( pSetup->bRequest )
  142. {
  143. case PROTO_REQ_WRITE_DATA_FLASH:
  144. {
  145. return fFlashApp_WriteDataFlash( pSetup, rx, idx, bytesRemaining );
  146. }
  147. break;
  148. }
  149. return 0;
  150. }
  151. // &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ---- &&&& ----
  152. static size_t fFlashAppControlTx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining )
  153. {
  154. switch ( pSetup->bRequest )
  155. {
  156. case PROTO_REQ_READ_DATA_FLASH:
  157. {
  158. return fFlashApp_ReadDataFlash( pSetup, tx, idx, bytesRemaining );
  159. }
  160. break;
  161. case PROTO_REQ_GET_FLAG_FLASH_STATUS:
  162. {
  163. return fFlashApp_ReadReadyFlash( pSetup, tx, idx, bytesRemaining );
  164. }
  165. break;
  166. }
  167. return 0;
  168. }
  169. // &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ----
  170. static size_t fFlashApp_ReadDataFlash( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining )
  171. {
  172. flash_address_t chunk_address = idx + (flash_address_t)pSetup->wIndex + (((flash_address_t)pSetup->wValue)<<16);
  173. if( NULL == tx )
  174. {
  175. return ((ExtMemHandle.RangeCheck_Read( chunk_address, bytesRemaining ))?1:0);
  176. }
  177. flash_size_t chunk_bytes = MIN( bytesRemaining, usb_space_transfer( tx ) );
  178. if( ExtMemHandle.Read( chunk_address, usb_transfer_raw_write(tx), chunk_bytes ) )
  179. {
  180. return usb_transfer_virtual_write( tx, chunk_bytes );
  181. }
  182. return 0;
  183. }
  184. // &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ----
  185. static size_t fFlashApp_WriteDataFlash( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining )
  186. {
  187. flash_address_t chunk_address = idx + (flash_address_t)pSetup->wIndex + (((flash_address_t)pSetup->wValue)<<16);
  188. if( NULL == rx )
  189. {
  190. // For normal operation it is required that whole the packet
  191. // fits to the Low-Level RX-buffer (aka RX-transfer), and this
  192. // event fires only when all the data already received.
  193. // This fact guaranees that the application CAN USE MOVE SEMANTIC
  194. // on the RX-transfer because it is a last RX-event in the sequence.
  195. if( pSetup->wLength > USBD_VENDOR_get_control_rx_transfer_size() )
  196. {
  197. // No, the whole transfer length is greater than RX-transfer size.
  198. // Partial writing is not supported
  199. // Whole packet must fit into the transfer size.
  200. return false;
  201. }
  202. return ((ExtMemHandle.RangeCheck_Write( chunk_address, bytesRemaining ))?1:0);
  203. }
  204. // Check device ready and set busy flag
  205. if( fTrySetWritingFlag() )
  206. {
  207. flash_size_t chunk_bytes = MIN( bytesRemaining, usb_count_transfer( rx ) );
  208. // For normal operation it is required that whole the packet
  209. // fits to the Low-Level RX-buffer (aka RX-transfer), and this
  210. // event fires only when all the data already received.
  211. // This fact guaranees that the application CAN USE MOVE SEMANTIC
  212. // on the RX-transfer because it is a last RX-event in the sequence.
  213. // Check if all the data already is in the transfer:
  214. if( (0 == idx) && (usb_count_transfer( rx ) == bytesRemaining) )
  215. {
  216. // Ok, all conditions are true
  217. // use MOVE SEMANTIC on the passed transfer @rx
  218. // Make the source @rx transfer invalid
  219. // Move all resources from @rx to the new object @transf_write_flash
  220. // After the operation the source @rx transfer will be invalid.
  221. // The core will not be able use internal RX-transfer (specified by @rx).
  222. // Need to move the transfer back
  223. usb_move_transfer( &transf_write_flash, rx, false );
  224. // Remember region parameters
  225. WritingAddress = chunk_address;
  226. // It is required to remember the transfer object the move semantic implemented on.
  227. // Use user context value of the transfer objects: store the @rx pointer into the @transf_write_flash
  228. usb_transfer_set_context( &transf_write_flash, rx );
  229. // NOW USB-CORE UNABLE TO RECEIVE DATA!!!
  230. // Internal USB-CORE RX-buffer is moved to the @transf_write_flash object!
  231. // report the core that all
  232. return usb_count_transfer( &transf_write_flash );
  233. }
  234. // on error case: reset the flag
  235. fClrWritingFlag();
  236. }
  237. return 0;
  238. }
  239. // &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ----
  240. static size_t fFlashApp_ReadReadyFlash( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining )
  241. {
  242. flash_size_t chunk_bytes = MIN( bytesRemaining, usb_space_transfer( tx ) );
  243. uint8_t value[2] = { 0x00 };
  244. if( fGetWritingFlag() )
  245. value[0] = 0x00A5;
  246. else
  247. value[0] = 0x0000;
  248. if( (idx < sizeof( value )) && (bytesRemaining <= sizeof( value )) )
  249. {
  250. usb_push_transfer( tx, &value[idx], bytesRemaining );
  251. }
  252. return usb_count_transfer( tx );
  253. }
  254. // &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ----
  255. static bool fFlashApp_SetProtectionFlash( const tUSBSetupPacket_t * pSetup )
  256. {
  257. bool ret = false;
  258. switch( pSetup->wValue )
  259. {
  260. case 0x0000:
  261. {
  262. #if CONFIG_NFMBASECLASS
  263. ret = NFMClass->methods.xMemoryProtection.enable();
  264. #else
  265. ret = ExtMemHandle.BankProtect( extmem_bank_factory, true ) // Set BANK0 protection
  266. &&
  267. ExtMemHandle.BankProtect( extmem_bank_user, false ); // Clear BANK1 protection (always unprotected)
  268. #endif
  269. }
  270. break;
  271. case 0x0001:
  272. {
  273. #if CONFIG_NFMBASECLASS
  274. ret = NFMClass->methods.xMemoryProtection.disable();
  275. #else
  276. ret = ExtMemHandle.BankProtect( extmem_bank_factory, false ) // Clear BANK0 protection
  277. &&
  278. ExtMemHandle.BankProtect( extmem_bank_user, false ); // Clear BANK1 protection (always unprotected)
  279. #endif
  280. }
  281. break;
  282. }
  283. /* 30/05/19, Testing
  284. asm("bkpt #0");
  285. bool bank0 = false;
  286. bool bank1 = false;
  287. ExtMemHandle.CheckBankProtect( extmem_bank_factory, &bank0 );
  288. ExtMemHandle.CheckBankProtect( extmem_bank_user, &bank1 );
  289. asm("bkpt #0");
  290. ExtMemHandle.BankProtect( extmem_bank_factory, false );
  291. ExtMemHandle.BankProtect( extmem_bank_user, false );
  292. asm("bkpt #0");
  293. ExtMemHandle.BankProtect( extmem_bank_factory, true );
  294. ExtMemHandle.BankProtect( extmem_bank_user, false );
  295. asm("bkpt #0");
  296. ExtMemHandle.BankProtect( extmem_bank_factory, false );
  297. ExtMemHandle.BankProtect( extmem_bank_user, true );
  298. asm("bkpt #0");
  299. ExtMemHandle.BankProtect( extmem_bank_factory, true );
  300. ExtMemHandle.BankProtect( extmem_bank_user, true );
  301. asm("bkpt #0");
  302. (void)bank0; (void)bank1;
  303. */
  304. return ret;
  305. }
  306. // &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ---- &--& ----
  307. void usb_application_flash_serve()
  308. {
  309. // Serve the flash u-application
  310. // Check if the writing flag is set
  311. if( fGetWritingFlag() )
  312. {
  313. #if CONFIG_NFMCLASS_AUTOPROTECT_MEMORY
  314. // protect factory data: set memory protection
  315. NFMClass->methods.xMemoryProtection.disable();
  316. #endif
  317. // retireve the data pointer
  318. void * pWriteData = usb_transfer_raw_read( &transf_write_flash );
  319. flash_address_t WritingSize = usb_count_transfer( &transf_write_flash );
  320. // perform the writing
  321. ExtMemHandle.Write( WritingAddress, pWriteData, WritingSize );
  322. // It is required to return the USB-CORE buffer back.
  323. sUSBTransfer_t * usb_core_rx_transfer = NULL;
  324. // Retrieve the core-transfer object pointer from the @transf_write_flash context value:
  325. if( usb_transfer_get_context( &transf_write_flash, (void**)&usb_core_rx_transfer ) )
  326. {
  327. // Move the memory buffer back to the CORE:
  328. usb_move_transfer( usb_core_rx_transfer, &transf_write_flash, false );
  329. // Reset transfer (optional)
  330. usb_reset_transfer( usb_core_rx_transfer );
  331. }
  332. // Reset the writing flag
  333. fClrWritingFlag();
  334. #if CONFIG_NFMCLASS_AUTOPROTECT_MEMORY
  335. // protect factory data: set memory protection
  336. NFMClass->methods.xMemoryProtection.enable();
  337. #endif
  338. }
  339. }