sint8 nmi_get_otp_mac_address(uint8 *pu8MacAddr, uint8 * pu8IsValid) { sint8 ret; uint32 u32RegValue; uint8 mac[6]; ret = nm_read_reg_with_ret(rNMI_GP_REG_0, &u32RegValue); if(ret != M2M_SUCCESS) goto _EXIT_ERR; if(!EFUSED_MAC(u32RegValue)) { M2M_DBG("Default MAC\n"); m2m_memset(pu8MacAddr, 0, 6); goto _EXIT_ERR; } M2M_DBG("OTP MAC\n"); u32RegValue >>=16; nm_read_block(u32RegValue|0x30000, mac, 6); m2m_memcpy(pu8MacAddr,mac,6); if(pu8IsValid) *pu8IsValid = 1; return ret; _EXIT_ERR: if(pu8IsValid) *pu8IsValid = 0; return ret; }
sint8 wait_for_firmware_start(uint8 arg) { sint8 ret = M2M_SUCCESS; uint32 reg = 0, cnt = 0; volatile uint32 regAddress = NMI_STATE_REG; volatile uint32 checkValue = M2M_FINISH_INIT_STATE; if(2 == arg) { regAddress = NMI_REV_REG; checkValue = M2M_ATE_FW_IS_UP_VALUE; } else { /*bypass this step*/ } while (checkValue != reg) { nm_bsp_sleep(2); /* TODO: Why bus error if this delay is not here. */ M2M_DBG("%x %x %x\n",(unsigned int)nm_read_reg(0x108c),(unsigned int)nm_read_reg(0x108c),(unsigned int)nm_read_reg(0x14A0)); reg = nm_read_reg(regAddress); if(++cnt > TIMEOUT) { M2M_DBG("Time out for wait firmware Run\n"); ret = M2M_ERR_INIT; goto ERR; } } if(M2M_FINISH_INIT_STATE == checkValue) { nm_write_reg(NMI_STATE_REG, 0); } ERR: return ret; }
sint8 nmi_get_otp_mac_address(uint8 *pu8MacAddr, uint8 * pu8IsValid) { sint8 ret; uint32 u32RegValue; uint8 mac[6]; tstrGpRegs strgp = {0}; ret = nm_read_reg_with_ret(rNMI_GP_REG_2, &u32RegValue); if(ret != M2M_SUCCESS) goto _EXIT_ERR; ret = nm_read_block(u32RegValue|0x30000,(uint8*)&strgp,sizeof(tstrGpRegs)); if(ret != M2M_SUCCESS) goto _EXIT_ERR; u32RegValue = strgp.u32Mac_efuse_mib; if(!EFUSED_MAC(u32RegValue)) { M2M_DBG("Default MAC\n"); m2m_memset(pu8MacAddr, 0, 6); goto _EXIT_ERR; } M2M_DBG("OTP MAC\n"); u32RegValue >>=16; ret = nm_read_block(u32RegValue|0x30000, mac, 6); m2m_memcpy(pu8MacAddr,mac,6); if(pu8IsValid) *pu8IsValid = 1; return ret; _EXIT_ERR: if(pu8IsValid) *pu8IsValid = 0; return ret; }
/** * @fn NMI_API sint8 hif_deinit(void * arg); * @brief To Deinitialize HIF layer. * @param [in] arg * Pointer to the arguments. * @return The function shall return ZERO for successful operation and a negative value otherwise. */ sint8 hif_deinit(void * arg) { sint8 ret = M2M_SUCCESS; #if 0 uint32 reg = 0, cnt=0; while (reg != M2M_DISABLE_PS) { nm_bsp_sleep(1); reg = nm_read_reg(STATE_REG); if(++cnt > 1000) { M2M_DBG("failed to stop power save\n"); break; } } #endif ret = hif_chip_wake(); gu8ChipMode = 0; gu8ChipSleep = 0; gu8HifSizeDone = 0; gu8Interrupt = 0; pfWifiCb = NULL; pfIpCb = NULL; pfOtaCb = NULL; pfHifCb = NULL; return ret; }
sint8 wait_for_bootrom(uint8 arg) { sint8 ret = M2M_SUCCESS; uint32 reg = 0, cnt = 0; reg = 0; while(1) { reg = nm_read_reg(0x1014); /* wait for efuse loading done */ if (reg & 0x80000000) { break; } nm_bsp_sleep(1); /* TODO: Why bus error if this delay is not here. */ } reg = nm_read_reg(M2M_WAIT_FOR_HOST_REG); reg &= 0x1; /* check if waiting for the host will be skipped or not */ if(reg == 0) { reg = 0; while(reg != M2M_FINISH_BOOT_ROM) { nm_bsp_sleep(1); reg = nm_read_reg(BOOTROM_REG); if(++cnt > TIMEOUT) { M2M_DBG("failed to load firmware from flash.\n"); ret = M2M_ERR_INIT; goto ERR2; } } } if(2 == arg) { nm_write_reg(NMI_REV_REG, M2M_ATE_FW_START_VALUE); } else { /*bypass this step*/ } if(REV(nmi_get_chipid()) == REV_3A0) { chip_apply_conf(rHAVE_USE_PMU_BIT); } else { chip_apply_conf(0); } nm_write_reg(BOOTROM_REG,M2M_START_FIRMWARE); #ifdef __ROM_TEST__ rom_test(); #endif /* __ROM_TEST__ */ ERR2: return ret; }
/** * @fn nm_uart_reconfigure * @brief Reconfigures the UART interface * @param [in] ptr * Pointer to a DWORD containing baudrate at this moment. * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure * @author Viswanathan Murugesan * @date 22 OCT 2014 * @version 1.0 */ sint8 nm_uart_reconfigure(void *ptr) { tstrNmUartDefault strUart; sint8 s8Ret = M2M_SUCCESS; uint8 b[HDR_SZ+1]; /*write reg*/ b[0] = 0xa5; b[1] = 5; b[2] = 0; b[3] = 0; b[4] = 0; b[5] = 0; b[6] = 0; b[7] = 0; b[8] = 0; b[9] = (uint8)((*(unsigned long *)ptr) & 0x000000ff); b[10] = (uint8)(((*(unsigned long *)ptr) & 0x0000ff00)>>8); b[11] = (uint8)(((*(unsigned long *)ptr) & 0x00ff0000)>>16); b[12] = (uint8)(((*(unsigned long *)ptr) & 0xff000000)>>24); b[2] = get_cs(&b[1],HDR_SZ); get_cs(&b[1],HDR_SZ); strUart.pu8Buf = b; strUart.u16Sz = sizeof(b); if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) { M2M_ERR("write error\n"); s8Ret = M2M_ERR_BUS_FAIL; } else { if(!nm_bus_get_chip_type()) { //check for the ack from the SAMD21 for the packet reception. strUart.u16Sz = 1; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) { s8Ret = M2M_ERR_BUS_FAIL; } if(b[0] == 0xAC) { M2M_DBG("Successfully sent the UART reconfigure command\n"); } else { M2M_ERR("write error\n"); s8Ret = M2M_ERR_BUS_FAIL; } } } return s8Ret; }
/********************************************************************* Function socket Description Creates a socket. Return - Negative value for error. - ZERO or positive value as a socket ID if successful. Author Ahmed Ezzat Version 1.0 Date 4 June 2012 *********************************************************************/ SOCKET socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags) { SOCKET sock = -1; uint8 u8Count,u8SocketCount = MAX_SOCKET; volatile tstrSocket *pstrSock; /* The only supported family is the AF_INET for UDP and TCP transport layer protocols. */ if(u16Domain == AF_INET) { if(u8Type == SOCK_STREAM) { u8SocketCount = TCP_SOCK_MAX; u8Count = 0; } else if(u8Type == SOCK_DGRAM) { /*--- UDP SOCKET ---*/ u8SocketCount = MAX_SOCKET; u8Count = TCP_SOCK_MAX; } else return sock; for(;u8Count < u8SocketCount; u8Count ++) { pstrSock = &gastrSockets[u8Count]; if(pstrSock->bIsUsed == 0) { m2m_memset((uint8*)pstrSock, 0, sizeof(tstrSocket)); pstrSock->bIsUsed = 1; /* The session ID is used to distinguish different socket connections by comparing the assigned session ID to the one reported by the firmware*/ ++gu16SessionID; if(gu16SessionID == 0) ++gu16SessionID; pstrSock->u16SessionID = gu16SessionID; M2M_DBG("1 Socket %d session ID = %d\r\n",u8Count, gu16SessionID ); sock = (SOCKET)u8Count; if(u8Flags & SOCKET_FLAGS_SSL) { tstrSSLSocketCreateCmd strSSLCreate; strSSLCreate.sslSock = sock; pstrSock->u8SSLFlags = SSL_FLAGS_ACTIVE | SSL_FLAGS_NO_TX_COPY; SOCKET_REQUEST(SOCKET_CMD_SSL_CREATE, (uint8*)&strSSLCreate, sizeof(tstrSSLSocketCreateCmd), 0, 0, 0); } break; } } } return sock; }
NMI_API sint8 m2m_wifi_enable_mac_mcast(uint8* pu8MulticastMacAddress, uint8 u8AddRemove) { sint8 s8ret = M2M_ERR_FAIL; tstrM2MMulticastMac strMulticastMac; if(pu8MulticastMacAddress != NULL ) { strMulticastMac.u8AddRemove = u8AddRemove; m2m_memcpy(strMulticastMac.au8macaddress,pu8MulticastMacAddress,M2M_MAC_ADDRES_LEN); M2M_DBG("mac multicast: %x:%x:%x:%x:%x:%x\r\n",strMulticastMac.au8macaddress[0],strMulticastMac.au8macaddress[1],strMulticastMac.au8macaddress[2],strMulticastMac.au8macaddress[3],strMulticastMac.au8macaddress[4],strMulticastMac.au8macaddress[5]); s8ret = hif_send(M2M_REQ_GRP_WIFI, M2M_WIFI_REQ_SET_MAC_MCAST, (uint8 *)&strMulticastMac,sizeof(tstrM2MMulticastMac),NULL,0,0); } return s8ret; }
/** * @fn hif_Resp_handler(uint8 *pu8Buffer, uint16 u16BufferSize) * @brief Response handler for HIF layer. * @param [in] pu8Buffer Pointer to the buffer. * @param [in] u16BufferSize Buffer size. * @return The function SHALL return 0 for success and a negative value otherwise. */ sint8 hif_Resp_handler(uint8 *pu8Buffer, uint16 u16BufferSize) { uint8 u8WriteIdx = gstrAppReqList.u8WriteIdx; M2M_DBG("m2m_callback %x %x %x\n",pu8Buffer,u16BufferSize,u8WriteIdx); if (gstrAppReqList.astrReq[u8WriteIdx].u8IsUsed) M2M_ERR("APP Req Overflow\n"); gstrAppReqList.astrReq[u8WriteIdx].u8IsUsed = 1; gstrAppReqList.astrReq[u8WriteIdx].pu8ReqBuffer = pu8Buffer; gstrAppReqList.u8WriteIdx++; if (gstrAppReqList.u8WriteIdx >= APP_MAX_NUM_REQ) gstrAppReqList.u8WriteIdx = 0; app_os_sem_up(&gstrAppSem); return 0; }
sint8 chip_deinit(void) { uint32 reg = 0; sint8 ret; uint8 timeout = 10; /** stop the firmware, need a re-download **/ ret = nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); if (ret != M2M_SUCCESS) { M2M_ERR("failed to de-initialize\n"); } reg &= ~(1 << 10); ret = nm_write_reg(NMI_GLB_RESET_0, reg); if (ret != M2M_SUCCESS) { M2M_ERR("Error while writing reg\n"); return ret; } do { ret = nm_read_reg_with_ret(NMI_GLB_RESET_0, ®); if (ret != M2M_SUCCESS) { M2M_ERR("Error while reading reg\n"); return ret; } /*Workaround to ensure that the chip is actually reset*/ if ((reg & (1 << 10))) { M2M_DBG("Bit 10 not reset retry %d\n", timeout); reg &= ~(1 << 10); ret = nm_write_reg(NMI_GLB_RESET_0, reg); timeout--; } else { break; } } while (timeout); return ret; }
sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize, uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset) { sint8 ret = M2M_ERR_SEND; volatile tstrHifHdr strHif; strHif.u8Opcode = u8Opcode&(~NBIT7); strHif.u8Gid = u8Gid; strHif.u16Length = M2M_HIF_HDR_OFFSET; if(pu8DataBuf != NULL) { strHif.u16Length += u16DataOffset + u16DataSize; } else { strHif.u16Length += u16CtrlBufSize; } ret = hif_chip_wake(); if(ret == M2M_SUCCESS) { volatile uint32 reg, dma_addr = 0; volatile uint16 cnt = 0; //#define OPTIMIZE_BUS /*please define in firmware also*/ #ifndef OPTIMIZE_BUS reg = 0UL; reg |= (uint32)u8Gid; reg |= ((uint32)u8Opcode<<8); reg |= ((uint32)strHif.u16Length<<16); ret = nm_write_reg(NMI_STATE_REG,reg); if(M2M_SUCCESS != ret) goto ERR1; reg = 0UL; reg |= NBIT1; ret = nm_write_reg(WIFI_HOST_RCV_CTRL_2, reg); if(M2M_SUCCESS != ret) goto ERR1; #else reg = 0UL; reg |= NBIT1; reg |= ((u8Opcode & NBIT7) ? (NBIT2):(0)); /*Data = 1 or config*/ reg |= (u8Gid == M2M_REQ_GROUP_IP) ? (NBIT3):(0); /*IP = 1 or non IP*/ reg |= ((uint32)strHif.u16Length << 4); /*length of pkt max = 4096*/ ret = nm_write_reg(WIFI_HOST_RCV_CTRL_2, reg); if(M2M_SUCCESS != ret) goto ERR1; #endif dma_addr = 0; for(cnt = 0; cnt < 1000; cnt ++) { ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_2,(uint32 *)®); if(ret != M2M_SUCCESS) break; /* * If it takes too long to get a response, the slow down to * avoid back-to-back register read operations. */ if(cnt >= 500) { if(cnt < 501) { M2M_INFO("Slowing down...\n"); } nm_bsp_sleep(1); } if (!(reg & NBIT1)) { ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_4,(uint32 *)&dma_addr); if(ret != M2M_SUCCESS) { /*in case of read error clear the DMA address and return error*/ dma_addr = 0; goto ERR1; } /*in case of success break */ break; } } if (dma_addr != 0) { volatile uint32 u32CurrAddr; u32CurrAddr = dma_addr; strHif.u16Length=NM_BSP_B_L_16(strHif.u16Length); ret = nm_write_block(u32CurrAddr, (uint8*)&strHif, M2M_HIF_HDR_OFFSET); if(M2M_SUCCESS != ret) goto ERR1; u32CurrAddr += M2M_HIF_HDR_OFFSET; if(pu8CtrlBuf != NULL) { ret = nm_write_block(u32CurrAddr, pu8CtrlBuf, u16CtrlBufSize); if(M2M_SUCCESS != ret) goto ERR1; u32CurrAddr += u16CtrlBufSize; } if(pu8DataBuf != NULL) { u32CurrAddr += (u16DataOffset - u16CtrlBufSize); ret = nm_write_block(u32CurrAddr, pu8DataBuf, u16DataSize); if(M2M_SUCCESS != ret) goto ERR1; u32CurrAddr += u16DataSize; } reg = dma_addr << 2; reg |= NBIT1; ret = nm_write_reg(WIFI_HOST_RCV_CTRL_3, reg); if(M2M_SUCCESS != ret) goto ERR1; } else { ret = hif_chip_sleep(); M2M_DBG("Failed to alloc rx size %d\r",ret); ret = M2M_ERR_MEM_ALLOC; goto ERR2; } } else { M2M_ERR("(HIF)Fail to wakup the chip\n"); goto ERR2; } /*actual sleep ret = M2M_SUCCESS*/ ret = hif_chip_sleep(); return ret; ERR1: /*reset the count but no actual sleep as it already bus error*/ hif_chip_sleep_sc(); ERR2: /*logical error*/ return ret; }
/********************************************************************* Function m2m_ip_cb Description Callback function used by the NMC1000 driver to deliver messages for socket layer. Return None. Author Ahmed Ezzat Version 1.0 Date 17 July 2012 *********************************************************************/ static void m2m_ip_cb(uint8 u8OpCode, uint16 u16BufferSize,uint32 u32Address) { if(u8OpCode == SOCKET_CMD_BIND) { tstrBindReply strBindReply; tstrSocketBindMsg strBind; if(hif_receive(u32Address, (uint8*)&strBindReply, sizeof(tstrBindReply), 0) == M2M_SUCCESS) { strBind.status = strBindReply.s8Status; if(gpfAppSocketCb) gpfAppSocketCb(strBindReply.sock,SOCKET_MSG_BIND,&strBind); } } else if(u8OpCode == SOCKET_CMD_LISTEN) { tstrListenReply strListenReply; tstrSocketListenMsg strListen; if(hif_receive(u32Address, (uint8*)&strListenReply, sizeof(tstrListenReply), 0) == M2M_SUCCESS) { strListen.status = strListenReply.s8Status; if(gpfAppSocketCb) gpfAppSocketCb(strListenReply.sock,SOCKET_MSG_LISTEN, &strListen); } } else if(u8OpCode == SOCKET_CMD_ACCEPT) { tstrAcceptReply strAcceptReply; tstrSocketAcceptMsg strAccept; if(hif_receive(u32Address, (uint8*)&strAcceptReply, sizeof(tstrAcceptReply), 0) == M2M_SUCCESS) { if(strAcceptReply.sConnectedSock >= 0) { gastrSockets[strAcceptReply.sConnectedSock].u8SSLFlags = 0; gastrSockets[strAcceptReply.sConnectedSock].bIsUsed = 1; /* The session ID is used to distinguish different socket connections by comparing the assigned session ID to the one reported by the firmware*/ ++gu16SessionID; if(gu16SessionID == 0) ++gu16SessionID; gastrSockets[strAcceptReply.sConnectedSock].u16SessionID = gu16SessionID; M2M_DBG("Socket %d session ID = %d\r\n",strAcceptReply.sConnectedSock , gu16SessionID ); } strAccept.sock = strAcceptReply.sConnectedSock; strAccept.strAddr.sin_family = AF_INET; strAccept.strAddr.sin_port = strAcceptReply.strAddr.u16Port; strAccept.strAddr.sin_addr.s_addr = strAcceptReply.strAddr.u32IPAddr; if(gpfAppSocketCb) gpfAppSocketCb(strAcceptReply.sListenSock, SOCKET_MSG_ACCEPT, &strAccept); } } else if((u8OpCode == SOCKET_CMD_CONNECT) || (u8OpCode == SOCKET_CMD_SSL_CONNECT)) { tstrConnectReply strConnectReply; tstrSocketConnectMsg strConnMsg; if(hif_receive(u32Address, (uint8*)&strConnectReply, sizeof(tstrConnectReply), 0) == M2M_SUCCESS) { strConnMsg.sock = strConnectReply.sock; strConnMsg.s8Error = strConnectReply.s8Error; if(gpfAppSocketCb) gpfAppSocketCb(strConnectReply.sock,SOCKET_MSG_CONNECT, &strConnMsg); } } else if(u8OpCode == SOCKET_CMD_DNS_RESOLVE) { tstrDnsReply strDnsReply; if(hif_receive(u32Address, (uint8*)&strDnsReply, sizeof(tstrDnsReply), 0) == M2M_SUCCESS) { strDnsReply.u32HostIP = strDnsReply.u32HostIP; if(gpfAppResolveCb) gpfAppResolveCb((uint8*)strDnsReply.acHostName, strDnsReply.u32HostIP); } } else if((u8OpCode == SOCKET_CMD_RECV) || (u8OpCode == SOCKET_CMD_RECVFROM) || (u8OpCode == SOCKET_CMD_SSL_RECV)) { SOCKET sock; sint16 s16RecvStatus; tstrRecvReply strRecvReply; uint16 u16ReadSize; tstrSocketRecvMsg strRecvMsg; uint8 u8CallbackMsgID = SOCKET_MSG_RECV; uint16 u16DataOffset; if(u8OpCode == SOCKET_CMD_RECVFROM) u8CallbackMsgID = SOCKET_MSG_RECVFROM; /* Read RECV REPLY data structure. */ u16ReadSize = sizeof(tstrRecvReply); if(hif_receive(u32Address, (uint8*)&strRecvReply, u16ReadSize, 0) == M2M_SUCCESS) { uint16 u16SessionID = 0; sock = strRecvReply.sock; u16SessionID = strRecvReply.u16SessionID; M2M_DBG("recv callback session ID = %d\r\n",u16SessionID); /* Reset the Socket RX Pending Flag. */ gastrSockets[sock].bIsRecvPending = 0; s16RecvStatus = NM_BSP_B_L_16(strRecvReply.s16RecvStatus); u16DataOffset = NM_BSP_B_L_16(strRecvReply.u16DataOffset); strRecvMsg.strRemoteAddr.sin_port = strRecvReply.strRemoteAddr.u16Port; strRecvMsg.strRemoteAddr.sin_addr.s_addr = strRecvReply.strRemoteAddr.u32IPAddr; if(u16SessionID == gastrSockets[sock].u16SessionID) { if((s16RecvStatus > 0) && (s16RecvStatus < u16BufferSize)) { /* Skip incoming bytes until reaching the Start of Application Data. */ u32Address += u16DataOffset; /* Read the Application data and deliver it to the application callback in the given application buffer. If the buffer is smaller than the received data, the data is passed to the application in chunks according to its buffer size. */ u16ReadSize = (uint16)s16RecvStatus; Socket_ReadSocketData(sock, &strRecvMsg, u8CallbackMsgID, u32Address, u16ReadSize); } else { strRecvMsg.s16BufferSize = s16RecvStatus; strRecvMsg.pu8Buffer = NULL; if(gpfAppSocketCb) gpfAppSocketCb(sock,u8CallbackMsgID, &strRecvMsg); } } else { M2M_DBG("Discard recv callback %d %d \r\n",u16SessionID , gastrSockets[sock].u16SessionID); if(u16ReadSize < u16BufferSize) hif_receive(0, NULL, 0, 1); } } } else if((u8OpCode == SOCKET_CMD_SEND) || (u8OpCode == SOCKET_CMD_SENDTO) || (u8OpCode == SOCKET_CMD_SSL_SEND)) { SOCKET sock; sint16 s16Rcvd; tstrSendReply strReply; uint8 u8CallbackMsgID = SOCKET_MSG_SEND; if(u8OpCode == SOCKET_CMD_SENDTO) u8CallbackMsgID = SOCKET_MSG_SENDTO; if(hif_receive(u32Address, (uint8*)&strReply, sizeof(tstrSendReply), 0) == M2M_SUCCESS) { uint16 u16SessionID = 0; sock = strReply.sock; u16SessionID = strReply.u16SessionID; M2M_DBG("send callback session ID = %d\r\n",u16SessionID); s16Rcvd = NM_BSP_B_L_16(strReply.s16SentBytes); if(u16SessionID == gastrSockets[sock].u16SessionID) { if(gpfAppSocketCb) gpfAppSocketCb(sock,u8CallbackMsgID, &s16Rcvd); } else { M2M_DBG("Discard send callback %d %d \r\n",u16SessionID , gastrSockets[sock].u16SessionID); } } } }
sint8 hif_send(uint8 u8Gid,uint8 u8Opcode,uint8 *pu8CtrlBuf,uint16 u16CtrlBufSize, uint8 *pu8DataBuf,uint16 u16DataSize, uint16 u16DataOffset) { sint8 ret = M2M_ERR_SEND; volatile tstrHifHdr strHif; strHif.u8Opcode = u8Opcode&(~NBIT7); strHif.u8Gid = u8Gid; strHif.u16Length = M2M_HIF_HDR_OFFSET; if(pu8DataBuf != NULL) { strHif.u16Length += u16DataOffset + u16DataSize; } else { strHif.u16Length += u16CtrlBufSize; } ret = hif_chip_wake(); if(ret == M2M_SUCCESS) { volatile uint32 reg, dma_addr = 0; volatile uint16 cnt = 0; reg = 0UL; reg |= (uint32)u8Gid; reg |= ((uint32)u8Opcode<<8); reg |= ((uint32)strHif.u16Length<<16); ret = nm_write_reg(NMI_STATE_REG,reg); if(M2M_SUCCESS != ret) goto ERR1; reg = 0; reg |= (1<<1); ret = nm_write_reg(WIFI_HOST_RCV_CTRL_2, reg); if(M2M_SUCCESS != ret) goto ERR1; dma_addr = 0; //nm_bsp_interrupt_ctrl(0); for(cnt = 0; cnt < 1000; cnt ++) { ret = nm_read_reg_with_ret(WIFI_HOST_RCV_CTRL_2,(uint32 *)®); if(ret != M2M_SUCCESS) break; if (!(reg & 0x2)) { ret = nm_read_reg_with_ret(0x150400,(uint32 *)&dma_addr); if(ret != M2M_SUCCESS) { /*in case of read error clear the dma address and return error*/ dma_addr = 0; } /*in case of success break */ break; } } //nm_bsp_interrupt_ctrl(1); if (dma_addr != 0) { volatile uint32 u32CurrAddr; u32CurrAddr = dma_addr; strHif.u16Length=NM_BSP_B_L_16(strHif.u16Length); ret = nm_write_block(u32CurrAddr, (uint8*)&strHif, M2M_HIF_HDR_OFFSET); #ifdef CONF_WINC_USE_I2C nm_bsp_sleep(1); #endif if(M2M_SUCCESS != ret) goto ERR1; u32CurrAddr += M2M_HIF_HDR_OFFSET; if(pu8CtrlBuf != NULL) { ret = nm_write_block(u32CurrAddr, pu8CtrlBuf, u16CtrlBufSize); #ifdef CONF_WINC_USE_I2C nm_bsp_sleep(1); #endif if(M2M_SUCCESS != ret) goto ERR1; u32CurrAddr += u16CtrlBufSize; } if(pu8DataBuf != NULL) { u32CurrAddr += (u16DataOffset - u16CtrlBufSize); ret = nm_write_block(u32CurrAddr, pu8DataBuf, u16DataSize); #ifdef CONF_WINC_USE_I2C nm_bsp_sleep(1); #endif if(M2M_SUCCESS != ret) goto ERR1; u32CurrAddr += u16DataSize; } reg = dma_addr << 2; reg |= (1 << 1); ret = nm_write_reg(WIFI_HOST_RCV_CTRL_3, reg); if(M2M_SUCCESS != ret) goto ERR1; } else { M2M_DBG("Failed to alloc rx size\r"); ret = M2M_ERR_MEM_ALLOC; goto ERR1; } } else { M2M_ERR("(HIF)Fail to wakup the chip\n"); goto ERR1; } ret = hif_chip_sleep(); ERR1: return ret; }
/** * @fn m2m_wifi_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr, uint8 grp) * @brief WiFi call back function * @param [in] u8OpCode * HIF Opcode type. * @param [in] u16DataSize * HIF data length. * @param [in] u32Addr * HIF address. * @param [in] grp * HIF group type. * @author * @date * @version 1.0 */ static void m2m_wifi_cb(uint8 u8OpCode, uint16 u16DataSize, uint32 u32Addr) { uint8 rx_buf[8]; if (u8OpCode == M2M_WIFI_RESP_CON_STATE_CHANGED) { tstrM2mWifiStateChanged strState; if (hif_receive(u32Addr, (uint8*) &strState,sizeof(tstrM2mWifiStateChanged), 0) == M2M_SUCCESS) { if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_CON_STATE_CHANGED, &strState); } } else if(u8OpCode == M2M_WIFI_RESP_CONN_INFO) { tstrM2MConnInfo strConnInfo; if(hif_receive(u32Addr, (uint8*)&strConnInfo, sizeof(tstrM2MConnInfo), 1) == M2M_SUCCESS) { if(gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_CONN_INFO, &strConnInfo); } } else if (u8OpCode == M2M_WIFI_RESP_MEMORY_RECOVER) { #if 0 if (hif_receive(u32Addr, rx_buf, 4, 1) == M2M_SUCCESS) { tstrM2mWifiStateChanged strState; m2m_memcpy((uint8*) &strState, rx_buf,sizeof(tstrM2mWifiStateChanged)); if (app_wifi_recover_cb) app_wifi_recover_cb(strState.u8CurrState); } #endif } else if (u8OpCode == M2M_WIFI_REQ_DHCP_CONF) { tstrM2MIPConfig strIpConfig; if (hif_receive(u32Addr, (uint8 *)&strIpConfig, sizeof(tstrM2MIPConfig), 0) == M2M_SUCCESS) { if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_REQ_DHCP_CONF, (uint8 *)&strIpConfig.u32StaticIP); } } else if (u8OpCode == M2M_WIFI_REQ_WPS) { tstrM2MWPSInfo strWps; m2m_memset((uint8*)&strWps,0,sizeof(tstrM2MWPSInfo)); if(hif_receive(u32Addr, (uint8*)&strWps, sizeof(tstrM2MWPSInfo), 0) == M2M_SUCCESS) { if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_REQ_WPS, &strWps); } } else if (u8OpCode == M2M_WIFI_RESP_IP_CONFLICT) { tstrM2MIPConfig strIpConfig; if(hif_receive(u32Addr, (uint8 *)&strIpConfig, sizeof(tstrM2MIPConfig), 0) == M2M_SUCCESS) { M2M_DBG("Conflicted IP\"%u.%u.%u.%u\"\n", ((uint8 *)&strIpConfig.u32StaticIP)[0], ((uint8 *)&strIpConfig.u32StaticIP)[1], ((uint8 *)&strIpConfig.u32StaticIP)[2], ((uint8 *)&strIpConfig.u32StaticIP)[3]); if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_IP_CONFLICT, NULL); } } else if (u8OpCode == M2M_WIFI_RESP_SCAN_DONE) { tstrM2mScanDone strState; gu8scanInProgress = 0; if(hif_receive(u32Addr, (uint8*)&strState, sizeof(tstrM2mScanDone), 0) == M2M_SUCCESS) { gu8ChNum = strState.u8NumofCh; if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_SCAN_DONE, &strState); } } else if (u8OpCode == M2M_WIFI_RESP_SCAN_RESULT) { tstrM2mWifiscanResult strScanResult; if(hif_receive(u32Addr, (uint8*)&strScanResult, sizeof(tstrM2mWifiscanResult), 0) == M2M_SUCCESS) { if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_SCAN_RESULT, &strScanResult); } } else if (u8OpCode == M2M_WIFI_RESP_CURRENT_RSSI) { if (hif_receive(u32Addr, rx_buf, 4, 0) == M2M_SUCCESS) { if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_CURRENT_RSSI, rx_buf); } } else if (u8OpCode == M2M_WIFI_RESP_CLIENT_INFO) { if (hif_receive(u32Addr, rx_buf, 4, 0) == M2M_SUCCESS) { if (gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_CLIENT_INFO, rx_buf); } } else if(u8OpCode == M2M_WIFI_RESP_PROVISION_INFO) { tstrM2MProvisionInfo strProvInfo; if(hif_receive(u32Addr, (uint8*)&strProvInfo, sizeof(tstrM2MProvisionInfo), 1) == M2M_SUCCESS) { if(gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_PROVISION_INFO, &strProvInfo); } } else if(u8OpCode == M2M_WIFI_RESP_DEFAULT_CONNECT) { tstrM2MDefaultConnResp strResp; if(hif_receive(u32Addr, (uint8*)&strResp, sizeof(tstrM2MDefaultConnResp), 1) == M2M_SUCCESS) { if(gpfAppWifiCb) gpfAppWifiCb(M2M_WIFI_RESP_DEFAULT_CONNECT, &strResp); } } #ifdef ETH_MODE else if(u8OpCode == M2M_WIFI_RESP_ETHERNET_RX_PACKET) { if(hif_receive(u32Addr, rx_buf ,sizeof(tstrM2mIpRsvdPkt), 0) == M2M_SUCCESS) { tstrM2mIpRsvdPkt * pstrM2MIpRxPkt = (tstrM2mIpRsvdPkt*)rx_buf; tstrM2mIpCtrlBuf strM2mIpCtrlBuf; uint16 u16Offset = pstrM2MIpRxPkt->u16PktOffset; strM2mIpCtrlBuf.u16RemainigDataSize = pstrM2MIpRxPkt->u16PktSz; if((gpfAppEthCb) &&(gau8ethRcvBuf)&& (gu16ethRcvBufSize > 0)) { while (strM2mIpCtrlBuf.u16RemainigDataSize > 0) { if(strM2mIpCtrlBuf.u16RemainigDataSize > gu16ethRcvBufSize) { strM2mIpCtrlBuf.u16DataSize = gu16ethRcvBufSize ; } else { strM2mIpCtrlBuf.u16DataSize = strM2mIpCtrlBuf.u16RemainigDataSize; } if(hif_receive(u32Addr+u16Offset, gau8ethRcvBuf, strM2mIpCtrlBuf.u16DataSize, 0) == M2M_SUCCESS) { strM2mIpCtrlBuf.u16RemainigDataSize -= strM2mIpCtrlBuf.u16DataSize; u16Offset += strM2mIpCtrlBuf.u16DataSize; gpfAppEthCb(M2M_WIFI_RESP_ETHERNET_RX_PACKET, gau8ethRcvBuf, &(strM2mIpCtrlBuf)); } else { break; } } } } } #endif #ifdef CONF_MGMT else if(u8OpCode == M2M_WIFI_RESP_WIFI_RX_PACKET) { tstrM2MWifiRxPacketInfo strRxPacketInfo; if(hif_receive(u32Addr, (uint8*)&strRxPacketInfo, sizeof(tstrM2MWifiRxPacketInfo), 0) == M2M_SUCCESS) { u16DataSize -= sizeof(tstrM2MWifiRxPacketInfo); if(gstrMgmtCtrl.pu8Buf != NULL) { if(u16DataSize > (gstrMgmtCtrl.u16Sz + gstrMgmtCtrl.u16Offset)) { u16DataSize = gstrMgmtCtrl.u16Sz; } u32Addr += sizeof(tstrM2MWifiRxPacketInfo) + gstrMgmtCtrl.u16Offset; if(hif_receive(u32Addr , gstrMgmtCtrl.pu8Buf, u16DataSize, 1) != M2M_SUCCESS) { u16DataSize = 0; } } if(gpfAppMonCb) gpfAppMonCb(&strRxPacketInfo, gstrMgmtCtrl.pu8Buf,u16DataSize); } } #endif else { M2M_ERR("REQ Not defined %d\n",u8OpCode); } }
/** * @fn nm_uart_write_block * @brief Write block of data * @param [in] u32Addr * Start address * @param [in] puBuf * Pointer to the buffer holding the data to be written * @param [in] u16Sz * Number of bytes to write. The buffer size must be >= u16Sz * @return M2M_SUCCESS in case of success and M2M_ERR_BUS_FAIL in case of failure * @author Dina El Sissy * @date 13 AUG 2012 * @version 1.0 */ sint8 nm_uart_write_block(uint32 u32Addr, uint8 *puBuf, uint16 u16Sz) { tstrNmUartDefault strUart; sint8 s8Ret = M2M_SUCCESS; static uint8 au8Buf[HDR_SZ+1]; au8Buf[0] = 0xa5; au8Buf[1] = 3; au8Buf[2] = 0; au8Buf[3] = (uint8)(u16Sz & 0x00ff); au8Buf[4] = (uint8)((u16Sz & 0xff00)>>8); au8Buf[5] = (uint8)(u32Addr & 0x000000ff); au8Buf[6] = (uint8)((u32Addr & 0x0000ff00)>>8); au8Buf[7] = (uint8)((u32Addr & 0x00ff0000)>>16); au8Buf[8] = (uint8)((u32Addr & 0xff000000)>>24); au8Buf[9] = 0; au8Buf[10] = 0; au8Buf[11] = 0; au8Buf[12] = 0; au8Buf[2] = get_cs(&au8Buf[1],HDR_SZ); strUart.pu8Buf = au8Buf; strUart.u16Sz = sizeof(au8Buf); if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) { M2M_ERR("write error\n"); s8Ret = M2M_ERR_BUS_FAIL; } else { if(!nm_bus_get_chip_type()) { //check for the ack from the SAMD21 for the packet reception. strUart.u16Sz = 1; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) { s8Ret = M2M_ERR_BUS_FAIL; } if(au8Buf[0] == 0xAC) { M2M_DBG("Successfully sent the block Write command\n"); strUart.pu8Buf = puBuf; strUart.u16Sz = u16Sz; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) { M2M_ERR("write error\n"); s8Ret = M2M_ERR_BUS_FAIL; } else { //check for the ack from the SAMD21 for the payload reception. strUart.pu8Buf = au8Buf; strUart.u16Sz = 1; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) { s8Ret = M2M_ERR_BUS_FAIL; } if(au8Buf[0] == 0xAC) { M2M_DBG("Successfully sent the data payload\n"); } else { M2M_ERR("write error\n"); s8Ret = M2M_ERR_BUS_FAIL; } } } else { M2M_ERR("write error (Error sending the block write command)\n"); s8Ret = M2M_ERR_BUS_FAIL; } } else { strUart.pu8Buf = puBuf; strUart.u16Sz = u16Sz; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) { M2M_ERR("write error\n"); s8Ret = M2M_ERR_BUS_FAIL; } } } return s8Ret; }
sint8 nm_uart_read_reg_with_ret(uint32 u32Addr, uint32* pu32RetVal) { tstrNmUartDefault strUart; sint8 s8Ret = M2M_SUCCESS; uint8 b [HDR_SZ+1]; uint8 rsz; /*read reg*/ b[0] = 0xa5; b[1] = 0; b[2] = 0; b[3] = 0; b[4] = 0; b[5] = (uint8)(u32Addr & 0x000000ff); b[6] = (uint8)((u32Addr & 0x0000ff00)>>8); b[7] = (uint8)((u32Addr & 0x00ff0000)>>16); b[8] = (uint8)((u32Addr & 0xff000000)>>24); b[9] = 0; b[10] = 0; b[11] = 0; b[12] = 0; b[2] = get_cs(&b[1],HDR_SZ); rsz = 4; strUart.pu8Buf = b; strUart.u16Sz = sizeof(b); if(M2M_SUCCESS == nm_bus_ioctl(NM_BUS_IOCTL_W, &strUart)) { if(!nm_bus_get_chip_type()) { strUart.u16Sz = 1; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) { s8Ret = M2M_ERR_BUS_FAIL; } if(b[0] == 0xAC) { M2M_DBG("Successfully sent the command\n"); strUart.u16Sz = rsz; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) { s8Ret = M2M_ERR_BUS_FAIL; } } else { s8Ret = M2M_ERR_BUS_FAIL; } } else { strUart.u16Sz = rsz; if(M2M_SUCCESS != nm_bus_ioctl(NM_BUS_IOCTL_R, &strUart)) { s8Ret = M2M_ERR_BUS_FAIL; } } } else { M2M_ERR("failed to send cfg bytes\n"); s8Ret = M2M_ERR_BUS_FAIL; } /*TODO: this should be the way we read the register since the cortus is little endian*/ /**pu32RetVal = b[0] | ((uint32)b[1] << 8) | ((uint32)b[2] << 16) | ((uint32)b[3] << 24);*/ *pu32RetVal = ((uint32)b[0] << 24) | ((uint32)b[1] << 16) | ((uint32)b[2] << 8) | b[3]; return s8Ret; }