You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

879 rivejä
22 KiB

  1. /**
  2. *
  3. * \file
  4. *
  5. * \brief This module contains M2M host interface APIs implementation.
  6. *
  7. * Copyright (c) 2017-2018 Microchip Technology Inc. and its subsidiaries.
  8. *
  9. * \asf_license_start
  10. *
  11. * \page License
  12. *
  13. * Subject to your compliance with these terms, you may use Microchip
  14. * software and any derivatives exclusively with Microchip products.
  15. * It is your responsibility to comply with third party license terms applicable
  16. * to your use of third party software (including open source software) that
  17. * may accompany Microchip software.
  18. *
  19. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
  20. * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
  21. * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
  22. * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
  23. * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
  24. * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
  25. * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
  26. * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
  27. * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
  28. * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
  29. * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
  30. *
  31. * \asf_license_stop
  32. *
  33. */
  34. #include "common/include/nm_common.h"
  35. #include "driver/source/nmbus.h"
  36. #include "driver/source/nmdrv.h"
  37. #include "bsp/include/nm_bsp.h"
  38. #include "m2m_hif.h"
  39. #include "driver/include/m2m_types.h"
  40. #include "driver/source/nmasic.h"
  41. #include "driver/include/m2m_periph.h"
  42. #if (defined NM_EDGE_INTERRUPT)&&(defined NM_LEVEL_INTERRUPT)
  43. #error "only one type of interrupt NM_EDGE_INTERRUPT,NM_LEVEL_INTERRUPT"
  44. #endif
  45. #if !((defined NM_EDGE_INTERRUPT)||(defined NM_LEVEL_INTERRUPT))
  46. #error "define interrupt type NM_EDGE_INTERRUPT,NM_LEVEL_INTERRUPT"
  47. #endif
  48. #ifndef CORTUS_APP
  49. #define NMI_AHB_DATA_MEM_BASE 0x30000
  50. #define NMI_AHB_SHARE_MEM_BASE 0xd0000
  51. #define WIFI_HOST_RCV_CTRL_0 (0x1070)
  52. #define WIFI_HOST_RCV_CTRL_1 (0x1084)
  53. #define WIFI_HOST_RCV_CTRL_2 (0x1078)
  54. #define WIFI_HOST_RCV_CTRL_3 (0x106c)
  55. #define WAKE_VALUE (0x5678)
  56. #define SLEEP_VALUE (0x4321)
  57. #define WAKE_REG (0x1074)
  58. #define INTERRUPT_CORTUS_0_3000D0 (0x10a8)
  59. #define INTERRUPT_CORTUS_1_3000D0 (0x10ac)
  60. #define INTERRUPT_CORTUS_2_3000D0 (0x10b0)
  61. #define INTERRUPT_CORTUS_3_3000D0 (0x10b4)
  62. static volatile uint8 gu8ChipMode = 0;
  63. static volatile uint8 gu8ChipSleep = 0;
  64. static volatile uint8 gu8HifSizeDone = 0;
  65. static volatile uint8 gu8Interrupt = 0;
  66. static volatile uint8 gu8Yield = 0;
  67. /*
  68. Special codes for managing HIF restriction to OTA rollback/switch only
  69. */
  70. #define HIF_OTA_RB_ONLY 0xFFFF
  71. #define HIFCODE_OTA_RB ((M2M_REQ_GROUP_OTA << 8) | M2M_OTA_REQ_ROLLBACK)
  72. #define HIFCODE_OTA_SW ((M2M_REQ_GROUP_OTA << 8) | M2M_OTA_REQ_SWITCH_FIRMWARE)
  73. #define HIFCODE_SSL_WRITECERT ((M2M_REQ_GROUP_SSL << 8) | M2M_SSL_REQ_WRITE_OWN_CERTS)
  74. #define HIFCODE_WIFI_PASSIVESCAN ((M2M_REQ_GROUP_WIFI << 8) | M2M_WIFI_REQ_PASSIVE_SCAN)
  75. /*
  76. List of new HIF messages (since last HIF major increase)
  77. Each entry is formed of ((GroupId << 8) | OpCode)
  78. Additionally, entry 0 used to indicate OTA RB/SW only.
  79. */
  80. #define NEW_HIF_LIST HIF_OTA_RB_ONLY, HIFCODE_SSL_WRITECERT, HIFCODE_WIFI_PASSIVESCAN
  81. /*
  82. Array of HIF messages which are not supported by Firmware.
  83. During hif_init() this array is rebased using an offset determined by Firmware HIF level.
  84. */
  85. static uint16 gau16HifBlacklist[] = {NEW_HIF_LIST};
  86. #define HIF_BLACKLIST_SZ (sizeof(gau16HifBlacklist)/sizeof(gau16HifBlacklist[0]))
  87. static uint8 gu8HifBlOffset = 0;
  88. tpfHifCallBack pfWifiCb = NULL; /*!< pointer to Wi-Fi call back function */
  89. tpfHifCallBack pfIpCb = NULL; /*!< pointer to Socket call back function */
  90. tpfHifCallBack pfOtaCb = NULL; /*!< pointer to OTA call back function */
  91. tpfHifCallBack pfSigmaCb = NULL;
  92. tpfHifCallBack pfHifCb = NULL;
  93. tpfHifCallBack pfSSLCb = NULL;
  94. static void isr(void)
  95. {
  96. gu8Interrupt++;
  97. #ifdef NM_LEVEL_INTERRUPT
  98. nm_bsp_interrupt_ctrl(0);
  99. #endif
  100. }
  101. static sint8 hif_set_rx_done(void)
  102. {
  103. uint32 reg;
  104. sint8 ret = M2M_SUCCESS;
  105. #ifdef NM_EDGE_INTERRUPT
  106. nm_bsp_interrupt_ctrl(1);
  107. #endif
  108. if (ISNMC3400(nmi_get_chipid())) {
  109. ret = nm_write_reg(INTERRUPT_CORTUS_0_3000D0,1);
  110. if(ret != M2M_SUCCESS)goto ERR1;
  111. } else {
  112. ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0,&reg);
  113. if(ret != M2M_SUCCESS)goto ERR1;
  114. //reg &= ~(1<<0);
  115. /* Set RX Done */
  116. reg |= (1<<1);
  117. ret = nm_write_reg(WIFI_HOST_RCV_CTRL_0,reg);
  118. if(ret != M2M_SUCCESS)goto ERR1;
  119. }
  120. #ifdef NM_LEVEL_INTERRUPT
  121. nm_bsp_interrupt_ctrl(1);
  122. #endif
  123. ERR1:
  124. return ret;
  125. }
  126. /**
  127. * @fn static void m2m_hif_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr)
  128. * @brief WiFi call back function
  129. * @param [in] u8OpCode
  130. * HIF Opcode type.
  131. * @param [in] u16DataSize
  132. * HIF data length.
  133. * @param [in] u32Addr
  134. * HIF address.
  135. * @author
  136. * @date
  137. * @version 1.0
  138. */
  139. static void m2m_hif_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr)
  140. {
  141. }
  142. /**
  143. * @fn NMI_API sint8 hif_chip_wake(void);
  144. * @brief To Wakeup the chip.
  145. * @return The function shall return ZERO for successful operation and a negative value otherwise.
  146. */
  147. sint8 hif_chip_wake(void)
  148. {
  149. sint8 ret = M2M_SUCCESS;
  150. if(gu8ChipSleep == 0)
  151. {
  152. if((gu8ChipMode == M2M_PS_DEEP_AUTOMATIC)||(gu8ChipMode == M2M_PS_MANUAL))
  153. {
  154. ret = nm_clkless_wake();
  155. if(ret != M2M_SUCCESS)goto ERR1;
  156. ret = nm_write_reg(WAKE_REG, WAKE_VALUE);
  157. if(ret != M2M_SUCCESS)goto ERR1;
  158. }
  159. else
  160. {
  161. }
  162. }
  163. gu8ChipSleep++;
  164. ERR1:
  165. return ret;
  166. }
  167. /*!
  168. @fn \
  169. NMI_API void hif_set_sleep_mode(uint8 u8Pstype);
  170. @brief
  171. Set the sleep mode of the HIF layer.
  172. @param [in] u8Pstype
  173. Sleep mode.
  174. @return
  175. The function SHALL return 0 for success and a negative value otherwise.
  176. */
  177. void hif_set_sleep_mode(uint8 u8Pstype)
  178. {
  179. gu8ChipMode = u8Pstype;
  180. }
  181. /*!
  182. @fn \
  183. NMI_API uint8 hif_get_sleep_mode(void);
  184. @brief
  185. Get the sleep mode of the HIF layer.
  186. @return
  187. The function SHALL return the sleep mode of the HIF layer.
  188. */
  189. uint8 hif_get_sleep_mode(void)
  190. {
  191. return gu8ChipMode;
  192. }
  193. /**
  194. * @fn NMI_API sint8 hif_chip_sleep(void);
  195. * @brief To make the chip sleep.
  196. * @return The function shall return ZERO for successful operation and a negative value otherwise.
  197. */
  198. sint8 hif_chip_sleep(void)
  199. {
  200. sint8 ret = M2M_SUCCESS;
  201. if(gu8ChipSleep >= 1)
  202. {
  203. gu8ChipSleep--;
  204. }
  205. if(gu8ChipSleep == 0)
  206. {
  207. if((gu8ChipMode == M2M_PS_DEEP_AUTOMATIC)||(gu8ChipMode == M2M_PS_MANUAL))
  208. {
  209. uint32 reg = 0;
  210. ret = nm_write_reg(WAKE_REG, SLEEP_VALUE);
  211. if(ret != M2M_SUCCESS)goto ERR1;
  212. /* Clear bit 1 */
  213. ret = nm_read_reg_with_ret(0x1, &reg);
  214. if(ret != M2M_SUCCESS)goto ERR1;
  215. if(reg&0x2)
  216. {
  217. reg &=~(1 << 1);
  218. ret = nm_write_reg(0x1, reg);
  219. }
  220. }
  221. else
  222. {
  223. }
  224. }
  225. ERR1:
  226. return ret;
  227. }
  228. /**
  229. * @fn NMI_API sint8 hif_init(void * arg);
  230. * @brief To initialize HIF layer.
  231. * @param [in] arg
  232. * Pointer to the arguments.
  233. * @return The function shall return ZERO for successful operation and a negative value otherwise.
  234. */
  235. sint8 hif_init(void * arg)
  236. {
  237. pfWifiCb = NULL;
  238. pfIpCb = NULL;
  239. gu8ChipSleep = 0;
  240. gu8ChipMode = M2M_NO_PS;
  241. gu8Interrupt = 0;
  242. nm_bsp_register_isr(isr);
  243. gu8HifBlOffset = 0;
  244. hif_register_cb(M2M_REQ_GROUP_HIF,m2m_hif_cb);
  245. return M2M_SUCCESS;
  246. }
  247. /**
  248. * @fn NMI_API sint8 hif_deinit(void * arg);
  249. * @brief To Deinitialize HIF layer.
  250. * @param [in] arg
  251. * Pointer to the arguments.
  252. * @return The function shall return ZERO for successful operation and a negative value otherwise.
  253. */
  254. sint8 hif_deinit(void * arg)
  255. {
  256. sint8 ret = M2M_SUCCESS;
  257. #if 0
  258. uint32 reg = 0, cnt=0;
  259. while (reg != M2M_DISABLE_PS)
  260. {
  261. nm_bsp_sleep(1);
  262. reg = nm_read_reg(STATE_REG);
  263. if(++cnt > 1000)
  264. {
  265. M2M_DBG("failed to stop power save\n");
  266. break;
  267. }
  268. }
  269. #endif
  270. ret = hif_chip_wake();
  271. gu8ChipMode = 0;
  272. gu8ChipSleep = 0;
  273. gu8HifSizeDone = 0;
  274. gu8Interrupt = 0;
  275. pfWifiCb = NULL;
  276. pfIpCb = NULL;
  277. pfOtaCb = NULL;
  278. pfHifCb = NULL;
  279. return ret;
  280. }
  281. /**
  282. * @fn sint8 hif_check_compatibility(uint16 u16HifInfo);
  283. * @brief
  284. * To check the compatibility of an image with the current driver.
  285. * @param [in] u16HifInfo
  286. * HIF info of image to be checked.
  287. * @return The function shall return ZERO for compatible image and a negative value otherwise.
  288. */
  289. sint8 hif_check_compatibility(uint16 u16HifInfo)
  290. {
  291. sint8 ret = M2M_ERR_FW_VER_MISMATCH;
  292. if((M2M_GET_HIF_BLOCK(u16HifInfo) == M2M_HIF_BLOCK_VALUE) && (M2M_GET_HIF_MAJOR(u16HifInfo) == M2M_HIF_MAJOR_VALUE))
  293. {
  294. ret = M2M_SUCCESS;
  295. }
  296. return ret;
  297. }
  298. /**
  299. * @fn sint8 hif_enable_access(void);
  300. * @brief
  301. * To enable access to HIF layer, based on HIF level of Firmware.
  302. * This function reads HIF level directly from a register written by Firmware.
  303. * @return The function shall return ZERO for full match operation and a negative value if operation is restricted.
  304. */
  305. sint8 hif_enable_access(void)
  306. {
  307. sint8 ret = M2M_SUCCESS;
  308. uint16 fw_hif_info = 0;
  309. ret = nm_get_hif_info(&fw_hif_info, NULL);
  310. if(ret == M2M_SUCCESS)
  311. {
  312. ret = hif_check_compatibility(fw_hif_info);
  313. if(ret == M2M_SUCCESS)
  314. {
  315. switch(M2M_GET_HIF_MINOR(fw_hif_info))
  316. {
  317. case 0:
  318. gu8HifBlOffset = 1;
  319. break;
  320. case 1:
  321. gu8HifBlOffset = 2;
  322. break;
  323. case 2:
  324. gu8HifBlOffset = 2;
  325. break;
  326. case 3:
  327. gu8HifBlOffset = 3;
  328. break;
  329. // Additional case to be added each time hif minor increments.
  330. // All additional cases to be removed in the event of a hif major increment.
  331. // Default catches all cases in which hif minor is greater in Firmware than in Driver.
  332. default:
  333. gu8HifBlOffset = HIF_BLACKLIST_SZ;
  334. break;
  335. }
  336. }
  337. else
  338. {
  339. gu8HifBlOffset = 0;
  340. M2M_ERR("HIF access limited to OTA Switch/Rollback only\n");
  341. }
  342. }
  343. return ret;
  344. }
  345. /**
  346. * @fn sint8 hif_check_code(uint8 u8Gid, uint8 u8OpCode);
  347. * @brief
  348. * To check that a particular hif message is supported with the current driver/firmware pair.
  349. * @param [in] u8Gid
  350. * Group ID.
  351. * @param [in] u8Opcode
  352. * Operation ID.
  353. * @return The function shall return ZERO for support and a negative value otherwise.
  354. */
  355. sint8 hif_check_code(uint8 u8Gid, uint8 u8OpCode)
  356. {
  357. uint8 u8BlId;
  358. uint16 u16HifCode = ((uint16)u8Gid<<8) | u8OpCode;
  359. if((u16HifCode == HIFCODE_OTA_RB) || (u16HifCode == HIFCODE_OTA_SW))
  360. {
  361. return M2M_SUCCESS;
  362. }
  363. if(gu8HifBlOffset == 0)
  364. {
  365. M2M_ERR("HIF OTA rb/sw only\n");
  366. return M2M_ERR_SEND;
  367. }
  368. for(u8BlId = gu8HifBlOffset; u8BlId < HIF_BLACKLIST_SZ; u8BlId++)
  369. {
  370. if(u16HifCode == gau16HifBlacklist[u8BlId])
  371. {
  372. M2M_ERR("HIF message unsupported\n");
  373. return M2M_ERR_SEND;
  374. }
  375. }
  376. return M2M_SUCCESS;
  377. }
  378. /**
  379. * @fn NMI_API sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize,
  380. uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset)
  381. * @brief Send packet using host interface.
  382. * @param [in] u8Gid
  383. * Group ID.
  384. * @param [in] u8Opcode
  385. * Operation ID.
  386. * @param [in] pu8CtrlBuf
  387. * Pointer to the Control buffer.
  388. * @param [in] u16CtrlBufSize
  389. Control buffer size.
  390. * @param [in] u16DataOffset
  391. Packet Data offset.
  392. * @param [in] pu8DataBuf
  393. * Packet buffer Allocated by the caller.
  394. * @param [in] u16DataSize
  395. Packet buffer size (including the HIF header).
  396. * @return The function shall return ZERO for successful operation and a negative value otherwise.
  397. */
  398. sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize,
  399. uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset)
  400. {
  401. sint8 ret = M2M_ERR_SEND;
  402. volatile tstrHifHdr strHif;
  403. strHif.u8Opcode = u8Opcode&(~NBIT7);
  404. strHif.u8Gid = u8Gid;
  405. strHif.u16Length = M2M_HIF_HDR_OFFSET;
  406. if(pu8DataBuf != NULL)
  407. {
  408. strHif.u16Length += u16DataOffset + u16DataSize;
  409. }
  410. else
  411. {
  412. strHif.u16Length += u16CtrlBufSize;
  413. }
  414. ret = hif_check_code(strHif.u8Gid, strHif.u8Opcode);
  415. if(ret != M2M_SUCCESS)
  416. {
  417. goto ERR1;
  418. }
  419. ret = hif_chip_wake();
  420. if(ret == M2M_SUCCESS)
  421. {
  422. volatile uint32 reg, dma_addr = 0;
  423. volatile uint16 cnt = 0;
  424. reg = 0UL;
  425. reg |= (uint32)u8Gid;
  426. reg |= ((uint32)u8Opcode<<8);
  427. reg |= ((uint32)strHif.u16Length<<16);
  428. ret = nm_write_reg(NMI_STATE_REG,reg);
  429. if(M2M_SUCCESS != ret) goto ERR1;
  430. reg = 0;
  431. reg |= (1<<1);
  432. ret = nm_write_reg(WIFI_HOST_RCV_CTRL_2, reg);
  433. if(M2M_SUCCESS != ret) goto ERR1;
  434. if (ISNMC3400(nmi_get_chipid())) {
  435. ret = nm_write_reg(INTERRUPT_CORTUS_1_3000D0, 1);
  436. if(M2M_SUCCESS != ret) goto ERR1;
  437. }
  438. dma_addr = 0;
  439. //nm_bsp_interrupt_ctrl(0);
  440. for(cnt = 0; cnt < 1000*5; cnt ++)
  441. {
  442. ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_2,(uint32 *)&reg);
  443. if(ret != M2M_SUCCESS)
  444. break;
  445. if (!(reg & 0x2))
  446. {
  447. ret = nm_read_reg_with_ret(0x150400,(uint32 *)&dma_addr);
  448. if(ret != M2M_SUCCESS) {
  449. /*in case of read error clear the dma address and return error*/
  450. dma_addr = 0;
  451. }
  452. /*in case of success break */
  453. break;
  454. }
  455. //If we are struggling to get a response, start waiting longer
  456. if (cnt>=1000)
  457. nm_bsp_sleep(5);
  458. }
  459. //nm_bsp_interrupt_ctrl(1);
  460. if (dma_addr != 0)
  461. {
  462. volatile uint32 u32CurrAddr;
  463. u32CurrAddr = dma_addr;
  464. strHif.u16Length=NM_BSP_B_L_16(strHif.u16Length);
  465. M2M_DBG("Writing into %lx %ld\n", dma_addr, strHif.u16Length);
  466. ret = nm_write_block(u32CurrAddr, (uint8*)&strHif, M2M_HIF_HDR_OFFSET);
  467. if(M2M_SUCCESS != ret)
  468. goto ERR1;
  469. u32CurrAddr += M2M_HIF_HDR_OFFSET;
  470. if(pu8CtrlBuf != NULL)
  471. {
  472. ret = nm_write_block(u32CurrAddr, pu8CtrlBuf, u16CtrlBufSize);
  473. if(M2M_SUCCESS != ret)
  474. goto ERR1;
  475. u32CurrAddr += u16CtrlBufSize;
  476. }
  477. if(pu8DataBuf != NULL)
  478. {
  479. u32CurrAddr += (u16DataOffset - u16CtrlBufSize);
  480. ret = nm_write_block(u32CurrAddr, pu8DataBuf, u16DataSize);
  481. if(M2M_SUCCESS != ret)
  482. goto ERR1;
  483. u32CurrAddr += u16DataSize;
  484. }
  485. reg = dma_addr << 2;
  486. /* MERGEBUG: TODO: Following line of code is to generate the interrupt which
  487. is not needed for 3400, need to check if there are any side effects of keeping it
  488. */
  489. reg |= (1 << 1);
  490. ret = nm_write_reg(WIFI_HOST_RCV_CTRL_3, reg);
  491. if(M2M_SUCCESS != ret)
  492. goto ERR1;
  493. if (ISNMC3400(nmi_get_chipid())) {
  494. ret = nm_write_reg(INTERRUPT_CORTUS_2_3000D0, 1);
  495. if(M2M_SUCCESS != ret)
  496. goto ERR1;
  497. }
  498. }
  499. else
  500. {
  501. M2M_DBG("Failed to alloc rx size\n");
  502. ret = M2M_ERR_MEM_ALLOC;
  503. goto ERR1;
  504. }
  505. }
  506. else
  507. {
  508. M2M_ERR("(HIF)Fail to wakup the chip\n");
  509. goto ERR1;
  510. }
  511. ret = hif_chip_sleep();
  512. ERR1:
  513. return ret;
  514. }
  515. /**
  516. * @fn hif_isr
  517. * @brief Host interface interrupt service routine
  518. * @author M. Abdelmawla
  519. * @date 15 July 2012
  520. * @return 1 in case of interrupt received else 0 will be returned
  521. * @version 1.0
  522. */
  523. static sint8 hif_isr(void)
  524. {
  525. sint8 ret = M2M_SUCCESS;
  526. uint32 reg;
  527. volatile tstrHifHdr strHif;
  528. //if(ret == M2M_SUCCESS)
  529. {
  530. ret = nm_read_reg_with_ret(0x1070, &reg);
  531. if(M2M_SUCCESS == ret)
  532. {
  533. if(reg & 0x1) /* New interrupt has been received */
  534. {
  535. uint16 size;
  536. nm_bsp_interrupt_ctrl(0);
  537. /*Clearing RX interrupt*/
  538. ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0,&reg);
  539. if(ret != M2M_SUCCESS)goto ERR1;
  540. reg &= ~(1<<0);
  541. ret = nm_write_reg(WIFI_HOST_RCV_CTRL_0,reg);
  542. if(ret != M2M_SUCCESS)goto ERR1;
  543. /* read the rx size */
  544. ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0, &reg);
  545. if(M2M_SUCCESS != ret)
  546. {
  547. M2M_ERR("(hif) WIFI_HOST_RCV_CTRL_0 bus fail\n");
  548. nm_bsp_interrupt_ctrl(1);
  549. goto ERR1;
  550. }
  551. gu8HifSizeDone = 0;
  552. size = (uint16)((reg >> 2) & 0xfff);
  553. if (size > 0) {
  554. uint32 address = 0;
  555. /**
  556. start bus transfer
  557. **/
  558. ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_1, &address);
  559. if(M2M_SUCCESS != ret)
  560. {
  561. M2M_ERR("(hif) WIFI_HOST_RCV_CTRL_1 bus fail\n");
  562. nm_bsp_interrupt_ctrl(1);
  563. goto ERR1;
  564. }
  565. ret = nm_read_block(address, (uint8*)&strHif, sizeof(tstrHifHdr));
  566. strHif.u16Length = NM_BSP_B_L_16(strHif.u16Length);
  567. if(M2M_SUCCESS != ret)
  568. {
  569. M2M_ERR("(hif) address bus fail\n");
  570. nm_bsp_interrupt_ctrl(1);
  571. goto ERR1;
  572. }
  573. if(strHif.u16Length != size)
  574. {
  575. if((size - strHif.u16Length) > 4)
  576. {
  577. M2M_ERR("(hif) Corrupted packet Size = %u <L = %u, G = %u, OP = %02X>\n",
  578. size, strHif.u16Length, strHif.u8Gid, strHif.u8Opcode);
  579. nm_bsp_interrupt_ctrl(1);
  580. ret = M2M_ERR_BUS_FAIL;
  581. goto ERR1;
  582. }
  583. }
  584. if(M2M_REQ_GROUP_WIFI == strHif.u8Gid)
  585. {
  586. if(pfWifiCb)
  587. pfWifiCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET);
  588. }
  589. else if(M2M_REQ_GROUP_IP == strHif.u8Gid)
  590. {
  591. if(pfIpCb)
  592. pfIpCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET);
  593. }
  594. else if(M2M_REQ_GROUP_OTA == strHif.u8Gid)
  595. {
  596. if(pfOtaCb)
  597. pfOtaCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET);
  598. }
  599. else if(M2M_REQ_GROUP_SIGMA == strHif.u8Gid)
  600. {
  601. if(pfSigmaCb)
  602. pfSigmaCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET);
  603. }
  604. else if(M2M_REQ_GROUP_SSL == strHif.u8Gid)
  605. {
  606. if(pfSSLCb)
  607. pfSSLCb(strHif.u8Opcode,strHif.u16Length - M2M_HIF_HDR_OFFSET, address + M2M_HIF_HDR_OFFSET);
  608. }
  609. else
  610. {
  611. M2M_ERR("(hif) invalid group ID\n");
  612. ret = M2M_ERR_BUS_FAIL;
  613. goto ERR1;
  614. }
  615. #ifndef ENABLE_UNO_BOARD
  616. if(!gu8HifSizeDone)
  617. {
  618. M2M_ERR("(hif) host app didn't set RX Done\n");
  619. ret = hif_set_rx_done();
  620. }
  621. #endif
  622. }
  623. else
  624. {
  625. ret = M2M_ERR_RCV;
  626. M2M_ERR("(hif) Wrong Size\n");
  627. goto ERR1;
  628. }
  629. }
  630. else
  631. {
  632. #ifndef WIN32
  633. M2M_ERR("(hif) False interrupt %lx",reg);
  634. #endif
  635. }
  636. }
  637. else
  638. {
  639. M2M_ERR("(hif) Fail to Read interrupt reg\n");
  640. }
  641. }
  642. ERR1:
  643. return ret;
  644. }
  645. /**
  646. * @fn hif_handle_isr(void)
  647. * @brief Handle interrupt received from NMC1500 firmware.
  648. * @return The function SHALL return 0 for success and a negative value otherwise.
  649. */
  650. void hif_yield(void)
  651. {
  652. gu8Yield = 1;
  653. }
  654. sint8 hif_handle_isr(void)
  655. {
  656. sint8 ret = M2M_SUCCESS;
  657. if (gu8Interrupt) {
  658. ret = hif_chip_wake();
  659. // Sleep(10);
  660. if(ret == M2M_SUCCESS)
  661. {
  662. gu8Yield = 0;
  663. while (gu8Interrupt && !gu8Yield) {
  664. /*must be at that place because of the race of interrupt increment and that decrement*/
  665. /*when the interrupt enabled*/
  666. gu8Interrupt--;
  667. while(1)
  668. {
  669. ret = hif_isr();
  670. if(ret == M2M_SUCCESS/* || gu8Interrupt == 0*/) { //JFM: WTF un while(1)!!!!!
  671. /*we will try forever until we get that interrupt*/
  672. /*Fail return errors here due to bus errors (reading expected values)*/
  673. break;
  674. } else {
  675. M2M_ERR("(HIF) Fail to handle interrupt %d try Again..\n",ret);
  676. }
  677. }
  678. }
  679. ret = hif_chip_sleep();
  680. }
  681. else {
  682. M2M_ERR("(hif) FAIL to wakeup the chip\n");
  683. }
  684. }
  685. return ret;
  686. }
  687. /*
  688. * @fn hif_receive
  689. * @brief Host interface interrupt service routine
  690. * @param [in] u32Addr
  691. * Receive start address
  692. * @param [out] pu8Buf
  693. * Pointer to receive buffer. Allocated by the caller
  694. * @param [in] u16Sz
  695. * Receive buffer size
  696. * @param [in] isDone
  697. * If you don't need any more packets send True otherwise send false
  698. * @return The function shall return ZERO for successful operation and a negative value otherwise.
  699. */
  700. sint8 hif_receive(uint32 u32Addr, uint8 *pu8Buf, uint16 u16Sz, uint8 isDone)
  701. {
  702. uint32 address, reg;
  703. uint16 size;
  704. sint8 ret = M2M_SUCCESS;
  705. if(u32Addr == 0 || pu8Buf == NULL || u16Sz == 0)
  706. {
  707. if(isDone)
  708. {
  709. gu8HifSizeDone = 1;
  710. /* set RX done */
  711. ret = hif_set_rx_done();
  712. if((u32Addr == 0) && (pu8Buf == NULL) && (u16Sz == 0))
  713. return M2M_SUCCESS;
  714. }
  715. ret = M2M_ERR_FAIL;
  716. M2M_ERR(" hif_receive: Invalid argument\n");
  717. goto ERR1;
  718. }
  719. ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_0,&reg);
  720. if(ret != M2M_SUCCESS)goto ERR1;
  721. size = (uint16)((reg >> 2) & 0xfff);
  722. ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_1,&address);
  723. if(ret != M2M_SUCCESS)goto ERR1;
  724. /* Receive the payload */
  725. ret = nm_read_block(u32Addr, pu8Buf, u16Sz);
  726. if(ret != M2M_SUCCESS)goto ERR1;
  727. if(u16Sz > size)
  728. {
  729. ret = M2M_ERR_FAIL;
  730. M2M_ERR("APP Requested Size is larger than the recived buffer size <%d><%d>\n",u16Sz, size);
  731. goto ERR1;
  732. }
  733. if((u32Addr < address)||((u32Addr + u16Sz)>(address+size)))
  734. {
  735. ret = M2M_ERR_FAIL;
  736. M2M_ERR("APP Requested Address beyond the recived buffer address and length\n");
  737. goto ERR1;
  738. }
  739. /* check if this is the last packet */
  740. if(isDone || (((address+size) - (u32Addr+u16Sz)) == 0) ||
  741. ((4 - ((u32Addr+u16Sz) & 3)) == ((address+size) - (u32Addr+u16Sz)))) /* Length in the RCV CTRL 0 register is rounded off to 4 by the firmware,
  742. but length inside the HIF header is not, Hence consider done if number
  743. of rounding bytes equal to length left to read */
  744. {
  745. gu8HifSizeDone = 1;
  746. /* set RX done */
  747. ret = hif_set_rx_done();
  748. }
  749. ERR1:
  750. return ret;
  751. }
  752. /**
  753. * @fn hif_register_cb
  754. * @brief To set Callback function for every component
  755. * @param [in] u8Grp
  756. * Group to which the Callback function should be set.
  757. * @param [in] fn
  758. * function to be set
  759. * @return The function shall return ZERO for successful operation and a negative value otherwise.
  760. */
  761. sint8 hif_register_cb(uint8 u8Grp,tpfHifCallBack fn)
  762. {
  763. sint8 ret = M2M_SUCCESS;
  764. switch(u8Grp)
  765. {
  766. case M2M_REQ_GROUP_IP:
  767. pfIpCb = fn;
  768. break;
  769. case M2M_REQ_GROUP_WIFI:
  770. pfWifiCb = fn;
  771. break;
  772. case M2M_REQ_GROUP_OTA:
  773. pfOtaCb = fn;
  774. break;
  775. case M2M_REQ_GROUP_HIF:
  776. pfHifCb = fn;
  777. break;
  778. case M2M_REQ_GROUP_SIGMA:
  779. pfSigmaCb = fn;
  780. break;
  781. case M2M_REQ_GROUP_SSL:
  782. pfSSLCb = fn;
  783. break;
  784. default:
  785. M2M_ERR("GRp ? %d\n",u8Grp);
  786. ret = M2M_ERR_FAIL;
  787. break;
  788. }
  789. return ret;
  790. }
  791. #endif