IAP_YMODEM_ATY.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366
  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. void Main_Cycle(void)
  270. {
  271. uint8_t sKey[2] = {0};
  272. Interface_PutString("\r\n\r\nS to start\r\n\r\n");
  273. while(1)
  274. {
  275. #ifdef IAP_YMODEM_ATY_USB
  276. if(hcdc->RxLength > 1024){
  277. uint8_t t[1] = {0};
  278. Interface_Receive(t, 1, 10);
  279. continue;
  280. }
  281. #endif
  282. if(1)
  283. {
  284. if(Interface_Receive(sKey, 2, IAP_S_TIME) == HAL_OK)
  285. {
  286. if(sKey[0] == 'S')
  287. {
  288. uint8_t verStr[] = "BLA_V_1_01_250705\r\n";
  289. Interface_Transmit(verStr, sizeof(verStr), 100);
  290. if(sKey[1] == '3'){
  291. Interface_Clean();
  292. Interface_PutString("\r\nStart program execution...\r\n");
  293. JumpToAppWithReset();
  294. }
  295. else if(sKey[1] == '1'){
  296. Interface_Clean();
  297. if(Interface_Download() != COM_OK){
  298. Interface_PutString("\r\nStart program execution...\r\n");
  299. JumpToAppWithReset();
  300. }
  301. }
  302. else{
  303. Interface_Clean();
  304. Main_Menu();
  305. }
  306. }
  307. else{
  308. Interface_Clean();
  309. }
  310. }
  311. else{
  312. Interface_Clean();
  313. Main_Menu();
  314. }
  315. }
  316. /* Keep the user application running */
  317. else
  318. {
  319. JumpToAppWithReset();
  320. }
  321. }
  322. }
  323. /* ****************************************************************************/
  324. /* interface realize **********************************************************/
  325. /**
  326. * @brief Print a string on the HyperTerminal
  327. * @param p_string: The string to be printed
  328. * @retval send state
  329. */
  330. HAL_StatusTypeDef Interface_PutString(uint8_t* p_string)
  331. {
  332. #ifdef IAP_YMODEM_ATY_DBG
  333. uint16_t length = 0;
  334. while(p_string[length] != '\0')
  335. {
  336. length++;
  337. }
  338. return Interface_Transmit(p_string, length, TX_TIMEOUT);
  339. #else
  340. return Interface_Transmit("", 0, TX_TIMEOUT);;
  341. #endif
  342. }
  343. /**
  344. * @brief Transmit a byte to the HyperTerminal
  345. * @param bytes The byte to be sent
  346. * @retval send state
  347. */
  348. HAL_StatusTypeDef Interface_PutByte(uint8_t bytes)
  349. {
  350. return Interface_Transmit(&bytes, 1, TX_TIMEOUT);
  351. }
  352. /**
  353. * @brief Download a file
  354. * @retval download state
  355. */
  356. COM_StatusTypeDef Interface_Download(void)
  357. {
  358. uint8_t number[11] = {0};
  359. uint32_t size = 0;
  360. COM_StatusTypeDef result;
  361. Interface_PutString("\r\nWaiting for the file to be sent... (press 'a' to abort)\r\n");
  362. result = Ymodem_Receive(&size);
  363. if(result == COM_OK)
  364. {
  365. Interface_PutString("\r\n\r\nProgramming Completed Successfully!\n\r--------------------------------\r\n Name: ");
  366. Interface_PutString(aFileName);
  367. Int2Str(number, size);
  368. Interface_PutString("\r\nSize: ");
  369. Interface_PutString(number);
  370. Interface_PutString(" Bytes\r\n");
  371. Interface_PutString("-------------------\r\n");
  372. }
  373. else if(result == COM_LIMIT)
  374. {
  375. Interface_PutString("\r\nThe image size is higher than the allowed space memory!\n\r");
  376. }
  377. else if(result == COM_DATA)
  378. {
  379. Interface_PutString("\r\nVerification failed!\n\r");
  380. }
  381. else if(result == COM_ABORT)
  382. {
  383. Interface_PutString("\r\nAborted by user.\n\r");
  384. }
  385. else
  386. {
  387. Interface_PutString("\r\nFailed to receive the file!\r\n");
  388. }
  389. return result;
  390. }
  391. /**
  392. * @brief Upload a file
  393. */
  394. void Interface_Upload(void)
  395. {
  396. uint8_t status = 0;
  397. Interface_PutString("\r\n\r\nSelect receive file... (press 'a' to abort)\r\n");
  398. while(1)
  399. {
  400. Interface_Receive(&status, 1, RX_TIMEOUT);
  401. if(status == CRC16)
  402. {
  403. /* Transmit the flash image through ymodem protocol */
  404. status = Ymodem_Transmit((uint8_t*)APPLICATION_ADDRESS, (const uint8_t*)"UploadedFlashImage.bin", USER_FLASH_SIZE);
  405. if(status != 0)
  406. {
  407. if(status == COM_ABORT)
  408. Interface_PutString("\r\nAborted by user.\n\r");
  409. else
  410. Interface_PutString("\r\nError occurred while transmitting file\r\n");
  411. }
  412. else
  413. {
  414. Interface_PutString("\r\nFile uploaded successfully\r\n");
  415. }
  416. break;
  417. }
  418. else if(status == ABORT1 || status == ABORT2)
  419. {
  420. Interface_PutString("\r\nAborted by user.\n\r");
  421. break;
  422. }
  423. }
  424. }
  425. /* common *********************************************************************/
  426. /**
  427. * @brief Convert an Integer to a string
  428. * @param p_str: The string output pointer
  429. * @param intnum: The integer to be converted
  430. */
  431. void Int2Str(uint8_t* p_str, uint32_t intnum)
  432. {
  433. uint32_t i, divider = 1000000000, pos = 0, status = 0;
  434. for(i = 0; i < 10; i++)
  435. {
  436. p_str[pos++] = (intnum / divider) + 48;
  437. intnum = intnum % divider;
  438. divider /= 10;
  439. if((p_str[pos - 1] == '0') & (status == 0))
  440. {
  441. pos = 0;
  442. }
  443. else
  444. {
  445. status++;
  446. }
  447. }
  448. }
  449. /**
  450. * @brief Convert a string to an integer
  451. * @param p_inputstr: The string to be converted
  452. * @param p_intnum: The integer value
  453. * @retval 1: Correct
  454. * 0: Error
  455. */
  456. uint32_t Str2Int(uint8_t* p_inputstr, uint32_t* p_intnum)
  457. {
  458. uint32_t i = 0, res = 0;
  459. uint32_t val = 0;
  460. if((p_inputstr[0] == '0') && ((p_inputstr[1] == 'x') || (p_inputstr[1] == 'X')))
  461. {
  462. i = 2;
  463. while((i < 11) && (p_inputstr[i] != '\0'))
  464. {
  465. if(ISVALIDHEX(p_inputstr[i]))
  466. {
  467. val = (val << 4) + CONVERTHEX(p_inputstr[i]);
  468. }
  469. else
  470. {
  471. /* Return 0, Invalid input */
  472. res = 0;
  473. break;
  474. }
  475. i++;
  476. }
  477. /* valid result */
  478. if(p_inputstr[i] == '\0')
  479. {
  480. *p_intnum = val;
  481. res = 1;
  482. }
  483. }
  484. else /* max 10-digit decimal input */
  485. {
  486. while((i < 11) && (res != 1))
  487. {
  488. if(p_inputstr[i] == '\0')
  489. {
  490. *p_intnum = val;
  491. /* return 1 correct */
  492. res = 1;
  493. }
  494. else if(((p_inputstr[i] == 'k') || (p_inputstr[i] == 'K')) && (i > 0))
  495. {
  496. val = val << 10;
  497. *p_intnum = val;
  498. res = 1;
  499. }
  500. else if(((p_inputstr[i] == 'm') || (p_inputstr[i] == 'M')) && (i > 0))
  501. {
  502. val = val << 20;
  503. *p_intnum = val;
  504. res = 1;
  505. }
  506. else if(ISVALIDDEC(p_inputstr[i]))
  507. {
  508. val = val * 10 + CONVERTDEC(p_inputstr[i]);
  509. }
  510. else
  511. {
  512. /* return 0, Invalid input */
  513. res = 0;
  514. break;
  515. }
  516. i++;
  517. }
  518. }
  519. return res;
  520. }
  521. /* flash_if *******************************************************************/
  522. /**
  523. * @brief Unlocks Flash for write access
  524. */
  525. void FLASH_If_Init(void)
  526. {
  527. /* Unlock the Program memory */
  528. HAL_FLASH_Unlock();
  529. /* Clear all FLASH flags */
  530. __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
  531. /* Unlock the Program memory */
  532. HAL_FLASH_Lock();
  533. }
  534. /**
  535. * @brief This function does an erase of all user flash area
  536. * @param start: start of user flash area
  537. * @retval FLASHIF_OK : user flash area successfully erased
  538. * FLASHIF_ERASEKO : error occurred
  539. */
  540. uint32_t FLASH_If_Erase(uint32_t start)
  541. {
  542. uint32_t NbrOfPages = 0;
  543. uint32_t PageError = 0;
  544. FLASH_EraseInitTypeDef pEraseInit;
  545. HAL_StatusTypeDef status = HAL_OK;
  546. /* Unlock the Flash to enable the flash control register access */
  547. HAL_FLASH_Unlock();
  548. /* Get the sector where start the user flash area */
  549. NbrOfPages = (USER_FLASH_END_ADDRESS - start) / FLASH_PAGE_SIZE;
  550. pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
  551. pEraseInit.PageAddress = start;
  552. pEraseInit.Banks = FLASH_BANK_1;
  553. pEraseInit.NbPages = NbrOfPages;
  554. status = HAL_FLASHEx_Erase(&pEraseInit, &PageError);
  555. /* Lock the Flash to disable the flash control register access (recommended
  556. to protect the FLASH memory against possible unwanted operation) */
  557. HAL_FLASH_Lock();
  558. if(status != HAL_OK)
  559. {
  560. /* Error occurred while page erase */
  561. return FLASHIF_ERASEKO;
  562. }
  563. return FLASHIF_OK;
  564. }
  565. /**
  566. * @brief This function writes a data buffer in flash (data are 32-bit aligned).
  567. * @note After writing data buffer, the flash content is checked.
  568. * @param destination: start address for target location
  569. * @param p_source: pointer on buffer with data to write
  570. * @param length: length of data buffer (unit is 32-bit word)
  571. * @retval uint32_t 0: Data successfully written to Flash memory
  572. * 1: Error occurred while writing data in Flash memory
  573. * 2: Written Data in flash memory is different from expected one
  574. */
  575. uint32_t FLASH_If_Write(uint32_t destination, uint32_t* p_source, uint32_t length)
  576. {
  577. uint32_t i = 0;
  578. /* Unlock the Flash to enable the flash control register access */
  579. HAL_FLASH_Unlock();
  580. for(i = 0; (i < length) && (destination <= (USER_FLASH_END_ADDRESS - 4)); i++)
  581. {
  582. /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
  583. be done by word */
  584. if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, destination, *(uint32_t*)(p_source + i)) == HAL_OK)
  585. {
  586. /* Check the written value */
  587. if(*(uint32_t*)destination != *(uint32_t*)(p_source + i))
  588. {
  589. /* Flash content doesn't match SRAM content */
  590. return(FLASHIF_WRITINGCTRL_ERROR);
  591. }
  592. /* Increment FLASH destination address */
  593. destination += 4;
  594. }
  595. else
  596. {
  597. /* Error occurred while writing data in Flash memory */
  598. return (FLASHIF_WRITING_ERROR);
  599. }
  600. }
  601. /* Lock the Flash to disable the flash control register access (recommended
  602. to protect the FLASH memory against possible unwanted operation) */
  603. HAL_FLASH_Lock();
  604. return (FLASHIF_OK);
  605. }
  606. /**
  607. * @brief Returns the write protection status of application flash area.
  608. * @retval If a sector in application area is write-protected returned value is a combinaison
  609. of the possible values : FLASHIF_PROTECTION_WRPENABLED, FLASHIF_PROTECTION_PCROPENABLED, ...
  610. * If no sector is write-protected FLASHIF_PROTECTION_NONE is returned.
  611. */
  612. uint32_t FLASH_If_GetWriteProtectionStatus(void)
  613. {
  614. uint32_t ProtectedPAGE = FLASHIF_PROTECTION_NONE;
  615. FLASH_OBProgramInitTypeDef OptionsBytesStruct;
  616. /* Unlock the Flash to enable the flash control register access */
  617. HAL_FLASH_Unlock();
  618. /* Check if there are write protected sectors inside the user flash area */
  619. HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
  620. /* Lock the Flash to disable the flash control register access (recommended
  621. to protect the FLASH memory against possible unwanted operation) */
  622. HAL_FLASH_Lock();
  623. /* Get pages already write protected */
  624. ProtectedPAGE = ~(OptionsBytesStruct.WRPPage) & FLASH_PAGE_TO_BE_PROTECTED;
  625. /* Check if desired pages are already write protected */
  626. if(ProtectedPAGE != 0)
  627. {
  628. /* Some sectors inside the user flash area are write protected */
  629. return FLASHIF_PROTECTION_WRPENABLED;
  630. }
  631. else
  632. {
  633. /* No write protected sectors inside the user flash area */
  634. return FLASHIF_PROTECTION_NONE;
  635. }
  636. }
  637. /**
  638. * @brief Configure the write protection status of user flash area.
  639. * @param protectionstate : FLASHIF_WRP_DISABLE or FLASHIF_WRP_ENABLE the protection
  640. * @retval uint32_t FLASHIF_OK if change is applied.
  641. */
  642. uint32_t FLASH_If_WriteProtectionConfig(uint32_t protectionstate)
  643. {
  644. uint32_t ProtectedPAGE = 0x0;
  645. FLASH_OBProgramInitTypeDef config_new, config_old;
  646. HAL_StatusTypeDef result = HAL_OK;
  647. /* Get pages write protection status */
  648. HAL_FLASHEx_OBGetConfig(&config_old);
  649. /* The parameter says whether we turn the protection on or off */
  650. config_new.WRPState = (protectionstate == FLASHIF_WRP_ENABLE ? OB_WRPSTATE_ENABLE : OB_WRPSTATE_DISABLE);
  651. /* We want to modify only the Write protection */
  652. config_new.OptionType = OPTIONBYTE_WRP;
  653. /* No read protection, keep BOR and reset settings */
  654. config_new.RDPLevel = OB_RDP_LEVEL_0;
  655. config_new.USERConfig = config_old.USERConfig;
  656. /* Get pages already write protected */
  657. ProtectedPAGE = config_old.WRPPage | FLASH_PAGE_TO_BE_PROTECTED;
  658. /* Unlock the Flash to enable the flash control register access */
  659. HAL_FLASH_Unlock();
  660. /* Unlock the Options Bytes */
  661. HAL_FLASH_OB_Unlock();
  662. /* Erase all the option Bytes */
  663. result = HAL_FLASHEx_OBErase();
  664. if(result == HAL_OK)
  665. {
  666. config_new.WRPPage = ProtectedPAGE;
  667. result = HAL_FLASHEx_OBProgram(&config_new);
  668. }
  669. return (result == HAL_OK ? FLASHIF_OK : FLASHIF_PROTECTION_ERRROR);
  670. }
  671. /* ymodem *********************************************************************/
  672. /* activate the CRC16 integrity */
  673. #define CRC16_F
  674. /* ATTENTION - please keep this variable 32bit alligned */
  675. uint8_t aPacketData[PACKET_1K_SIZE + PACKET_DATA_INDEX + PACKET_TRAILER_SIZE];
  676. uint8_t aFileName[FILE_NAME_LENGTH];
  677. /**
  678. * @brief Receive a packet from sender
  679. * @param data
  680. * @param length
  681. * 0: end of transmission
  682. * 2: abort by sender
  683. * >0: packet length
  684. * @param timeout
  685. * @retval HAL_OK: normally return
  686. * HAL_BUSY: abort by user
  687. */
  688. static HAL_StatusTypeDef ReceivePacket(uint8_t* p_data, uint32_t* p_length, uint32_t timeout)
  689. {
  690. uint32_t crc;
  691. uint32_t packet_size = 0;
  692. HAL_StatusTypeDef status;
  693. uint8_t byteOne;
  694. *p_length = 0;
  695. status = Interface_Receive(&byteOne, 1, timeout);
  696. if(status == HAL_OK)
  697. {
  698. switch(byteOne)
  699. {
  700. case SOH:
  701. packet_size = PACKET_SIZE;
  702. break;
  703. case STX:
  704. packet_size = PACKET_1K_SIZE;
  705. break;
  706. case EOT:
  707. break;
  708. case CA:
  709. if((Interface_Receive(&byteOne, 1, timeout) == HAL_OK) && (byteOne == CA))
  710. {
  711. packet_size = 2;
  712. }
  713. else
  714. {
  715. status = HAL_ERROR;
  716. }
  717. break;
  718. case ABORT1:
  719. case ABORT2:
  720. status = HAL_BUSY;
  721. break;
  722. default:
  723. status = HAL_ERROR;
  724. break;
  725. }
  726. *p_data = byteOne;
  727. if(packet_size >= PACKET_SIZE)
  728. {
  729. status = Interface_Receive(&p_data[PACKET_NUMBER_INDEX], packet_size + PACKET_OVERHEAD_SIZE, timeout);
  730. /* Simple packet sanity check */
  731. if(status == HAL_OK)
  732. {
  733. if(p_data[PACKET_NUMBER_INDEX] != ((p_data[PACKET_CNUMBER_INDEX]) ^ NEGATIVE_BYTE))
  734. {
  735. packet_size = 0;
  736. status = HAL_ERROR;
  737. }
  738. else
  739. {
  740. /* Check packet CRC */
  741. crc = p_data[packet_size + PACKET_DATA_INDEX] << 8;
  742. crc += p_data[packet_size + PACKET_DATA_INDEX + 1];
  743. if(Cal_CRC16(&p_data[PACKET_DATA_INDEX], packet_size) != crc)
  744. {
  745. packet_size = 0;
  746. status = HAL_ERROR;
  747. }
  748. }
  749. }
  750. else
  751. {
  752. packet_size = 0;
  753. }
  754. }
  755. }
  756. *p_length = packet_size;
  757. return status;
  758. }
  759. /**
  760. * @brief Prepare the first block
  761. * @param p_data: output buffer
  762. * @param p_file_name: name of the file to be sent
  763. * @param length: length of the file to be sent in bytes
  764. */
  765. static void PrepareIntialPacket(uint8_t* p_data, const uint8_t* p_file_name, uint32_t length)
  766. {
  767. uint32_t i, j = 0;
  768. uint8_t astring[10];
  769. /* first 3 bytes are constant */
  770. p_data[PACKET_START_INDEX] = SOH;
  771. p_data[PACKET_NUMBER_INDEX] = 0x00;
  772. p_data[PACKET_CNUMBER_INDEX] = 0xff;
  773. /* Filename written */
  774. for(i = 0; (p_file_name[i] != '\0') && (i < FILE_NAME_LENGTH); i++)
  775. {
  776. p_data[i + PACKET_DATA_INDEX] = p_file_name[i];
  777. }
  778. p_data[i + PACKET_DATA_INDEX] = 0x00;
  779. /* file size written */
  780. Int2Str(astring, length);
  781. i = i + PACKET_DATA_INDEX + 1;
  782. while(astring[j] != '\0')
  783. {
  784. p_data[i++] = astring[j++];
  785. }
  786. /* padding with zeros */
  787. for(j = i; j < PACKET_SIZE + PACKET_DATA_INDEX; j++)
  788. {
  789. p_data[j] = 0;
  790. }
  791. }
  792. /**
  793. * @brief Prepare the data packet
  794. * @param p_source: pointer to the data to be sent
  795. * @param p_packet: pointer to the output buffer
  796. * @param pkt_nr: number of the packet
  797. * @param size_blk: length of the block to be sent in bytes
  798. */
  799. static void PreparePacket(uint8_t* p_source, uint8_t* p_packet, uint8_t pkt_nr, uint32_t size_blk)
  800. {
  801. uint8_t* p_record;
  802. uint32_t i, size, packet_size;
  803. /* Make first three packet */
  804. packet_size = size_blk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
  805. size = size_blk < packet_size ? size_blk : packet_size;
  806. if(packet_size == PACKET_1K_SIZE)
  807. {
  808. p_packet[PACKET_START_INDEX] = STX;
  809. }
  810. else
  811. {
  812. p_packet[PACKET_START_INDEX] = SOH;
  813. }
  814. p_packet[PACKET_NUMBER_INDEX] = pkt_nr;
  815. p_packet[PACKET_CNUMBER_INDEX] = (~pkt_nr);
  816. p_record = p_source;
  817. /* Filename packet has valid data */
  818. for(i = PACKET_DATA_INDEX; i < size + PACKET_DATA_INDEX; i++)
  819. {
  820. p_packet[i] = *p_record++;
  821. }
  822. if(size <= packet_size)
  823. {
  824. for(i = size + PACKET_DATA_INDEX; i < packet_size + PACKET_DATA_INDEX; i++)
  825. {
  826. p_packet[i] = 0x1A; /* EOF (0x1A) or 0x00 */
  827. }
  828. }
  829. }
  830. /**
  831. * @brief Update CRC16 for input byte
  832. * @param crc_in input value
  833. * @param input byte
  834. */
  835. uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte)
  836. {
  837. uint32_t crc = crc_in;
  838. uint32_t in = byte | 0x100;
  839. do
  840. {
  841. crc <<= 1;
  842. in <<= 1;
  843. if(in & 0x100)
  844. ++crc;
  845. if(crc & 0x10000)
  846. crc ^= 0x1021;
  847. }
  848. while(!(in & 0x10000));
  849. return crc & 0xffffu;
  850. }
  851. /**
  852. * @brief Cal CRC16 for YModem Packet
  853. * @param data
  854. * @param length
  855. */
  856. uint16_t Cal_CRC16(const uint8_t* p_data, uint32_t size)
  857. {
  858. uint32_t crc = 0;
  859. const uint8_t* dataEnd = p_data + size;
  860. while(p_data < dataEnd)
  861. crc = UpdateCRC16(crc, *p_data++);
  862. crc = UpdateCRC16(crc, 0);
  863. crc = UpdateCRC16(crc, 0);
  864. return crc & 0xffffu;
  865. }
  866. /**
  867. * @brief Calculate Check sum for YModem Packet
  868. * @param p_data Pointer to input data
  869. * @param size length of input data
  870. * @retval uint8_t checksum value
  871. */
  872. uint8_t CalcChecksum(const uint8_t* p_data, uint32_t size)
  873. {
  874. uint32_t sum = 0;
  875. const uint8_t* p_data_end = p_data + size;
  876. while(p_data < p_data_end)
  877. {
  878. sum += *p_data++;
  879. }
  880. return (sum & 0xffu);
  881. }
  882. /* Public functions ---------------------------------------------------------*/
  883. /**
  884. * @brief Receive a file using the ymodem protocol with CRC16.
  885. * @param p_size The size of the file.
  886. * @retval COM_StatusTypeDef result of reception/programming
  887. */
  888. COM_StatusTypeDef Ymodem_Receive(uint32_t* p_size)
  889. {
  890. uint32_t i, packet_length, session_done = 0, file_done, errors = 0, session_begin = 0;
  891. uint32_t flashdestination, ramsource, filesize;
  892. uint8_t* file_ptr;
  893. uint8_t file_size[FILE_SIZE_LENGTH], tmp, packets_received;
  894. COM_StatusTypeDef result = COM_OK;
  895. /* Initialize flashdestination variable */
  896. flashdestination = APPLICATION_ADDRESS;
  897. while((session_done == 0) && (result == COM_OK))
  898. {
  899. packets_received = 0;
  900. file_done = 0;
  901. while((file_done == 0) && (result == COM_OK))
  902. {
  903. switch(ReceivePacket(aPacketData, &packet_length, DOWNLOAD_TIMEOUT))
  904. {
  905. case HAL_OK:
  906. errors = 0;
  907. switch(packet_length)
  908. {
  909. case 2:
  910. /* Abort by sender */
  911. Interface_PutByte(ACK);
  912. result = COM_ABORT;
  913. break;
  914. case 0:
  915. /* End of transmission */
  916. Interface_PutByte(ACK);
  917. file_done = 1;
  918. break;
  919. default:
  920. /* Normal packet */
  921. if(aPacketData[PACKET_NUMBER_INDEX] != packets_received)
  922. {
  923. Interface_PutByte(NAK);
  924. }
  925. else
  926. {
  927. if(packets_received == 0)
  928. {
  929. /* File name packet */
  930. if(aPacketData[PACKET_DATA_INDEX] != 0)
  931. {
  932. /* File name extraction */
  933. i = 0;
  934. file_ptr = aPacketData + PACKET_DATA_INDEX;
  935. while((*file_ptr != 0) && (i < FILE_NAME_LENGTH))
  936. {
  937. aFileName[i++] = *file_ptr++;
  938. }
  939. /* File size extraction */
  940. aFileName[i++] = '\0';
  941. i = 0;
  942. file_ptr++;
  943. while((*file_ptr != ' ') && (i < FILE_SIZE_LENGTH))
  944. {
  945. file_size[i++] = *file_ptr++;
  946. }
  947. file_size[i++] = '\0';
  948. Str2Int(file_size, &filesize);
  949. /* Test the size of the image to be sent */
  950. /* Image size is greater than Flash size */
  951. if(*p_size > (USER_FLASH_SIZE + 1))
  952. {
  953. /* End session */
  954. tmp = CA;
  955. Interface_Transmit(&tmp, 1, NAK_TIMEOUT);
  956. Interface_Transmit(&tmp, 1, NAK_TIMEOUT);
  957. result = COM_LIMIT;
  958. }
  959. /* Erase user application area */
  960. FLASH_If_Erase(APPLICATION_ADDRESS);
  961. *p_size = filesize;
  962. Interface_PutByte(ACK);
  963. Interface_PutByte(CRC16);
  964. }
  965. /* File header packet is empty, end session */
  966. else
  967. {
  968. Interface_PutByte(ACK);
  969. file_done = 1;
  970. session_done = 1;
  971. break;
  972. }
  973. }
  974. else /* Data packet */
  975. {
  976. ramsource = (uint32_t)&aPacketData[PACKET_DATA_INDEX];
  977. /* Write received data in Flash */
  978. if(FLASH_If_Write(flashdestination, (uint32_t*)ramsource, packet_length / 4) == FLASHIF_OK)
  979. {
  980. flashdestination += packet_length;
  981. Interface_PutByte(ACK);
  982. }
  983. else /* An error occurred while writing to Flash memory */
  984. {
  985. /* End session */
  986. Interface_PutByte(CA);
  987. Interface_PutByte(CA);
  988. result = COM_DATA;
  989. }
  990. }
  991. packets_received++;
  992. session_begin = 1;
  993. }
  994. break;
  995. }
  996. break;
  997. case HAL_BUSY: /* Abort actually */
  998. Interface_PutByte(CA);
  999. Interface_PutByte(CA);
  1000. result = COM_ABORT;
  1001. break;
  1002. default:
  1003. if(session_begin > 0)
  1004. {
  1005. errors++;
  1006. }
  1007. if(errors > MAX_ERRORS)
  1008. {
  1009. /* Abort communication */
  1010. Interface_PutByte(CA);
  1011. Interface_PutByte(CA);
  1012. }
  1013. else
  1014. {
  1015. /* Ask for a packet */
  1016. Interface_PutByte(CRC16);
  1017. }
  1018. break;
  1019. }
  1020. }
  1021. }
  1022. return result;
  1023. }
  1024. /**
  1025. * @brief Transmit a file using the ymodem protocol
  1026. * @param p_buf: Address of the first byte
  1027. * @param p_file_name: Name of the file sent
  1028. * @param file_size: Size of the transmission
  1029. * @retval COM_StatusTypeDef result of the communication
  1030. */
  1031. COM_StatusTypeDef Ymodem_Transmit(uint8_t* p_buf, const uint8_t* p_file_name, uint32_t file_size)
  1032. {
  1033. uint32_t errors = 0, ack_recpt = 0, size = 0, pkt_size;
  1034. uint8_t* p_buf_int;
  1035. COM_StatusTypeDef result = COM_OK;
  1036. uint32_t blk_number = 1;
  1037. uint8_t a_rx_ctrl[2];
  1038. uint8_t i;
  1039. #ifdef CRC16_F
  1040. uint32_t temp_crc;
  1041. #else /* CRC16_F */
  1042. uint8_t temp_chksum;
  1043. #endif /* CRC16_F */
  1044. /* Prepare first block - header */
  1045. PrepareIntialPacket(aPacketData, p_file_name, file_size);
  1046. while((!ack_recpt) && (result == COM_OK))
  1047. {
  1048. /* Send Packet */
  1049. Interface_Transmit(&aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);
  1050. /* Send CRC or Check Sum based on CRC16_F */
  1051. #ifdef CRC16_F
  1052. temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  1053. Interface_PutByte(temp_crc >> 8);
  1054. Interface_PutByte(temp_crc & 0xFF);
  1055. #else /* CRC16_F */
  1056. temp_chksum = CalcChecksum(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  1057. Interface_PutByte(temp_chksum);
  1058. #endif /* CRC16_F */
  1059. /* Wait for Ack and 'C' */
  1060. if(Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
  1061. {
  1062. if(a_rx_ctrl[0] == ACK)
  1063. {
  1064. ack_recpt = 1;
  1065. }
  1066. else if(a_rx_ctrl[0] == CA)
  1067. {
  1068. if((Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA))
  1069. {
  1070. HAL_Delay(2);
  1071. Interface_Clean();
  1072. result = COM_ABORT;
  1073. }
  1074. }
  1075. else if(a_rx_ctrl[0] == ABORT1 || a_rx_ctrl[0] == ABORT2)
  1076. {
  1077. result = COM_ABORT;
  1078. }
  1079. }
  1080. else
  1081. {
  1082. errors++;
  1083. }
  1084. if(errors >= MAX_ERRORS)
  1085. {
  1086. result = COM_ERROR;
  1087. }
  1088. }
  1089. p_buf_int = p_buf;
  1090. size = file_size;
  1091. /* Here 1024 bytes length is used to send the packets */
  1092. while((size) && (result == COM_OK))
  1093. {
  1094. /* Prepare next packet */
  1095. PreparePacket(p_buf_int, aPacketData, blk_number, size);
  1096. ack_recpt = 0;
  1097. a_rx_ctrl[0] = 0;
  1098. errors = 0;
  1099. /* Resend packet if NAK for few times else end of communication */
  1100. while((!ack_recpt) && (result == COM_OK))
  1101. {
  1102. /* Send next packet */
  1103. if(size >= PACKET_1K_SIZE)
  1104. {
  1105. pkt_size = PACKET_1K_SIZE;
  1106. }
  1107. else
  1108. {
  1109. pkt_size = PACKET_SIZE;
  1110. }
  1111. Interface_Transmit(&aPacketData[PACKET_START_INDEX], pkt_size + PACKET_HEADER_SIZE, NAK_TIMEOUT);
  1112. /* Send CRC or Check Sum based on CRC16_F */
  1113. #ifdef CRC16_F
  1114. temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], pkt_size);
  1115. Interface_PutByte(temp_crc >> 8);
  1116. Interface_PutByte(temp_crc & 0xFF);
  1117. #else /* CRC16_F */
  1118. temp_chksum = CalcChecksum(&aPacketData[PACKET_DATA_INDEX], pkt_size);
  1119. Interface_PutByte(temp_chksum);
  1120. #endif /* CRC16_F */
  1121. /* Wait for Ack */
  1122. if((Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == ACK))
  1123. {
  1124. ack_recpt = 1;
  1125. if(size > pkt_size)
  1126. {
  1127. p_buf_int += pkt_size;
  1128. size -= pkt_size;
  1129. if(blk_number == (USER_FLASH_SIZE / PACKET_1K_SIZE))
  1130. {
  1131. result = COM_LIMIT; /* boundary error */
  1132. }
  1133. else
  1134. {
  1135. blk_number++;
  1136. }
  1137. }
  1138. else
  1139. {
  1140. p_buf_int += pkt_size;
  1141. size = 0;
  1142. }
  1143. }
  1144. else
  1145. {
  1146. errors++;
  1147. }
  1148. /* Resend packet if NAK for a count of 10 else end of communication */
  1149. if(errors >= MAX_ERRORS)
  1150. {
  1151. result = COM_ERROR;
  1152. }
  1153. }
  1154. }
  1155. /* Sending End Of Transmission char */
  1156. ack_recpt = 0;
  1157. a_rx_ctrl[0] = 0x00;
  1158. errors = 0;
  1159. while((!ack_recpt) && (result == COM_OK))
  1160. {
  1161. Interface_PutByte(EOT);
  1162. /* Wait for Ack */
  1163. if(Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
  1164. {
  1165. if(a_rx_ctrl[0] == ACK)
  1166. {
  1167. ack_recpt = 1;
  1168. }
  1169. else if(a_rx_ctrl[0] == CA)
  1170. {
  1171. if((Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA))
  1172. {
  1173. HAL_Delay(2);
  1174. Interface_Clean();
  1175. result = COM_ABORT;
  1176. }
  1177. }
  1178. }
  1179. else
  1180. {
  1181. errors++;
  1182. }
  1183. if(errors >= MAX_ERRORS)
  1184. {
  1185. result = COM_ERROR;
  1186. }
  1187. }
  1188. /* Empty packet sent - some terminal emulators need this to close session */
  1189. if(result == COM_OK)
  1190. {
  1191. /* Preparing an empty packet */
  1192. aPacketData[PACKET_START_INDEX] = SOH;
  1193. aPacketData[PACKET_NUMBER_INDEX] = 0;
  1194. aPacketData[PACKET_CNUMBER_INDEX] = 0xFF;
  1195. for(i = PACKET_DATA_INDEX; i < (PACKET_SIZE + PACKET_DATA_INDEX); i++)
  1196. {
  1197. aPacketData[i] = 0x00;
  1198. }
  1199. /* Send Packet */
  1200. Interface_Transmit(&aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);
  1201. /* Send CRC or Check Sum based on CRC16_F */
  1202. #ifdef CRC16_F
  1203. temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  1204. Interface_PutByte(temp_crc >> 8);
  1205. Interface_PutByte(temp_crc & 0xFF);
  1206. #else /* CRC16_F */
  1207. temp_chksum = CalcChecksum(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  1208. Interface_PutByte(temp_chksum);
  1209. #endif /* CRC16_F */
  1210. /* Wait for Ack and 'C' */
  1211. if(Interface_Receive(&a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
  1212. {
  1213. if(a_rx_ctrl[0] == CA)
  1214. {
  1215. HAL_Delay(2);
  1216. Interface_Clean();
  1217. result = COM_ABORT;
  1218. }
  1219. }
  1220. }
  1221. return result; /* File transmitted successfully */
  1222. }
  1223. #endif /* __IAP_YMODEM_ATY_C */
  1224. /******************************** End Of File *********************************/