main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. /*------------------------------------------------------------------------------
  2. * main.c
  3. * Copyright 2019 WDKL Electronics Co.,Ltd.
  4. * Description:
  5. * - This file implements the follow functions:
  6. * -
  7. * modification history
  8. * --------------------
  9. * 09:59am, 24.Sep.2019, written by dwd
  10. * --------------------
  11. ------------------------------------------------------------------------------*/
  12. /*----------------------------------------------------------------------------
  13. * I N C L U D E
  14. *--------------------------------------------------------------------------*/
  15. #include "stm32f0xx.h"
  16. #include "general.h"
  17. #include "mapp_ext.h"
  18. #include "mapp_gpio.h"
  19. #include "mapp_key.h"
  20. #include "mapp_pwr.h"
  21. #include "mapp_uart1.h"
  22. #include "main.h"
  23. #include "mapp_msg.h"
  24. #include "mapp_arm.h"
  25. #define OS_TIMER_1MS 1
  26. /*------------------------------------------------------------------------------
  27. * D E F I N E
  28. *------------------------------------------------------------------------------*/
  29. #define WDKL_TYPE_FJI 0x2014100Bu /* 病床分机 */
  30. #define IAP_PACKET_SIZE ((U08)128)
  31. #define FLASH_PAGE_SIZE ((U16)2048)
  32. #define AppStoreAddressStart ((U32)0x8000000) //起始位
  33. #define AppStoreAddress ((U32)0x8008000) //32K位置
  34. #define AppStoreEndAddress ((U32)0x8020000) //128K位置
  35. /*------------------------------------------------------------------------------
  36. * G L O B A L
  37. *------------------------------------------------------------------------------*/
  38. //ddconst U08 DeviceID[] __attribute__((at(0X8008000)))="SZFJI221016001";
  39. const U08 DeviceMacInfo[] __attribute__((at(0X8003300)))="F301";
  40. //const U08 DeviceVisionInfo[] ={"HV20SV142103050"};
  41. const U08 DeviceVisionInfo[] ={"SZD101012502091"};
  42. uint16_t X_Addata=0,Y_Addata=0;
  43. /*----------------------------------------------------------------------------
  44. * V A R I A B L E S
  45. *--------------------------------------------------------------------------*/
  46. static VU08 s_vu8SysSched0Tmr = 0;
  47. static VU08 s_vu8SysSched1Tmr = 0;
  48. static VU08 s_vu8SysSched2Tmr = 0;
  49. static VU08 s_vu8SysSched3Tmr = 0;
  50. /*------------------------------------------------------------------------------
  51. * P R O T O T Y P E
  52. *------------------------------------------------------------------------------*/
  53. static void s_MainNvicCfg(void);
  54. static void s_MainSysTickCfg(void);
  55. static void s_MainPeripheralCfg(void);
  56. static void s_MainIwdgCfg(void);
  57. static void s_MainSysVarInit(void);
  58. static void EraseFlash(U08 eraseCnt);
  59. static void EraseFlashMultiple(U08 eraseCntStart,U08 eraseCntEnd);
  60. static void s_FlashUnlockFunc(void);
  61. //static U32 Get_ChipSerialNum(void);
  62. //static void WriteEncrypt(void) ;
  63. //--------------------------------------------------------
  64. void strncpy_rom(U08* to,const U08 from[],U08 size)
  65. {
  66. while(size)
  67. {
  68. *to=*from;
  69. to++;
  70. from++;
  71. size--;
  72. }
  73. return;
  74. }
  75. void strncpy_u8(U08* to,U08* from,U08 size)
  76. {
  77. while(size)
  78. {
  79. *to=*from;
  80. to++;
  81. from++;
  82. size--;
  83. }
  84. return;
  85. }
  86. U08 MEMCPY(void * to,void * from,U08 size)
  87. {
  88. U08 *pTo = (U08 *)to;
  89. U08 *pFrom = (U08 *)from;
  90. if((NULL == pTo) || (NULL == pFrom))
  91. {
  92. return 0;
  93. }
  94. if(!((pTo >= pFrom + size) || (pFrom >= pTo + size)))
  95. {
  96. return 0;
  97. }
  98. while(size-- > 0)
  99. {
  100. *pTo++=*pFrom++;
  101. }
  102. return 1;
  103. }
  104. void MEMSET(void *buff,U08 data,U16 length)
  105. {
  106. U16 i;
  107. U08 *p;
  108. p = (U08 *)buff;
  109. for(i=0;i<length;i++)
  110. {
  111. *p = data;
  112. p++;
  113. }
  114. }
  115. U08 StrnCmp(U08 *str1,U08 *str2,U08 size)
  116. {
  117. U08 i;
  118. if(str1==str2) return 0;
  119. for(i=0;i<size;++i)
  120. {
  121. if(*str1>*str2) return 1;
  122. else if(*str1<*str2) return 1;
  123. else
  124. {
  125. ++str1;
  126. ++str2;
  127. }
  128. }
  129. return 0;
  130. }
  131. /*----------------------------------------------------------------------
  132. // Function uses : SysDelayUs
  133. // Input parameter :
  134. // Output parameter :
  135. // Use Function : delay 1us timer.
  136. // Reserve date : 11:10am, 17.Apr.2012, written by Sirius
  137. ----------------------------------------------------------------------*/
  138. void SysDelayUs(U16 dlyus)
  139. {
  140. U16 i = 0;
  141. while (dlyus--) {
  142. i = 15;
  143. while (i--);
  144. }
  145. }
  146. /*----------------------------------------------------------------------
  147. // Function uses : SysDelayMs
  148. // Input parameter :
  149. // Output parameter :
  150. // Use Function : delay 1ms timer.
  151. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  152. ----------------------------------------------------------------------*/
  153. void SysDelayMs(U16 dlyms)
  154. {
  155. U16 i = 0;
  156. while (dlyms--) {
  157. i = 6200;
  158. while (i--);
  159. }
  160. }
  161. /*----------------------------------------------------------------------
  162. // Function uses : SysTickISR
  163. // Input parameter :
  164. // Output parameter :
  165. // Use Function : Decrements the TimingDelay variable,tick every 5ms.
  166. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  167. //---------------------------------------------------------------------*/
  168. void SysTickISR(void)
  169. {
  170. static U08 u8systimecnt =0;
  171. if (s_vu8SysSched0Tmr != 0xff) { s_vu8SysSched0Tmr++; }
  172. if (s_vu8SysSched1Tmr != 0xff) { s_vu8SysSched1Tmr++; }
  173. if (s_vu8SysSched2Tmr != 0xff) { s_vu8SysSched2Tmr++; }
  174. if (s_vu8SysSched3Tmr != 0xff) { s_vu8SysSched3Tmr++; }
  175. if (gtArm.uarttxcnt != 0xff) { gtArm.uarttxcnt++; }
  176. /*--- Power task timer ---*/
  177. PwrTaskTmr();
  178. ArmTaskTmr();
  179. /*---I2C task timer---*/
  180. u8systimecnt ++;
  181. }
  182. void SosLedState(U08 u8sta)
  183. {
  184. static U08 u8cnt =0;
  185. if (u8sta ==0) {
  186. LED_EMEGENCY_ON ;
  187. } else if (u8sta ==1) {
  188. LED_EMEGENCY_OFF ;
  189. } else if (u8sta ==2) {
  190. u8cnt ++;
  191. if (u8cnt <5) {
  192. LED_EMEGENCY_OFF ;
  193. } else if (u8cnt >=9) {
  194. LED_EMEGENCY_ON ;
  195. u8cnt =0;
  196. } else if (u8cnt >5) {
  197. LED_EMEGENCY_ON ;
  198. }
  199. }
  200. }
  201. void DoorLedState(void)
  202. {
  203. static U08 u8cnt[4] ={0};
  204. if (gtArm.DoorLed[0] == 0) {
  205. LED_RED_OFF;
  206. } else if (gtArm.DoorLed[0] ==1) {
  207. LED_RED_ON ;
  208. } else if (gtArm.DoorLed[0] ==2) {
  209. u8cnt[0] ++;
  210. if (u8cnt[0] <5) {
  211. LED_RED_ON ;
  212. } else if (u8cnt[0] >=9) {
  213. u8cnt[0] =0;
  214. LED_RED_OFF;
  215. } else if (u8cnt[0] >5) {
  216. LED_RED_OFF;
  217. }
  218. }
  219. if (gtArm.DoorLed[1] == 0) {
  220. LED_BLUE_OFF ;
  221. } else if (gtArm.DoorLed[1] ==1) {
  222. LED_BLUE_ON;
  223. } else if (gtArm.DoorLed[1] ==2) {
  224. u8cnt[1] ++;
  225. if (u8cnt[1] <5) {
  226. LED_BLUE_ON;
  227. } else if (u8cnt[1] >=9) {
  228. u8cnt[1] =0;
  229. LED_BLUE_OFF ;
  230. } else if (u8cnt[1] >5) {
  231. LED_BLUE_OFF ;
  232. }
  233. }
  234. if (gtArm.DoorLed[2] == 0) {
  235. LED_GREEN_OFF;
  236. } else if (gtArm.DoorLed[2] ==1) {
  237. LED_GREEN_ON ;
  238. } else if (gtArm.DoorLed[2] ==2) {
  239. u8cnt[2] ++;
  240. if (u8cnt[2] <5) {
  241. LED_GREEN_ON ;
  242. } else if (u8cnt[2] >=9) {
  243. u8cnt[2] =0;
  244. LED_GREEN_OFF;
  245. } else if (u8cnt[2] >5) {
  246. LED_GREEN_OFF;
  247. }
  248. }
  249. }
  250. void CallLedState(void)
  251. {
  252. static U08 u8cnt = 0;
  253. static U08 u8cnt2 = 0;
  254. if (gtArm.callled_red == 1 ) {
  255. u8cnt ++;
  256. if (u8cnt <5) {
  257. LED_R_ON;
  258. } else if (u8cnt >=9) {
  259. u8cnt =0;
  260. LED_R_OFF;
  261. } else if (u8cnt > 5) {
  262. LED_R_OFF;
  263. }
  264. } else if (gtArm.callled_red == 2 ) {
  265. LED_R_ON;
  266. } else {
  267. LED_R_OFF;
  268. }
  269. if (gtArm.callled_yel == 1 ) {
  270. u8cnt2 ++;
  271. if (u8cnt2 <5) {
  272. LED_Y_ON;
  273. } else if (u8cnt2 >=9) {
  274. u8cnt2 =0;
  275. LED_Y_OFF;
  276. } else if (u8cnt2 > 5) {
  277. LED_Y_OFF;
  278. }
  279. } else if (gtArm.callled_yel == 2 ) {
  280. LED_Y_ON;
  281. } else {
  282. LED_Y_OFF;
  283. }
  284. }
  285. void LED_Task(void)
  286. {
  287. static U08 uLedKeyStae =0;
  288. static U08 u8time =0;
  289. static U08 u8cnt =0;
  290. static U08 u8cnt2 =0;
  291. #if 0
  292. u8time ++;
  293. if (gtArm.LedKeyState != uLedKeyStae) {
  294. u8time =0;
  295. if (gtArm.LedKeyState == 13) {
  296. u8cnt ++;
  297. if (u8cnt > 10) {
  298. u8cnt2 ++;
  299. u8cnt =0;
  300. LED_GREEN_OFF;
  301. } else if (u8cnt > 5) {
  302. LED_GREEN_OFF;
  303. } else {
  304. LED_GREEN_ON;
  305. }
  306. if (u8cnt2 >2) {
  307. u8cnt2 =0;
  308. gtArm.LedKeyState =0;
  309. }
  310. } else if (gtArm.LedKeyState == 12) {
  311. u8cnt ++;
  312. if (u8cnt > 10) {
  313. u8cnt2 ++;
  314. u8cnt =0;
  315. LED_GREEN_OFF;
  316. } else if (u8cnt > 5) {
  317. LED_GREEN_OFF;
  318. } else {
  319. LED_GREEN_ON;
  320. }
  321. if (u8cnt2 >0) {
  322. u8cnt2 =0;
  323. gtArm.LedKeyState =0;
  324. }
  325. } else if (gtArm.LedKeyState == 11) {
  326. u8cnt ++;
  327. if (u8cnt > 10) {
  328. u8cnt2 ++;
  329. u8cnt =0;
  330. LED_GREEN_OFF;
  331. } else if (u8cnt > 5) {
  332. LED_GREEN_OFF;
  333. } else {
  334. LED_GREEN_ON;
  335. }
  336. if (u8cnt2 >0) {
  337. u8cnt2 =0;
  338. gtArm.LedKeyState =0;
  339. }
  340. } else {
  341. u8cnt2 =0;
  342. }
  343. uLedKeyStae = gtArm.LedKeyState ;
  344. }
  345. if (u8time >50) { //5秒后清除按键
  346. u8time =0;
  347. gtArm.LedKeyState =0;
  348. uLedKeyStae = gtArm.LedKeyState ;
  349. }
  350. #endif
  351. SosLedState(gtArm.Uled);
  352. DoorLedState();
  353. CallLedState();
  354. }
  355. /*----------------------------------------------------------------------
  356. // Function uses : main
  357. // Input parameter :
  358. // Output parameter :
  359. // Use Function :
  360. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  361. ----------------------------------------------------------------------*/
  362. int main(void)
  363. {
  364. s_MainSysTickCfg(); /* Configure the systick */
  365. s_MainPeripheralCfg(); /* Peripheral Configuration */
  366. s_MainNvicCfg(); /* NVIC configuration */
  367. s_MainSysVarInit();
  368. s_MainIwdgCfg();
  369. #if 0
  370. // 使能GPIOA的时钟
  371. RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
  372. // 配置PA7为输出模式
  373. GPIOA->MODER &= ~(GPIO_MODER_MODER7); // 清除MODER7位
  374. GPIOA->MODER |= GPIO_MODER_MODER7_0; // 设置MODER7位为01,即输出模式
  375. // 设置PA7输出高电平
  376. GPIOA->BSRR = GPIO_BSRR_BS_7;
  377. if (s_vu8SysSched0Tmr >= OS_TIMER_5MS) { /* Schedule 5ms task with priority 0 */
  378. s_vu8SysSched0Tmr = 0;
  379. ArmTxTask();
  380. KeyPB0Check();
  381. continue;
  382. }
  383. #endif
  384. while (1) {
  385. IWDG_ReloadCounter(); /* Reload IWDG counter */
  386. if (s_vu8SysSched0Tmr >= OS_TIMER_5MS) { /* Schedule 5ms task with priority 0 */
  387. s_vu8SysSched0Tmr = 0;
  388. ArmTxTask();
  389. KeyPB0Check();
  390. KeyPA8Check();
  391. continue;
  392. }
  393. if (s_vu8SysSched1Tmr >= OS_TIMER_35MS) { /* Schedule 35ms task with priority 1 */
  394. s_vu8SysSched1Tmr = 0;
  395. ArmRxTask();
  396. KeyTask();
  397. continue;
  398. }
  399. if (s_vu8SysSched2Tmr >= OS_TIMER_100MS) { /* Schedule 100ms task with priority 2*/
  400. s_vu8SysSched2Tmr = 0;
  401. PwrTask();
  402. ExtTask();
  403. LED_Task();
  404. continue;
  405. }
  406. if (s_vu8SysSched3Tmr >= OS_TIMER_35MS) { /* Schedule 100+ms task with priority 2*/
  407. s_vu8SysSched3Tmr = 0;
  408. continue;
  409. }
  410. }
  411. }
  412. /*----------------------------------------------------------------------
  413. // Function uses : s_MainNvicCfg
  414. // Input parameter : Configures Vector Table base location.
  415. // Output parameter :
  416. // Use Function :
  417. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  418. ----------------------------------------------------------------------*/
  419. static void s_MainNvicCfg(void)
  420. {
  421. RCC_ClocksTypeDef get_rcc_clock;//???
  422. NVIC_InitTypeDef NVIC_InitStructure;
  423. RCC_GetClocksFreq(&get_rcc_clock);
  424. /* Configure one bit for preemption priority */
  425. /* Enable the CAN1 RX0 Interrupt */
  426. //NVIC_InitStructure.NVIC_IRQChannel = CEC_CAN_IRQn;
  427. //NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
  428. //NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  429. //NVIC_Init(&NVIC_InitStructure);
  430. /* Enable DVD USART3 USART4 Interrupt */
  431. NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
  432. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  433. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  434. NVIC_Init(&NVIC_InitStructure);
  435. }
  436. /*----------------------------------------------------------------------
  437. // Function uses : s_MainSysTickCfg
  438. // Input parameter :
  439. // Output parameter :
  440. // Use Function :
  441. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  442. ----------------------------------------------------------------------*/
  443. static void s_MainSysTickCfg(void)
  444. {
  445. /* This example shows how to configure the SysTick to generate a time base equal to
  446. 5 ms. The system clock is set to 24 MHz on Value line devices and to 72 MHz on
  447. other devices, the SysTick is clocked by the AHB clock (HCLK).
  448. prm == (N.[ms] * SystemCoreClock / 1000).
  449. */
  450. if (SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC))
  451. {
  452. /* Capture error */
  453. while (1);
  454. }
  455. }
  456. /*----------------------------------------------------------------------
  457. // Function uses : s_MainPeripheralCfg
  458. // Input parameter : Configures the different peripheral.
  459. // Output parameter :
  460. // Use Function :
  461. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  462. ----------------------------------------------------------------------*/
  463. static void s_MainPeripheralCfg(void)
  464. {
  465. U32 u32prm =0;
  466. /*--- GPIO ---*/
  467. GpioCfgInit();
  468. /*---UART1 ---*/
  469. Uart1CfgInit();
  470. /*---AD----*/
  471. //AdcCfgInit();
  472. u32prm =*(U32*)(0X8003300);
  473. if ((u32prm !=0) && (u32prm !=0xffffff) ) {
  474. //gtArm.SlaveFJZHmac = TO_WORD(LO_BYTE(u16prm), HI_BYTE(u16prm));
  475. gtArm.FJKeymac = HexToInt(u32prm);
  476. // gtArm.SlaveFJZHmac = u16prm;
  477. }
  478. }
  479. /*----------------------------------------------------------------------
  480. // Function uses : s_MainIwdgCfg
  481. // Input parameter :
  482. // Output parameter :
  483. // Use Function :
  484. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  485. ----------------------------------------------------------------------*/
  486. static void s_MainIwdgCfg(void)
  487. {
  488. /* IWDG timeout equal to 2000 ms (the timeout may varies due to LSI frequency
  489. dispersion) */
  490. /* Enable write access to IWDG_PR and IWDG_RLR registers */
  491. IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
  492. /* IWDG counter clock: 40KHz(LSI) / 32 = 1.25 KHz */
  493. IWDG_SetPrescaler(IWDG_Prescaler_128);
  494. /* Set counter reload value to 499 */
  495. IWDG_SetReload(1000);
  496. /* Reload IWDG counter */
  497. IWDG_ReloadCounter();
  498. /* Enable IWDG (the LSI oscillator will be enabled by hardware) */
  499. IWDG_Enable();
  500. }
  501. /*----------------------------------------------------------------------
  502. // Function uses : s_MainSysVarInit
  503. // Input parameter :
  504. // Output parameter :
  505. // Use Function :
  506. // Reserve date : 10:10am, 9.Sep.2019, written by dwd
  507. //---------------------------------------------------------------------*/
  508. static void s_MainSysVarInit(void)
  509. {
  510. s_vu8SysSched0Tmr = 0;
  511. s_vu8SysSched1Tmr = 0;
  512. s_vu8SysSched2Tmr = 0;
  513. s_vu8SysSched3Tmr = 0;
  514. /*--- POWER ---*/
  515. PwrVarInit();
  516. /*--- UART1 ---*/
  517. /*--- KEY ---*/
  518. KeyVarInit();
  519. /*---dvd---*/
  520. ArmValInit();
  521. /*---ext---*/
  522. ExtValInit();
  523. /*---msg---*/
  524. OSQInit();
  525. }
  526. void FlashCheckWriteProtect(void)
  527. {
  528. unsigned int BlockNbr = 0;
  529. unsigned int UserMemoryMask = 0;
  530. BlockNbr = (AppStoreAddress - 0x08000000) >> 12;
  531. /* Compute the mask to test if the Flash memory, where the user program will be
  532. loaded, is write protected */
  533. UserMemoryMask = ((unsigned int)~((1 << BlockNbr) - 1));
  534. /* Test if any page of Flash memory where program user will be loaded is write protected */
  535. if ((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask) {
  536. FLASH_EraseOptionBytes();
  537. }
  538. }
  539. static void EraseFlash(U08 eraseCnt)
  540. {
  541. FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
  542. FLASH_ErasePage(AppStoreAddress + (FLASH_PAGE_SIZE * eraseCnt));
  543. }
  544. static void EraseFlashMultiple(U08 eraseCntStart,U08 eraseCntEnd)
  545. {
  546. U08 u8prm =0;
  547. U08 u8diff =0;
  548. FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
  549. u8diff = eraseCntEnd -eraseCntStart;
  550. for (u8prm =0;u8prm < u8diff;u8prm++) {
  551. FLASH_ErasePage( AppStoreAddressStart+(FLASH_PAGE_SIZE * (eraseCntStart +u8prm)));
  552. }
  553. }
  554. static void s_FlashUnlockFunc(void)
  555. {
  556. FLASH_Unlock();
  557. FlashCheckWriteProtect();
  558. EraseFlash(32);
  559. }
  560. //FLASH_ProgramHalfWord(AppStoreAddress, u16sncnt); //写FLASH值
  561. //stIap.totalSN = *(u32*)(AppStoreAddress); //读FLASH位置
  562. //读取指定地址的半字(16位数据)
  563. //也是按照半字读出,即每次读2个字节数据返回
  564. U16 FLASH_ReadHalfWord(U32 address)
  565. {
  566. return *(__IO U16*)address;
  567. }
  568. //从指定地址开始读取多个数据
  569. void FLASH_ReadMoreData(U32 startAddress,U16 *readData,U16 countToRead)
  570. {
  571. U16 dataIndex;
  572. for(dataIndex=0;dataIndex<countToRead;dataIndex++)
  573. {
  574. readData[dataIndex]=FLASH_ReadHalfWord(startAddress+dataIndex*2);
  575. }
  576. }