📄 halrtl8019as.c
字号:
* 根据读取接收计数寄存器的值,来得到接收数据包的长度。 * * @param[in] vpHalDevData:指针,指向HAL数据表(T_HAL_RTL8019AS_DEV_DATA)。 * @param[out] wpKtLen:指针,数据包的长度。 * * @return 成功返回TRUE;否则,返回FALSE。 */T_BOOL RTL8019AS_GetPktLen(T_VOID *vpHalDevData, T_WORD *wpKtLen){ T_HAL_RTL8019AS_DEV_DATA *pDevData = (T_HAL_RTL8019AS_DEV_DATA *)vpHalDevData; //用户可在此处添加代码: T_UWORD thisFrame; T_UWORD currentOffset; T_UWORD headSize; T_UHWORD count = 0; T_UBYTE keepCmd; T_UBYTE frame; EN_PKTHEADER_T rxFrame; BSP_InByte(pDevData->IoBaseAddr,keepCmd); //读出命令寄存器的值并保存。 /// Get the rx page (incoming packet pointer). BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE1); //设置命令寄存器:无DMA,寄存器页为1页。 BSP_InByte(pDevData->IoBaseAddr + EN1_CURPAG,pDevData->rxingPage); //读取当前写入页面指针(写入网卡缓存的数据首地址)。 if(!pDevData->flag) //如果没有接收到正确的数据。 {NonCopy_Return: pDevData->currentPage = pDevData->rxingPage; //重新设定当前页面位置。 BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE0); //设置命令寄存器:无DMA,寄存器页为0页。 BSP_OutByte(pDevData->IoBaseAddr + EN0_BOUNDARY, pDevData->rxingPage - 1);//设置边界寄存器:当前写入地址-1。 BSP_OutByte(pDevData->IoBaseAddr, keepCmd); //恢复先前保存的命令寄存器的值。 return FALSE; } else //接收到了正确的信息。 { if(pDevData->currentPage == pDevData->rxingPage) //写入页面指针无变化。 { BSP_OutByte(pDevData->IoBaseAddr, keepCmd); //恢复先前保存的命令寄存器的值。 return FALSE; } BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE0); //设置命令寄存器:无DMA,寄存器页为0页。 BSP_InByte(pDevData->IoBaseAddr + EN0_BOUNDARY,frame); //读页指针移动一,到当前写入数据地址(写页指针)。 thisFrame = frame + 1; thisFrame = RTL8019AS_RingIndex(pDevData, thisFrame); //设定指针的循环(接收循环FIFO队列)。 if(thisFrame != pDevData->currentPage) //读页指针不等于写页指针。 { thisFrame = pDevData->currentPage; //调整读页指针等于写页指针。 } currentOffset = thisFrame << 8; //由页(256byte)地址的到实际地址。 headSize = sizeof(rxFrame); RTL8019AS_BlockInput(headSize, (T_BYTE*) & rxFrame, currentOffset,pDevData); //获取包头数据。 if(!RTL8019AS_CheckFrame(pDevData, thisFrame ,(EN_PKTHEADER_T*) & rxFrame))//检查包头信息判断这个包中的数据是否正确。 { BSP_OutByte(pDevData->IoBaseAddr, keepCmd); //恢复先前保存的命令寄存器的值。 return FALSE; } pDevData->currentPage = rxFrame.next; //设定当前页面为接收包的下一页。 if((rxFrame.status & 0x0F) == ENRSR_RXOK) //接收到正确的包。 { count = rxFrame.count - headSize; //有效数据长度:接收到的数据长度减去包头长度。 } else //如果没有接收到正确的包 { goto NonCopy_Return; } //记录下在GetPktData中需要使用到的数据 pDevData->next = rxFrame.next; pDevData->curOffset = currentOffset; pDevData->headSize = headSize; } *wpKtLen = count; //将数据包长度值传给上层提供的参数。 BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE0);//设置命令寄存器:无DMA,寄存器页为0页。 BSP_OutByte(pDevData->IoBaseAddr + EN0_ISR,ENISR_PRX + ENISR_RXE); //清中断状态寄存器。 BSP_OutByte(pDevData->IoBaseAddr, keepCmd); //恢复先前保存的命令寄存器的值。 pDevData->flag = 0; return TRUE;}/** * @brief * 功能: * 获取接收到的数据。 * * 实现内容: * 拷贝已经接收的数据到指针(bpKtBuf)所指向的内存空间。 * * @param[in] vpHalDevData:指针,指向HAL数据表(T_HAL_RTL8019AS_DEV_DATA)。 * @param[in] bpKtBuf:指针,指向数据缓冲区。 * @param[in] wKtLen:数据包的长度,该参数即GetPktLen的返回值。 * * @return 成功返回TRUE;否则,返回FALSE。 */T_BOOL RTL8019AS_GetPktData(T_VOID *vpHalDevData, T_BYTE *bpKtBuf, T_WORD wKtLen){ T_HAL_RTL8019AS_DEV_DATA *pDevData = (T_HAL_RTL8019AS_DEV_DATA *)vpHalDevData; //用户可在此处添加代码: T_UWORD current_offset; T_UBYTE keepCmd; BSP_InByte(pDevData->IoBaseAddr, keepCmd); //记录基地址 //设置参数 current_offset = pDevData->curOffset + pDevData->headSize; RTL8019AS_BlockInput(wKtLen , bpKtBuf , current_offset,pDevData); //接收数据到分配的缓冲区中 /// set next recieve page 重新设定指针,指向当前最后1个数据所在的位置 BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA+ENCMD_PAGE0); BSP_OutByte(pDevData->IoBaseAddr + EN0_BOUNDARY, pDevData->next - 1); BSP_OutByte(pDevData->IoBaseAddr,keepCmd); return TRUE;}/** * @brief * 功能: * 获取设备的中断类型。 * * 实现内容: * 通过读取中断状态寄存器,来判断设备有无中断发生,若有中断产生,则判断是接收、发送、错误中断。 * 注:如果产生相应的设备中断,清除对应的中断标志位。 * * @param[in] vpHalDevData:指针,指向HAL数据表(T_HAL_RTL8019AS_DEV_DATA)。 * @param[in] uwVector:中断向量。 * @param[out] wpIntInfo:指针,中断信息。 * * @return * DEV_NO_INTERRUPT: 无中断产生。 * DEV_INT_HAD_HANDLED: 硬件中断处理。 * DEV_RECEIVE_INTERRUPT: 接收中断产生。 * DEV_SENDOVER_INTERRUPT: 发送中断产生。 * DEV_OTHER_INTTYPE: 其他的中断类型。 * 当发生多种中断时,把相应中断类型位或运算后返回。 */T_UWORD RTL8019AS_GetIntType(T_VOID *vpHalDevData, T_UWORD uwVector, T_WORD *wpIntInfo){ T_HAL_RTL8019AS_DEV_DATA *pDevData = (T_HAL_RTL8019AS_DEV_DATA *)vpHalDevData; //用户可在此处添加代码: T_UBYTE keepCmd; T_WORD isrStatus; T_UWORD ret = 0; BSP_InByte(pDevData->IoBaseAddr,keepCmd); //读出命令寄存器的值并保存。 BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE0); //设置命令寄存器:无DMA,寄存器页为0页。 BSP_InByte(pDevData->IoBaseAddr + EN0_ISR,isrStatus); isrStatus = (isrStatus & ENISR_PART); //读中断状态寄存器获取中断类型(不处理发送完成中断)。 BSP_OutByte(pDevData->IoBaseAddr +EN0_ISR,0xff); //清中断状态寄存器。 if(isrStatus & ENISR_OVW) //网卡接收缓冲区溢出,做重启芯片处理。 { RTL8019AS_HandlerOverflow(pDevData); ret |= DEV_INT_HAD_HANDLED; } if(0 == (isrStatus & (ENISR_PRX | ENISR_RXE | ENISR_TXE | ENISR_OVW | ENISR_CNT))) { ret |= DEV_NO_INTERRUPT; } if(isrStatus & (ENISR_PRX | ENISR_RXE))//接收中断。 { ret|= DEV_RECEIVE_INTERRUPT; if( isrStatus & ENISR_PRX ) //正确接收数据,做接收处理。 { pDevData->flag = 1; } else //接受错误过多,调整指针,但不接收数据。 { pDevData->flag = 0; } } if(isrStatus & (ENISR_TXE | ENISR_CNT))//冲突过多导致传送失败,网络记数器记数。 { ret |= DEV_OHER_INTTYPE ; } BSP_OutByte(pDevData->IoBaseAddr, keepCmd); //恢复先前保存的命令寄存器的值。 *wpIntInfo = isrStatus; //将中断状态传给上层传入的参数。 BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE0 + ENCMD_START);//调试时添加 return ret;}/** * @brief * 功能: * 处理其他类型的中断。 * * 实现内容: * 根据中断类型,作相应的处理。 * * @param[in] vpHalDevData:指针,指向HAL数据表(T_HAL_RTL8019AS_DEV_DATA)。 * @param[in] wpIntInfo: 中断状态信息。 * * @return 成功返回TRUE;否则,返回FALSE。 */T_BOOL RTL8019AS_HandleOtherIsrType(T_VOID *vpHalDevData, T_WORD wIntInfo){ T_HAL_RTL8019AS_DEV_DATA *pDevData = (T_HAL_RTL8019AS_DEV_DATA *)vpHalDevData; //用户可在此处添加代码: T_WORD isrStatus; isrStatus = wIntInfo; if(isrStatus & ENISR_TXE) //冲突过多导致传送失败,重发INT judge { BSP_OutByte(pDevData->IoBaseAddr + EN0_ISR, ENISR_TXE); //清中断中断状态寄存器。 } if(isrStatus & ENISR_CNT) //网络记数器的MSB设置完成。 { RTL8019AS_UpdateCounters(pDevData); //刷新网络记数器。 } return TRUE;}/** * @brief * 功能: * 获取设备的网络连接情况。 * * 实现内容: * 读取相关寄存器的值,来判断网络的连接情况。 * * @param[in] vpHalDevData:指针,指向HAL数据表(T_HAL_RTL8019AS_DEV_DATA)。 * @param[out] wplineStatus:连接状态。 * ETHER_IFOPERSTATUS_UP: 在线。 * ETHER_IFOPERSTATUS_DOWN:离线。 * * @return 成功返回TRUE;否则,返回FALSE。 */T_BOOL RTL8019AS_LineCheck(T_VOID *vpHalDevData, T_WORD *wplineStatus){ T_HAL_RTL8019AS_DEV_DATA *pDevData = (T_HAL_RTL8019AS_DEV_DATA *)vpHalDevData; //用户可在此处添加代码: T_UWORD currentOffset; T_UWORD outputPage = pDevData->txStartPage; T_UBYTE tsrStatus; T_UBYTE isrStatus; T_BYTE buf[60]; T_WORD i; T_WORD wait = 0; T_WORD retval = 0; for(i = 0; i < 60; i++) { buf[i] = i; } BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_PAGE0 + ENCMD_START + ENCMD_NODMA);//设置命令寄存器:寄存器页为0页,打开包接收/发送,无DMA。 BSP_OutByte(pDevData->IoBaseAddr + EN0_IMR,0x00); //设置中断控制寄存器:屏蔽所有中断。 currentOffset = outputPage << 8; RTL8019AS_BlockOutput(pDevData, 60,(T_BYTE *)buf, currentOffset); //将用户BUF 中的数据发送到网卡发送缓冲中。 retval = RTL8019AS_TriggerSend(pDevData, 60); //将网卡缓冲中数据发送到网络并判断是否成功。 if (retval != 0) { *wplineStatus = DNET_IFOPERSTATUS_DOWN; return FALSE; } BSP_OutByte(pDevData->IoBaseAddr + EN_CMD,ENCMD_NODMA + ENCMD_PAGE0); //设置命令寄存器:无DMA,寄存器页为0页。 BSP_InByte(pDevData->IoBaseAddr + EN0_ISR,isrStatus); //读中断状态寄存器。 while (!(isrStatus & 0xa) && (wait < 5000)) { BSP_InByte(pDevData->IoBaseAddr + EN0_ISR,isrStatus); //等待发送完成(通过获取发送完成中断状态实现)。 wait++; } BSP_OutByte(pDevData->IoBaseAddr + EN0_ISR,0xa); //清中断状态寄存器。 BSP_InByte(pDevData->IoBaseAddr + EN0_TSR,tsrStatus); //读传输状态寄存器获取数据包传输状态。 if(tsrStatus & (ENTSR_CRS | ENTSR_CDH)) //传输过程中数据包丢失或者传送器传送信号失败。 { *wplineStatus = DNET_IFOPERSTATUS_DOWN; return FALSE; } *wplineStatus = DNET_IFOPERSTATUS_UP; return TRUE;}/** * @brief * 获取设备的MAC地址 * * @param[in] vpHalDevData:设备数据块指针,该结构的类型由HAL定义 * @param[out] cpMacAddr:存放MAC地址的缓存 * * @return * FALSE 失败 * TRUE 成功 */T_BOOL RTL8019AS_GetMacAddr(T_VOID *vpHalDevData, T_CHAR *cpMacAddr){ T_HAL_RTL8019AS_DEV_DATA *pDevData = (T_HAL_RTL8019AS_DEV_DATA *)vpHalDevData; //用户可在此处添加代码: T_WORD i; T_CHAR keepCmd; BSP_InByte(pDevData->IoBaseAddr, keepCmd); //读出命令寄存器的值并保存。 BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE1 + ENCMD_STOP); //设置命令寄存器:寄存器页为1页,无DMA,关闭包接收/发送。 for(i=0;i<6;i++) { BSP_InByte(pDevData->IoBaseAddr + EN1_PHYS + i, pDevData->macaddr[i]); //将MAC地址从寄存器中取出存放到数组中。 } memcpy(cpMacAddr,pDevData->macaddr,6); //将MAC地址传给上层提供的参数。 BSP_OutByte(pDevData->IoBaseAddr,keepCmd); //恢复先前保存的命令寄存器的值。 return TRUE;}/** * @brief * 设置设备的MAC地址 * * @param[in] vpHalDevData:设备数据块指针,该结构的类型由HAL定义 * @param[in] cpMacAddr:存放MAC地址的缓存 * * @return * FALSE 失败 * TRUE 成功 */T_BOOL RTL8019AS_SetMacAddr(T_VOID *vpHalDevData, T_CHAR *cpMacAddr){ T_HAL_RTL8019AS_DEV_DATA *pDevData = (T_HAL_RTL8019AS_DEV_DATA *)vpHalDevData; //用户可在此处添加代码: T_WORD i; T_UBYTE keep_cmd; BSP_InByte(pDevData->IoBaseAddr, keep_cmd ); //读出命令寄存器的值并保存。 BSP_OutByte(pDevData->IoBaseAddr + EN_CMD, ENCMD_NODMA + ENCMD_PAGE1 + ENCMD_STOP); for(i = 0; i < 6; i++) { pDevData->macaddr[i] = cpMacAddr[i]; //将MAC地址写入RTL8019网卡设备的PAR0-PAR5寄存器。 BSP_OutByte(pDevData->IoBaseAddr + EN1_PHYS + i, pDevData->macaddr[i]); } BSP_OutByte(pDevData->IoBaseAddr,keep_cmd); //恢复先前保存的命令寄存器的值。 return TRUE;}/** * @brief * 增加一个组播地址到该网卡 * * @param[in] vpHalDevData 设备数据块指针,该结构的类型由HAL定义 * * @param[in] bMacAddr 指向一个6字节的存储空间,内容为需要增加的组播MAC地址 *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -