IAP_YMODEM_ATY.c 41 KB

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