IAP_YMODEM_STM32F1_ATY.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252
  1. /**
  2. * @file IAP_YMODEM_STM32F1_ATY.c
  3. *
  4. * @param Project DEVICE_GENERAL_ATY_LIB
  5. *
  6. * @author ATY
  7. *
  8. * @copyright
  9. * - Copyright 2017 - 2023 MZ-ATY
  10. * - This code follows:
  11. * - MZ-ATY Various Contents Joint Statement -
  12. * <a href="https://mengze.top/MZ-ATY_VCJS">
  13. * https://mengze.top/MZ-ATY_VCJS</a>
  14. * - CC 4.0 BY-NC-SA -
  15. * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
  16. * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
  17. * - Your use will be deemed to have accepted the terms of this statement.
  18. *
  19. * @brief functions of IAP with YMODEM for STM32F1xx
  20. *
  21. * @version
  22. * - 1_01_240911 > ATY
  23. * -# Preliminary version, first Release
  24. * - 1_02_250701 > ATY
  25. * -# real fix to lib type
  26. * - 1_03_250704 > ATY
  27. * -# finish uart and ucdc IAP whole test
  28. * - 1_04_251016 > ATY
  29. * -# fix large bin 255 limit at 128 and 1K trans in USB CDC
  30. * @todo some IT not restart when jump to app some times
  31. ********************************************************************************
  32. */
  33. #ifndef __IAP_YMODEM_STM32F1_ATY_C
  34. #define __IAP_YMODEM_STM32F1_ATY_C
  35. #include "IAP_YMODEM_STM32F1_ATY.h"
  36. /******************************* For user *************************************/
  37. uint8_t EmptyBuf[1] = {0};
  38. #ifdef IAP_YMODEM_STM32F1_ATY_USB
  39. USBD_CDC_HandleTypeDef* hcdc;
  40. uint32_t ucdcRcvLength = 0;
  41. uint8_t ucdcRcvOverFlag = 1;
  42. uint32_t ucdcRcvLastTime = 0;
  43. uint8_t ucdcRcvBuffer[PACKET_1K_SIZE + PACKET_DATA_INDEX + PACKET_TRAILER_SIZE] = {0};
  44. #endif
  45. void JumpToAppWithReset(void){
  46. // ResetBeforeJumpToApp();
  47. #ifdef IAP_YMODEM_STM32F1_ATY_USB
  48. // Deinitialize USB
  49. USBD_DeInit(&hUsbDeviceFS);
  50. #endif
  51. Bootloader_DeInit();
  52. JumpToApp(APPLICATION_ADDRESS);
  53. }
  54. void Interface_Clean(void){
  55. #ifdef IAP_YMODEM_STM32F1_ATY_USB
  56. #warning "IAP_YMODEM_STM32F1_ATY_USB"
  57. ucdcRcvLength = 0;
  58. ucdcRcvOverFlag = 1;
  59. #else
  60. #warning "NOT IAP_YMODEM_STM32F1_ATY_USB"
  61. __HAL_UART_FLUSH_DRREGISTER(&Interface_UART);
  62. #endif
  63. }
  64. #ifdef IAP_YMODEM_STM32F1_ATY_USB
  65. void PUT_IN_CDC_Receive_FS(uint8_t* Buf, uint32_t* Len){
  66. if(ucdcRcvOverFlag == 1){ // new start
  67. ucdcRcvOverFlag = 0;
  68. ucdcRcvLength = *Len;
  69. memcpy(ucdcRcvBuffer, Buf, *Len);
  70. if(*Len < 64){
  71. ucdcRcvOverFlag = 1;
  72. }
  73. else{
  74. ucdcRcvLastTime = HAL_GetTick();
  75. }
  76. }
  77. else{ // pending to before
  78. memcpy(ucdcRcvBuffer + ucdcRcvLength, Buf, *Len);
  79. ucdcRcvLength += *Len;
  80. if(*Len < 64){
  81. ucdcRcvOverFlag = 1;
  82. }
  83. else{
  84. ucdcRcvLastTime = HAL_GetTick();
  85. }
  86. }
  87. // USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  88. // USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  89. // return (USBD_OK);
  90. }
  91. #endif
  92. uint32_t timeoutCount = 0;
  93. uint32_t timeoutFinal = 100;
  94. HAL_StatusTypeDef Interface_Receive(uint8_t* bytes, uint16_t size, uint32_t timeout){
  95. #ifdef IAP_YMODEM_STM32F1_ATY_USB
  96. hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
  97. if(hcdc->RxLength > APP_RX_DATA_SIZE)
  98. return HAL_ERROR;
  99. timeoutCount = 0;
  100. timeoutFinal = timeout;
  101. while(ucdcRcvLength == 0){
  102. timeoutCount++;
  103. if(timeoutCount > timeoutFinal){
  104. timeoutCount = 0;
  105. USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  106. bytes[0] = 0;
  107. return HAL_TIMEOUT;
  108. }
  109. HAL_Delay(1);
  110. }
  111. if(ucdcRcvOverFlag == 0){
  112. while(HAL_GetTick() - ucdcRcvLastTime < 200){
  113. }
  114. ucdcRcvOverFlag = 1;
  115. }
  116. if(ucdcRcvLength > 0 && ucdcRcvLength <= PACKET_1K_SIZE + PACKET_DATA_INDEX + PACKET_TRAILER_SIZE){
  117. uint16_t copySize = (ucdcRcvLength > size) ? size : ucdcRcvLength;
  118. memcpy(bytes, ucdcRcvBuffer, copySize);
  119. ucdcRcvLength -= copySize;
  120. memcpy(ucdcRcvBuffer, ucdcRcvBuffer + copySize, ucdcRcvLength);
  121. }
  122. return HAL_OK;
  123. #else
  124. HAL_StatusTypeDef state = HAL_UART_Receive(&Interface_UART, bytes, size, timeout);
  125. return state;
  126. // return HAL_UART_Receive(&Interface_UART, bytes, size, timeout);
  127. #endif
  128. }
  129. HAL_StatusTypeDef Interface_Transmit(uint8_t* bytes, uint16_t size, uint32_t timeout){
  130. #ifdef IAP_YMODEM_STM32F1_ATY_USB
  131. Interface_Clean();
  132. ucdcRcvOverFlag = 1;
  133. timeoutCount = 0;
  134. timeoutFinal = timeout;
  135. while(CDC_Transmit_FS(bytes, size) != HAL_OK){
  136. timeoutCount++;
  137. if(timeoutCount > timeoutFinal)
  138. return HAL_TIMEOUT;
  139. HAL_Delay(1);
  140. }
  141. return HAL_OK;
  142. #else
  143. /* May be timeouted... */
  144. if(Interface_UART.gState == HAL_UART_STATE_TIMEOUT){
  145. Interface_UART.gState = HAL_UART_STATE_READY;
  146. }
  147. return HAL_UART_Transmit(&Interface_UART, bytes, size, timeout);
  148. #endif
  149. }
  150. /**
  151. * @brief Display the Main Menu on HyperTerminal
  152. */
  153. void Main_Menu(uint8_t transKey){
  154. uint8_t key = 0;
  155. uint16_t errTimes = 0;
  156. uint32_t FlashProtection = 0;
  157. /* Initialise Flash */
  158. FLASH_If_Init();
  159. /* Test if any sector of Flash memory where user application will be loaded is write protected */
  160. FlashProtection = FLASH_If_GetWriteProtectionStatus();
  161. Interface_PutString("\r\n\r\n=================== Main Menu ============================\r\n\r\n");
  162. Interface_PutString(" Download image to the internal Flash ----------------- 1\r\n\r\n");
  163. Interface_PutString(" Upload image from the internal Flash ----------------- 2\r\n\r\n");
  164. Interface_PutString(" Execute the loaded application ----------------------- 3\r\n\r\n");
  165. if(FlashProtection != FLASHIF_PROTECTION_NONE){
  166. Interface_PutString(" Disable the write protection ------------------------- 4\r\n\r\n");
  167. }
  168. else{
  169. Interface_PutString(" Enable the write protection -------------------------- 4\r\n\r\n");
  170. }
  171. Interface_PutString("==========================================================\r\n\r\n");
  172. while(1){
  173. /* Clean the input path */
  174. Interface_Clean();
  175. if(transKey != 0){
  176. key = transKey;
  177. }
  178. else{
  179. /* Receive key */
  180. Interface_Receive(&key, 1, IAP_3_TIME);
  181. /* Auto jump to app */
  182. if(key == 0)
  183. key = '3';
  184. }
  185. switch(key){
  186. case '*':
  187. /* Upload user application from the Flash */
  188. Interface_Upload();
  189. break;
  190. case '2':
  191. /* Upload user application from the Flash */
  192. Interface_PutString("\r\nAuthorize wrong!\r\n\r\n");
  193. break;
  194. case '1':
  195. /* Download user application in the Flash */
  196. // HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_SET);
  197. if(Interface_Download() != COM_OK)
  198. break;
  199. case '3':
  200. Interface_PutString("\r\nStart program execution...\r\n");
  201. JumpToAppWithReset();
  202. break;
  203. case '4':
  204. if(FlashProtection != FLASHIF_PROTECTION_NONE){
  205. /* Disable the write protection */
  206. if(FLASH_If_WriteProtectionConfig(FLASHIF_WRP_DISABLE) == FLASHIF_OK){
  207. Interface_PutString("Write protection disabled...\r\n");
  208. Interface_PutString("System will now restart...\r\n");
  209. /* Launch the option byte loading */
  210. HAL_FLASH_OB_Launch();
  211. }
  212. else{
  213. Interface_PutString("Error: Flash write un-protection failed...\r\n");
  214. }
  215. }
  216. else{
  217. if(FLASH_If_WriteProtectionConfig(FLASHIF_WRP_ENABLE) == FLASHIF_OK){
  218. Interface_PutString("Write protection enabled...\r\n");
  219. Interface_PutString("System will now restart...\r\n");
  220. /* Launch the option byte loading */
  221. HAL_FLASH_OB_Launch();
  222. }
  223. else{
  224. Interface_PutString("Error: Flash write protection failed...\r\n");
  225. }
  226. }
  227. break;
  228. default:
  229. errTimes++;
  230. if(errTimes > 500){
  231. Interface_PutString("Start program execution for max err...\r\n\r\n");
  232. JumpToAppWithReset();
  233. }
  234. // Interface_PutString("Invalid Number ! ==> The number should be either 1, 2, 3 or 4\r\n");
  235. break;
  236. }
  237. key = 0;
  238. }
  239. }
  240. // do not init usb if not use and connect to others with d+ dan d- pins
  241. #include "rtc.h"
  242. #include "usart.h"
  243. void Main_Cycle(void){
  244. uint8_t sKey[2] = {0};
  245. HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, IAP_VerA);
  246. HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, IAP_VerB);
  247. HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, IAP_VerC);
  248. HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_RESET);
  249. Interface_PutString("\r\n\r\nS to start\r\n\r\n");
  250. if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR6) == __ATY_BL_APP){
  251. HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR6, 0);
  252. JumpToAppWithReset();
  253. }
  254. else if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR6) == __ATY_BL_UPDATE){
  255. HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR6, 0);
  256. MX_USART3_UART_Init();
  257. Main_Menu('1');
  258. }
  259. else{
  260. #ifndef IAP_YMODEM_STM32F1_ATY_USB
  261. HAL_Delay(6000); // for android sereen start
  262. MX_USART3_UART_Init();
  263. #endif
  264. }
  265. Interface_PutString("\r\n\r\nS to start\r\n\r\n");
  266. while(1){
  267. #ifdef IAP_YMODEM_STM32F1_ATY_USB
  268. if(hcdc->RxLength > 1024){
  269. uint8_t t[1] = {0};
  270. Interface_Clean();
  271. Interface_PutByte(0x00);
  272. Interface_Receive(t, 1, 10);
  273. continue;
  274. }
  275. #endif
  276. if(1){
  277. if(Interface_Receive(sKey, 2, IAP_S_TIME) == HAL_OK){
  278. if(sKey[0] == 'S'){
  279. if(sKey[1] == '3'){
  280. Interface_Clean();
  281. Interface_PutString("\r\nStart program execution...\r\n");
  282. JumpToAppWithReset();
  283. }
  284. else if(sKey[1] == '1'){
  285. Interface_Clean();
  286. if(Interface_Download() != COM_OK){
  287. Interface_PutString("\r\nStart program execution...\r\n");
  288. JumpToAppWithReset();
  289. }
  290. }
  291. else{
  292. Interface_Clean();
  293. Main_Menu(0);
  294. }
  295. }
  296. else{
  297. Interface_Clean();
  298. }
  299. }
  300. else{
  301. Interface_Clean();
  302. Main_Menu(0);
  303. }
  304. }
  305. /* Keep the user application running */
  306. else{
  307. JumpToAppWithReset();
  308. }
  309. }
  310. }
  311. /* ****************************************************************************/
  312. /* interface realize **********************************************************/
  313. /**
  314. * @brief Print a string on the HyperTerminal
  315. * @param p_string: The string to be printed
  316. * @retval send state
  317. */
  318. HAL_StatusTypeDef Interface_PutString(uint8_t* p_string){
  319. #ifdef IAP_YMODEM_STM32F1_ATY_DBG
  320. uint16_t length = 0;
  321. while(p_string[length] != '\0'){
  322. length++;
  323. }
  324. return Interface_Transmit(p_string, length, TX_TIMEOUT);
  325. #else
  326. return Interface_Transmit("", 0, TX_TIMEOUT);;
  327. #endif
  328. }
  329. /**
  330. * @brief Transmit a byte to the HyperTerminal
  331. * @param bytes The byte to be sent
  332. * @retval send state
  333. */
  334. HAL_StatusTypeDef Interface_PutByte(uint8_t bytes){
  335. return Interface_Transmit(&bytes, 1, TX_TIMEOUT);
  336. }
  337. /**
  338. * @brief Download a file
  339. * @retval download state
  340. */
  341. COM_StatusTypeDef Interface_Download(void){
  342. uint8_t number[11] = {0};
  343. uint32_t size = 0;
  344. COM_StatusTypeDef result;
  345. Interface_PutString("\r\nWaiting for the file to be sent... (press 'a' to abort)\r\n");
  346. Interface_PutByte(CRC16);
  347. result = Ymodem_Receive(&size);
  348. if(result == COM_OK){
  349. Interface_PutString("\r\n\r\nProgramming Completed Successfully!\n\r--------------------------------\r\n Name: ");
  350. Interface_PutString(aFileName);
  351. Int2Str(number, size);
  352. Interface_PutString("\r\nSize: ");
  353. Interface_PutString(number);
  354. Interface_PutString(" Bytes\r\n");
  355. Interface_PutString("-------------------\r\n");
  356. }
  357. else if(result == COM_LIMIT){
  358. Interface_PutString("\r\nThe image size is higher than the allowed space memory!\n\r");
  359. }
  360. else if(result == COM_DATA){
  361. Interface_PutString("\r\nVerification failed!\n\r");
  362. }
  363. else if(result == COM_ABORT){
  364. Interface_PutString("\r\nAborted by user.\n\r");
  365. }
  366. else{
  367. Interface_PutString("\r\nFailed to receive the file!\r\n");
  368. }
  369. return result;
  370. }
  371. /**
  372. * @brief Upload a file
  373. */
  374. void Interface_Upload(void){
  375. uint8_t status = 0;
  376. Interface_PutString("\r\n\r\nSelect receive file... (press 'a' to abort)\r\n");
  377. while(1){
  378. Interface_Receive(&status, 1, RX_TIMEOUT);
  379. if(status == CRC16){
  380. /* Transmit the flash image through ymodem protocol */
  381. status = Ymodem_Transmit((uint8_t*)APPLICATION_ADDRESS, (const uint8_t*)"UploadedFlashImage.bin", USER_FLASH_SIZE);
  382. if(status != 0){
  383. if(status == COM_ABORT)
  384. Interface_PutString("\r\nAborted by user.\n\r");
  385. else
  386. Interface_PutString("\r\nError occurred while transmitting file\r\n");
  387. }
  388. else{
  389. Interface_PutString("\r\nFile uploaded successfully\r\n");
  390. }
  391. break;
  392. }
  393. else if(status == ABORT1 || status == ABORT2){
  394. Interface_PutString("\r\nAborted by user.\n\r");
  395. break;
  396. }
  397. }
  398. }
  399. /* common *********************************************************************/
  400. /**
  401. * @brief Convert an Integer to a string
  402. * @param p_str: The string output pointer
  403. * @param intnum: The integer to be converted
  404. */
  405. void Int2Str(uint8_t* p_str, uint32_t intnum){
  406. uint32_t i, divider = 1000000000, pos = 0, status = 0;
  407. for(i = 0; i < 10; i++){
  408. p_str[pos++] = (intnum / divider) + 48;
  409. intnum = intnum % divider;
  410. divider /= 10;
  411. if((p_str[pos - 1] == '0') & (status == 0)){
  412. pos = 0;
  413. }
  414. else{
  415. status++;
  416. }
  417. }
  418. }
  419. /**
  420. * @brief Convert a string to an integer
  421. * @param p_inputstr: The string to be converted
  422. * @param p_intnum: The integer value
  423. * @retval 1: Correct
  424. * 0: Error
  425. */
  426. uint32_t Str2Int(uint8_t* p_inputstr, uint32_t* p_intnum){
  427. uint32_t i = 0, res = 0;
  428. uint32_t val = 0;
  429. if((p_inputstr[0] == '0') && ((p_inputstr[1] == 'x') || (p_inputstr[1] == 'X'))){
  430. i = 2;
  431. while((i < 11) && (p_inputstr[i] != '\0')){
  432. if(ISVALIDHEX(p_inputstr[i])){
  433. val = (val << 4) + CONVERTHEX(p_inputstr[i]);
  434. }
  435. else{
  436. /* Return 0, Invalid input */
  437. res = 0;
  438. break;
  439. }
  440. i++;
  441. }
  442. /* valid result */
  443. if(p_inputstr[i] == '\0'){
  444. *p_intnum = val;
  445. res = 1;
  446. }
  447. }
  448. else /* max 10-digit decimal input */
  449. {
  450. while((i < 11) && (res != 1)){
  451. if(p_inputstr[i] == '\0'){
  452. *p_intnum = val;
  453. /* return 1 correct */
  454. res = 1;
  455. }
  456. else if(((p_inputstr[i] == 'k') || (p_inputstr[i] == 'K')) && (i > 0)){
  457. val = val << 10;
  458. *p_intnum = val;
  459. res = 1;
  460. }
  461. else if(((p_inputstr[i] == 'm') || (p_inputstr[i] == 'M')) && (i > 0)){
  462. val = val << 20;
  463. *p_intnum = val;
  464. res = 1;
  465. }
  466. else if(ISVALIDDEC(p_inputstr[i])){
  467. val = val * 10 + CONVERTDEC(p_inputstr[i]);
  468. }
  469. else{
  470. /* return 0, Invalid input */
  471. res = 0;
  472. break;
  473. }
  474. i++;
  475. }
  476. }
  477. return res;
  478. }
  479. /* flash_if *******************************************************************/
  480. /**
  481. * @brief Unlocks Flash for write access
  482. */
  483. void FLASH_If_Init(void){
  484. /* Unlock the Program memory */
  485. HAL_FLASH_Unlock();
  486. /* Clear all FLASH flags */
  487. __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
  488. /* Unlock the Program memory */
  489. HAL_FLASH_Lock();
  490. }
  491. /**
  492. * @brief This function does an erase of all user flash area
  493. * @param start: start of user flash area
  494. * @retval FLASHIF_OK : user flash area successfully erased
  495. * FLASHIF_ERASEKO : error occurred
  496. */
  497. uint32_t FLASH_If_Erase(uint32_t start){
  498. uint32_t NbrOfPages = 0;
  499. uint32_t PageError = 0;
  500. FLASH_EraseInitTypeDef pEraseInit;
  501. HAL_StatusTypeDef status = HAL_OK;
  502. /* Unlock the Flash to enable the flash control register access */
  503. HAL_FLASH_Unlock();
  504. /* Get the sector where start the user flash area */
  505. NbrOfPages = (USER_FLASH_END_ADDRESS - start) / FLASH_PAGE_SIZE;
  506. pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
  507. pEraseInit.PageAddress = start;
  508. pEraseInit.Banks = FLASH_BANK_1;
  509. pEraseInit.NbPages = NbrOfPages;
  510. status = HAL_FLASHEx_Erase(&pEraseInit, &PageError);
  511. /* Lock the Flash to disable the flash control register access (recommended
  512. to protect the FLASH memory against possible unwanted operation) */
  513. HAL_FLASH_Lock();
  514. if(status != HAL_OK){
  515. /* Error occurred while page erase */
  516. return FLASHIF_ERASEKO;
  517. }
  518. return FLASHIF_OK;
  519. }
  520. /**
  521. * @brief This function writes a data buffer in flash (data are 32-bit aligned).
  522. * @note After writing data buffer, the flash content is checked.
  523. * @param destination: start address for target location
  524. * @param p_source: pointer on buffer with data to write
  525. * @param length: length of data buffer (unit is 32-bit word)
  526. * @retval uint32_t 0: Data successfully written to Flash memory
  527. * 1: Error occurred while writing data in Flash memory
  528. * 2: Written Data in flash memory is different from expected one
  529. */
  530. uint32_t FLASH_If_Write(uint32_t destination, uint32_t* p_source, uint32_t length){
  531. uint32_t i = 0;
  532. /* Unlock the Flash to enable the flash control register access */
  533. HAL_FLASH_Unlock();
  534. for(i = 0; (i < length) && (destination <= (USER_FLASH_END_ADDRESS - 4)); i++){
  535. /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
  536. be done by word */
  537. if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, destination, *(uint32_t*)(p_source + i)) == HAL_OK){
  538. /* Check the written value */
  539. if(*(uint32_t*)destination != *(uint32_t*)(p_source + i)){
  540. /* Flash content doesn't match SRAM content */
  541. return(FLASHIF_WRITINGCTRL_ERROR);
  542. }
  543. /* Increment FLASH destination address */
  544. destination += 4;
  545. }
  546. else{
  547. /* Error occurred while writing data in Flash memory */
  548. return (FLASHIF_WRITING_ERROR);
  549. }
  550. }
  551. /* Lock the Flash to disable the flash control register access (recommended
  552. to protect the FLASH memory against possible unwanted operation) */
  553. HAL_FLASH_Lock();
  554. return (FLASHIF_OK);
  555. }
  556. /**
  557. * @brief Returns the write protection status of application flash area.
  558. * @retval If a sector in application area is write-protected returned value is a combinaison
  559. of the possible values : FLASHIF_PROTECTION_WRPENABLED, FLASHIF_PROTECTION_PCROPENABLED, ...
  560. * If no sector is write-protected FLASHIF_PROTECTION_NONE is returned.
  561. */
  562. uint32_t FLASH_If_GetWriteProtectionStatus(void){
  563. uint32_t ProtectedPAGE = FLASHIF_PROTECTION_NONE;
  564. FLASH_OBProgramInitTypeDef OptionsBytesStruct;
  565. /* Unlock the Flash to enable the flash control register access */
  566. HAL_FLASH_Unlock();
  567. /* Check if there are write protected sectors inside the user flash area */
  568. HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
  569. /* Lock the Flash to disable the flash control register access (recommended
  570. to protect the FLASH memory against possible unwanted operation) */
  571. HAL_FLASH_Lock();
  572. /* Get pages already write protected */
  573. ProtectedPAGE = ~(OptionsBytesStruct.WRPPage) & FLASH_PAGE_TO_BE_PROTECTED;
  574. /* Check if desired pages are already write protected */
  575. if(ProtectedPAGE != 0){
  576. /* Some sectors inside the user flash area are write protected */
  577. return FLASHIF_PROTECTION_WRPENABLED;
  578. }
  579. else{
  580. /* No write protected sectors inside the user flash area */
  581. return FLASHIF_PROTECTION_NONE;
  582. }
  583. }
  584. /**
  585. * @brief Configure the write protection status of user flash area.
  586. * @param protectionstate : FLASHIF_WRP_DISABLE or FLASHIF_WRP_ENABLE the protection
  587. * @retval uint32_t FLASHIF_OK if change is applied.
  588. */
  589. uint32_t FLASH_If_WriteProtectionConfig(uint32_t protectionstate){
  590. uint32_t ProtectedPAGE = 0x0;
  591. FLASH_OBProgramInitTypeDef config_new, config_old;
  592. HAL_StatusTypeDef result = HAL_OK;
  593. /* Get pages write protection status */
  594. HAL_FLASHEx_OBGetConfig(&config_old);
  595. /* The parameter says whether we turn the protection on or off */
  596. config_new.WRPState = (protectionstate == FLASHIF_WRP_ENABLE ? OB_WRPSTATE_ENABLE : OB_WRPSTATE_DISABLE);
  597. /* We want to modify only the Write protection */
  598. config_new.OptionType = OPTIONBYTE_WRP;
  599. /* No read protection, keep BOR and reset settings */
  600. config_new.RDPLevel = OB_RDP_LEVEL_0;
  601. config_new.USERConfig = config_old.USERConfig;
  602. /* Get pages already write protected */
  603. ProtectedPAGE = config_old.WRPPage | FLASH_PAGE_TO_BE_PROTECTED;
  604. /* Unlock the Flash to enable the flash control register access */
  605. HAL_FLASH_Unlock();
  606. /* Unlock the Options Bytes */
  607. HAL_FLASH_OB_Unlock();
  608. /* Erase all the option Bytes */
  609. result = HAL_FLASHEx_OBErase();
  610. if(result == HAL_OK){
  611. config_new.WRPPage = ProtectedPAGE;
  612. result = HAL_FLASHEx_OBProgram(&config_new);
  613. }
  614. return (result == HAL_OK ? FLASHIF_OK : FLASHIF_PROTECTION_ERRROR);
  615. }
  616. /* ymodem *********************************************************************/
  617. /* activate the CRC16 integrity */
  618. #define CRC16_F
  619. /* ATTENTION - please keep this variable 32bit alligned */
  620. uint8_t aPacketData[PACKET_1K_SIZE + PACKET_DATA_INDEX + PACKET_TRAILER_SIZE];
  621. uint8_t aFileName[FILE_NAME_LENGTH];
  622. /**
  623. * @brief Receive a packet from sender
  624. * @param data
  625. * @param length
  626. * 0: end of transmission
  627. * 2: abort by sender
  628. * >0: packet length
  629. * @param timeout
  630. * @retval HAL_OK: normally return
  631. * HAL_BUSY: abort by user
  632. */
  633. uint8_t byteOneTmp = 0;
  634. HAL_StatusTypeDef statusA;
  635. static HAL_StatusTypeDef ReceivePacket(uint8_t* p_data, uint32_t* p_length, uint32_t timeout){
  636. uint32_t crc;
  637. uint32_t packet_size = 0;
  638. HAL_StatusTypeDef status;
  639. uint8_t byteOne;
  640. *p_length = 0;
  641. status = Interface_Receive(&byteOne, 1, timeout);
  642. statusA = status;
  643. byteOneTmp = byteOne;
  644. if(status == HAL_OK){
  645. switch(byteOne){
  646. case SOH:
  647. packet_size = PACKET_SIZE;
  648. break;
  649. case STX:
  650. packet_size = PACKET_1K_SIZE;
  651. break;
  652. case EOT:
  653. break;
  654. case CA:
  655. if((Interface_Receive(&byteOne, 1, timeout) == HAL_OK) && (byteOne == CA)){
  656. packet_size = 2;
  657. }
  658. else{
  659. status = HAL_ERROR;
  660. }
  661. break;
  662. case ABORT1:
  663. case ABORT2:
  664. status = HAL_BUSY;
  665. break;
  666. default:
  667. status = HAL_ERROR;
  668. break;
  669. }
  670. *p_data = byteOne;
  671. if(packet_size >= PACKET_SIZE){
  672. status = Interface_Receive(&p_data[PACKET_NUMBER_INDEX], packet_size + PACKET_OVERHEAD_SIZE, timeout);
  673. /* Simple packet sanity check */
  674. if(status == HAL_OK){
  675. if(p_data[PACKET_NUMBER_INDEX] != ((p_data[PACKET_CNUMBER_INDEX]) ^ NEGATIVE_BYTE)){
  676. packet_size = 0;
  677. status = HAL_ERROR;
  678. }
  679. else{
  680. /* Check packet CRC */
  681. crc = p_data[packet_size + PACKET_DATA_INDEX] << 8;
  682. crc += p_data[packet_size + PACKET_DATA_INDEX + 1];
  683. if(Cal_CRC16(&p_data[PACKET_DATA_INDEX], packet_size) != crc){
  684. packet_size = 0;
  685. status = HAL_ERROR;
  686. }
  687. }
  688. }
  689. else{
  690. packet_size = 0;
  691. }
  692. }
  693. }
  694. *p_length = packet_size;
  695. return status;
  696. }
  697. /**
  698. * @brief Prepare the first block
  699. * @param p_data: output buffer
  700. * @param p_file_name: name of the file to be sent
  701. * @param length: length of the file to be sent in bytes
  702. */
  703. static void PrepareIntialPacket(uint8_t* p_data, const uint8_t* p_file_name, uint32_t length){
  704. uint32_t i, j = 0;
  705. uint8_t astring[10];
  706. /* first 3 bytes are constant */
  707. p_data[PACKET_START_INDEX] = SOH;
  708. p_data[PACKET_NUMBER_INDEX] = 0x00;
  709. p_data[PACKET_CNUMBER_INDEX] = 0xff;
  710. /* Filename written */
  711. for(i = 0; (p_file_name[i] != '\0') && (i < FILE_NAME_LENGTH); i++){
  712. p_data[i + PACKET_DATA_INDEX] = p_file_name[i];
  713. }
  714. p_data[i + PACKET_DATA_INDEX] = 0x00;
  715. /* file size written */
  716. Int2Str(astring, length);
  717. i = i + PACKET_DATA_INDEX + 1;
  718. while(astring[j] != '\0'){
  719. p_data[i++] = astring[j++];
  720. }
  721. /* padding with zeros */
  722. for(j = i; j < PACKET_SIZE + PACKET_DATA_INDEX; j++){
  723. p_data[j] = 0;
  724. }
  725. }
  726. /**
  727. * @brief Prepare the data packet
  728. * @param p_source: pointer to the data to be sent
  729. * @param p_packet: pointer to the output buffer
  730. * @param pkt_nr: number of the packet
  731. * @param size_blk: length of the block to be sent in bytes
  732. */
  733. static void PreparePacket(uint8_t* p_source, uint8_t* p_packet, uint8_t pkt_nr, uint32_t size_blk){
  734. uint8_t* p_record;
  735. uint32_t i, size, packet_size;
  736. /* Make first three packet */
  737. packet_size = size_blk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
  738. size = size_blk < packet_size ? size_blk : packet_size;
  739. if(packet_size == PACKET_1K_SIZE){
  740. p_packet[PACKET_START_INDEX] = STX;
  741. }
  742. else{
  743. p_packet[PACKET_START_INDEX] = SOH;
  744. }
  745. p_packet[PACKET_NUMBER_INDEX] = pkt_nr;
  746. p_packet[PACKET_CNUMBER_INDEX] = (~pkt_nr);
  747. p_record = p_source;
  748. /* Filename packet has valid data */
  749. for(i = PACKET_DATA_INDEX; i < size + PACKET_DATA_INDEX; i++){
  750. p_packet[i] = *p_record++;
  751. }
  752. if(size <= packet_size){
  753. for(i = size + PACKET_DATA_INDEX; i < packet_size + PACKET_DATA_INDEX; i++){
  754. p_packet[i] = 0x1A; /* EOF (0x1A) or 0x00 */
  755. }
  756. }
  757. }
  758. /**
  759. * @brief Update CRC16 for input byte
  760. * @param crc_in input value
  761. * @param input byte
  762. */
  763. uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte){
  764. uint32_t crc = crc_in;
  765. uint32_t in = byte | 0x100;
  766. do{
  767. crc <<= 1;
  768. in <<= 1;
  769. if(in & 0x100)
  770. ++crc;
  771. if(crc & 0x10000)
  772. crc ^= 0x1021;
  773. }
  774. while(!(in & 0x10000));
  775. return crc & 0xffffu;
  776. }
  777. /**
  778. * @brief Cal CRC16 for YModem Packet
  779. * @param data
  780. * @param length
  781. */
  782. uint16_t Cal_CRC16(const uint8_t* p_data, uint32_t size){
  783. uint32_t crc = 0;
  784. const uint8_t* dataEnd = p_data + size;
  785. while(p_data < dataEnd)
  786. crc = UpdateCRC16(crc, *p_data++);
  787. crc = UpdateCRC16(crc, 0);
  788. crc = UpdateCRC16(crc, 0);
  789. return crc & 0xffffu;
  790. }
  791. /**
  792. * @brief Calculate Check sum for YModem Packet
  793. * @param p_data Pointer to input data
  794. * @param size length of input data
  795. * @retval uint8_t checksum value
  796. */
  797. uint8_t CalcChecksum(const uint8_t* p_data, uint32_t size){
  798. uint32_t sum = 0;
  799. const uint8_t* p_data_end = p_data + size;
  800. while(p_data < p_data_end){
  801. sum += *p_data++;
  802. }
  803. return (sum & 0xffu);
  804. }
  805. /* Public functions ---------------------------------------------------------*/
  806. /**
  807. * @brief Receive a file using the ymodem protocol with CRC16.
  808. * @param p_size The size of the file.
  809. * @retval COM_StatusTypeDef result of reception/programming
  810. */
  811. HAL_StatusTypeDef statA = HAL_OK;
  812. uint16_t packets_received;
  813. COM_StatusTypeDef Ymodem_Receive(uint32_t* p_size){
  814. uint32_t i, packet_length, session_done = 0, file_done, errors = 0, session_begin = 0;
  815. uint32_t flashdestination, ramsource, filesize;
  816. uint8_t* file_ptr;
  817. uint8_t file_size[FILE_SIZE_LENGTH], tmp;
  818. COM_StatusTypeDef result = COM_OK;
  819. uint8_t tryTimes = 0;
  820. /* Initialize flashdestination variable */
  821. flashdestination = APPLICATION_ADDRESS;
  822. while((session_done == 0) && (result == COM_OK)){
  823. packets_received = 0;
  824. file_done = 0;
  825. while((file_done == 0) && (result == COM_OK)){
  826. statA = ReceivePacket(aPacketData, &packet_length, DOWNLOAD_TIMEOUT);
  827. switch(statA){
  828. case HAL_OK:
  829. HAL_GPIO_TogglePin(SYSLED_GPIO_Port, SYSLED_Pin);
  830. errors = 0;
  831. switch(packet_length){
  832. case 2:
  833. /* Abort by sender */
  834. Interface_PutByte(ACK);
  835. result = COM_ABORT;
  836. return result;
  837. case 0:
  838. /* End of transmission */
  839. Interface_PutByte(ACK);
  840. file_done = 1;
  841. break;
  842. default:
  843. /* Normal packet */
  844. if(aPacketData[PACKET_NUMBER_INDEX] != (packets_received % 256)){
  845. Interface_PutByte(NAK);
  846. }
  847. else{
  848. if(packets_received == 0){
  849. /* File name packet */
  850. if(aPacketData[PACKET_DATA_INDEX] != 0){
  851. /* File name extraction */
  852. i = 0;
  853. file_ptr = aPacketData + PACKET_DATA_INDEX;
  854. while((*file_ptr != 0) && (i < FILE_NAME_LENGTH)){
  855. aFileName[i++] = *file_ptr++;
  856. }
  857. /* File size extraction */
  858. aFileName[i++] = '\0';
  859. i = 0;
  860. file_ptr++;
  861. while((*file_ptr != ' ') && (i < FILE_SIZE_LENGTH)){
  862. file_size[i++] = *file_ptr++;
  863. }
  864. file_size[i++] = '\0';
  865. Str2Int(file_size, &filesize);
  866. /* Test the size of the image to be sent */
  867. /* Image size is greater than Flash size */
  868. if(*p_size > (USER_FLASH_SIZE + 1)){
  869. /* End session */
  870. tmp = CA;
  871. Interface_Transmit(&tmp, 1, NAK_TIMEOUT);
  872. Interface_Transmit(&tmp, 1, NAK_TIMEOUT);
  873. result = COM_LIMIT;
  874. }
  875. /* Erase user application area */
  876. FLASH_If_Erase(APPLICATION_ADDRESS);
  877. *p_size = filesize;
  878. Interface_PutByte(ACK);
  879. Interface_PutByte(CRC16);
  880. }
  881. /* File header packet is empty, end session */
  882. else{
  883. Interface_PutByte(ACK);
  884. file_done = 1;
  885. session_done = 1;
  886. break;
  887. }
  888. }
  889. else /* Data packet */
  890. {
  891. ramsource = (uint32_t)&aPacketData[PACKET_DATA_INDEX];
  892. /* Write received data in Flash */
  893. if(FLASH_If_Write(flashdestination, (uint32_t*)ramsource, packet_length / 4) == FLASHIF_OK){
  894. flashdestination += packet_length;
  895. Interface_PutByte(ACK);
  896. }
  897. else /* An error occurred while writing to Flash memory */
  898. {
  899. /* End session */
  900. Interface_PutByte(CA);
  901. Interface_PutByte(CA);
  902. result = COM_DATA;
  903. }
  904. }
  905. packets_received++;
  906. session_begin = 1;
  907. }
  908. break;
  909. }
  910. break;
  911. case HAL_BUSY: /* Abort actually */
  912. Interface_PutByte(CA);
  913. Interface_PutByte(CA);
  914. result = COM_ABORT;
  915. break;
  916. default:
  917. if(session_begin > 0){
  918. errors++;
  919. }
  920. if(errors > MAX_ERRORS){
  921. /* Abort communication */
  922. Interface_PutByte(CA);
  923. Interface_PutByte(CA);
  924. }
  925. else{
  926. tryTimes++;
  927. if(tryTimes > 10){
  928. Interface_PutByte(ACK);
  929. result = COM_ABORT;
  930. return result;
  931. }
  932. /* Ask for a packet */
  933. Interface_PutByte(CRC16);
  934. HAL_GPIO_TogglePin(SYSLED_GPIO_Port, SYSLED_Pin);
  935. }
  936. break;
  937. }
  938. }
  939. }
  940. return result;
  941. }
  942. /**
  943. * @brief Transmit a file using the ymodem protocol
  944. * @param p_buf: Address of the first byte
  945. * @param p_file_name: Name of the file sent
  946. * @param file_size: Size of the transmission
  947. * @retval COM_StatusTypeDef result of the communication
  948. */
  949. COM_StatusTypeDef Ymodem_Transmit(uint8_t* p_buf, const uint8_t* p_file_name, uint32_t file_size){
  950. uint32_t errors = 0, ack_recpt = 0, size = 0, pkt_size;
  951. uint8_t* p_buf_int;
  952. COM_StatusTypeDef result = COM_OK;
  953. uint32_t blk_number = 1;
  954. uint8_t a_rx_ctrl[2];
  955. uint8_t i;
  956. #ifdef CRC16_F
  957. uint32_t temp_crc;
  958. #else /* CRC16_F */
  959. uint8_t temp_chksum;
  960. #endif /* CRC16_F */
  961. /* Prepare first block - header */
  962. PrepareIntialPacket(aPacketData, p_file_name, file_size);
  963. while((!ack_recpt) && (result == COM_OK)){
  964. /* Send Packet */
  965. Interface_Transmit(&aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);
  966. /* Send CRC or Check Sum based on CRC16_F */
  967. #ifdef CRC16_F
  968. temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  969. Interface_PutByte(temp_crc >> 8);
  970. Interface_PutByte(temp_crc & 0xFF);
  971. #else /* CRC16_F */
  972. temp_chksum = CalcChecksum(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  973. Interface_PutByte(temp_chksum);
  974. #endif /* CRC16_F */
  975. /* Wait for Ack and 'C' */
  976. if(Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK){
  977. if(a_rx_ctrl[0] == ACK){
  978. ack_recpt = 1;
  979. }
  980. else if(a_rx_ctrl[0] == CA){
  981. if((Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA)){
  982. HAL_Delay(2);
  983. Interface_Clean();
  984. result = COM_ABORT;
  985. }
  986. }
  987. else if(a_rx_ctrl[0] == ABORT1 || a_rx_ctrl[0] == ABORT2){
  988. result = COM_ABORT;
  989. }
  990. }
  991. else{
  992. errors++;
  993. }
  994. if(errors >= MAX_ERRORS){
  995. result = COM_ERROR;
  996. }
  997. }
  998. p_buf_int = p_buf;
  999. size = file_size;
  1000. /* Here 1024 bytes length is used to send the packets */
  1001. while((size) && (result == COM_OK)){
  1002. /* Prepare next packet */
  1003. PreparePacket(p_buf_int, aPacketData, blk_number, size);
  1004. ack_recpt = 0;
  1005. a_rx_ctrl[0] = 0;
  1006. errors = 0;
  1007. /* Resend packet if NAK for few times else end of communication */
  1008. while((!ack_recpt) && (result == COM_OK)){
  1009. /* Send next packet */
  1010. if(size >= PACKET_1K_SIZE){
  1011. pkt_size = PACKET_1K_SIZE;
  1012. }
  1013. else{
  1014. pkt_size = PACKET_SIZE;
  1015. }
  1016. Interface_Transmit(&aPacketData[PACKET_START_INDEX], pkt_size + PACKET_HEADER_SIZE, NAK_TIMEOUT);
  1017. /* Send CRC or Check Sum based on CRC16_F */
  1018. #ifdef CRC16_F
  1019. temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], pkt_size);
  1020. Interface_PutByte(temp_crc >> 8);
  1021. Interface_PutByte(temp_crc & 0xFF);
  1022. #else /* CRC16_F */
  1023. temp_chksum = CalcChecksum(&aPacketData[PACKET_DATA_INDEX], pkt_size);
  1024. Interface_PutByte(temp_chksum);
  1025. #endif /* CRC16_F */
  1026. /* Wait for Ack */
  1027. if((Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == ACK)){
  1028. ack_recpt = 1;
  1029. if(size > pkt_size){
  1030. p_buf_int += pkt_size;
  1031. size -= pkt_size;
  1032. if(blk_number == (USER_FLASH_SIZE / PACKET_1K_SIZE)){
  1033. result = COM_LIMIT; /* boundary error */
  1034. }
  1035. else{
  1036. blk_number++;
  1037. }
  1038. }
  1039. else{
  1040. p_buf_int += pkt_size;
  1041. size = 0;
  1042. }
  1043. }
  1044. else{
  1045. errors++;
  1046. }
  1047. /* Resend packet if NAK for a count of 10 else end of communication */
  1048. if(errors >= MAX_ERRORS){
  1049. result = COM_ERROR;
  1050. }
  1051. }
  1052. }
  1053. /* Sending End Of Transmission char */
  1054. ack_recpt = 0;
  1055. a_rx_ctrl[0] = 0x00;
  1056. errors = 0;
  1057. while((!ack_recpt) && (result == COM_OK)){
  1058. Interface_PutByte(EOT);
  1059. /* Wait for Ack */
  1060. if(Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK){
  1061. if(a_rx_ctrl[0] == ACK){
  1062. ack_recpt = 1;
  1063. }
  1064. else if(a_rx_ctrl[0] == CA){
  1065. if((Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA)){
  1066. HAL_Delay(2);
  1067. Interface_Clean();
  1068. result = COM_ABORT;
  1069. }
  1070. }
  1071. }
  1072. else{
  1073. errors++;
  1074. }
  1075. if(errors >= MAX_ERRORS){
  1076. result = COM_ERROR;
  1077. }
  1078. }
  1079. /* Empty packet sent - some terminal emulators need this to close session */
  1080. if(result == COM_OK){
  1081. /* Preparing an empty packet */
  1082. aPacketData[PACKET_START_INDEX] = SOH;
  1083. aPacketData[PACKET_NUMBER_INDEX] = 0;
  1084. aPacketData[PACKET_CNUMBER_INDEX] = 0xFF;
  1085. for(i = PACKET_DATA_INDEX; i < (PACKET_SIZE + PACKET_DATA_INDEX); i++){
  1086. aPacketData[i] = 0x00;
  1087. }
  1088. /* Send Packet */
  1089. Interface_Transmit(&aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);
  1090. /* Send CRC or Check Sum based on CRC16_F */
  1091. #ifdef CRC16_F
  1092. temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  1093. Interface_PutByte(temp_crc >> 8);
  1094. Interface_PutByte(temp_crc & 0xFF);
  1095. #else /* CRC16_F */
  1096. temp_chksum = CalcChecksum(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  1097. Interface_PutByte(temp_chksum);
  1098. #endif /* CRC16_F */
  1099. /* Wait for Ack and 'C' */
  1100. if(Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK){
  1101. if(a_rx_ctrl[0] == CA){
  1102. HAL_Delay(2);
  1103. Interface_Clean();
  1104. result = COM_ABORT;
  1105. }
  1106. }
  1107. }
  1108. return result; /* File transmitted successfully */
  1109. }
  1110. #endif /* __IAP_YMODEM_STM32F1_ATY_C */
  1111. /******************************** End Of File *********************************/