/*************************************************************************************************************
* 文件名: EMAC.h
* 功能: M48x EMAC控制器驱动
* 作者: cp1300@139.com
* 创建时间: 2021-10-09
* 最后修改时间: 2021-10-09
* 详细:
*************************************************************************************************************/
#ifndef _M48x_EMAC_H_
#define _M48x_EMAC_H_
#include "system.h"
#define EMAC_RXD_DESC_SIZE 3 //接收数据描述符数量,必须大于1
#define EMAC_TXD_DESC_SIZE 4 //发送数据描述符数量,必须大于1
#define EMAC_RXMS_LENGTH 1518 //数据帧长度限制1514+4
#define EMAC_INT_RX_PRO SYS_INT_EMAC_RX_PRO //EMAC接收中断优先级
#define EMAC_INT_TX_PRO SYS_INT_EMAC_TX_PRO //EMAC发送中断优先级
//中断定义===================================================================================================
//发送相关中断 MIEN MISTA
#define EMAC_TX_TIME_STAMP_ALARM_INT (1<<28) //时间戳报警中断
#define EMAC_TX_ERROR_INT (1<<24) //发送传输总线错误中断
#define EMAC_TX_DMA_ERROR_INT (1<<23) //发送描述符不可用,DMA传输错误中断
#define EMAC_TX_LATE_ERROR_INT (1<<22) //后期冲突中断-文档不够详细,没法理解这个是啥意思
#define EMAC_TX_ABORT_INT (1<<21) //传输终止中断
#define EMAC_TX_NO_CARRIER_INT (1<<20) //发送时无载波侦听中断
#define EMAC_TX_TIMEOUT_INT (1<<19) //发送超时中断
#define EMAC_TX_OK_INT (1<<18) //发送完成中断
#define EMAC_TX_FIFO_UNDER_INT (1<<17) //发送FIFO下溢中断-发送FIFO数据不多了,可以写数据了
#define EMAC_TX_TOTAL_INT (1<<16) //发送相关的总中断
#define EMAC_TX_ALL_INT (0xFFFF0000) //所有的发送中断
//接收相关中断
#define EMAC_RX_MAGIC_INT (1<<15) //魔术包接收中断-用于数据包唤醒
#define EMAC_RX_CONTROL_FRAME_INT (1<<14) //控制帧接收中断
#define EMAC_RX_ERROR_INT (1<<11) //接收总线错误中断
#define EMAC_RX_DMA_ERROR_INT (1<<10) //接收描述符不可用,DMA传输错误中断
#define EMAC_RX_DMA_EARLY_INT (1<<9) //DMA收到数据包
#define EMAC_RX_MAX_FRAME_INT (1<<8) //最大帧长度超过中断
#define EMAC_RX_MISS_INT (1<<7) //丢包计数器溢出中断-接收超时了
#define EMAC_RX_RUNT_INT (1<<6) //欠缺数据包中断-没理解
#define EMAC_RX_ALIGNMENT_ERROR_INT (1<<5) //对准错误中断-没理解
#define EMAC_RX_OK_INT (1<<4) //收到良好中断
#define EMAC_RX_LONG_INT (1<<3) //长数据包中断
#define EMAC_RX_FIFO_OVER_INT (1<<2) //接收FIFO溢出中断
#define EMAC_RX_CRC_ERROR_INT (1<<1) //CRC错误中断
#define EMAC_RX_TOTAL_INT (1<<0) //接收相关的总中断
#define EMAC_RX_ALL_INT (0x0000FFFF) //所有的接收中断
//所有中断
#define EMAC_ALL_INT_MASK (0xFFFFFFFF) //所有中断掩码
//状态 MGSTA
#define EMAC_STATUS_PRAU (1<<12) //远程暂停状态
#define EMAC_STATUS_TXHA (1<<11) //发送停止
#define EMAC_STATUS_SQE (1<<10) //信号质量差,出现SQE错误
#define EMAC_STATUS_PAU (1<<9) //传输已暂停
#define EMAC_STATUS_DEF (1<<8) //延迟传输
#define EMAC_STATUS_RXFFULL (1<<2) //RX FIFO已满
#define EMAC_STATUS_RXHA (1<<1) //接收停止
#define EMAC_STATUS_CFR (1<<0) //收到控制帧
#define EMAC_STATUS_ALL_MASK 0x1F0F //所有状态掩码
//EMAC地址过滤规则
typedef enum
{
MAC_FILTER_INVALID = 0, //关闭MAC地址过滤
MAC_FILTER_ENABLE_TARGET = 1, //允许目标MAC地址数据包接收
MAC_FILTER_DISABLE_TARGET = 2, //禁止目标MAC地址数据包接收
}EMAC_MAC_FILTER;
//RX DMA描述符状态
typedef union
{
u32 FrameStatus_u32;
struct
{
u32 ReceCount : 16; //BIT15-BIT0;记录当前数据缓冲区中的帧长度
u32 ReceInterrupt : 1; //BIT16;1:当前帧导致的接收中断;0:不是当前帧导致的接收中断
u32 CRC_Error : 1; //BIT17;1:接收帧发送CRC校验错误;0:无校验错误
u32 Reserved18 : 1; //保留
u32 LongPacket : 1; //BIT19;1:长帧(大于1518字节);0:不是长帧
u32 FrameComplete : 1; //BIT20;1:帧接收完成;0:帧接收未完成
u32 AlignmentError : 1; //BIT21;1:帧不是字节的倍数;0:帧是字节的倍数
u32 RuntPacket : 1; //BIT22;1:代表接收的是短帧(小于64字节);0:接收的不是短帧
u32 TimeStampAction : 1; //BIT23;1:代表接收时间戳有效;0:接收时间戳无效
u32 Reserved24_30 : 7; //保留
u32 Ownership : 1; //BIT31;1:代表DMA还未开始接收数据;0:DMA已经将数据接收完了
}b;
} EMAC_RXDMA_FrameStatus;
//DMA描述符地址或时间戳
typedef union
{
u32 BuffAddr;
u32 TimeStamp;
} EMAC_DMA_Addr_Time;
//EMAC接收DMA描述符
typedef struct
{
EMAC_RXDMA_FrameStatus FrameStatus; //帧状态
EMAC_DMA_Addr_Time FrameAddrTimeL; //当前帧接收缓冲区地址或接收时间戳低32bit,写的时候是接收BUFF地址,数据接收完成后,读取的是时间戳
u32 Reserved;
EMAC_DMA_Addr_Time NextAddrTimeH; //指向下一个描述符地址或接收时间戳高32bit,写的时候是指向下一个接收描述符的地址,数据接收成后,读取的是时间戳
u32 RxBuffAddr; //记录接收缓冲区地址
}EMAC_RXDMA_Struct;
//TX DMA描述符控制
typedef union
{
u32 FrameControl_u32;
struct
{
u32 EnablePadding : 1; //BIT0;1:使能此帧填充功能(不足60字节帧需要进行填充);0:不使能填充
u32 EnableCRC : 1; //BIT1;1:使能此帧添加CRC校验(4B);0:不使能此帧添加校验
u32 EnableInterrupt : 1; //BIT2;1:使能此帧发送完后触发中断;0:不使能中断
u32 EnableTimeStamp : 1; //BIT3;1:使能发送时间戳;0:不使能时间戳
u32 Reserved4_30 : 27; //保留
u32 Ownership : 1; //BIT31;1:代表DMA还未将数据发送完;0:DMA已经将数据发送完了
}b;
} EMAC_TXDMA_FrameControl;
//TX DMA描述符状态
typedef union
{
u32 FrameStatus_u32;
struct
{
u32 TranCount : 16; //BIT15-BIT0;当前发送缓冲区中帧的长度
u32 TranInterrupt : 1; //BIT16;1:数据包传输完成后触发了发送完成中断;0:没有触发中断
u32 TranDeferrce : 1; //BIT17;1:数据包传输被推迟一次;0:数据包传输没有被延迟
u32 Reserved18 : 1; //保留
u32 TranComplete : 1; //BIT19;1:数据包传输完成;0:数据包传输未完成(发送了错误或者人为结束通讯了)
u32 FrameDelay : 1; //BIT20;1:等待传输的帧延迟超过0.32768ms(100Mbps)或3.2768ms(10Mbps);0:等待传输的帧未延时;在禁用MCMDR的NDEF位并且EMAC在半双工模式下运行时有效
u32 NoCarrier : 1; //BIT21;1:CRS信号正确激活;0:没有收到CRS信号;仅当EMAC在半双工模式下运行时,NCS才可用。
u32 TranAbort : 1; //BIT22;1:数据包发生了16次连续冲突,导致发送终止;0:未冲突
u32 LateCollision : 1; //BIT23;1:发送数据发生冲突;0:未发生冲突;仅当EMAC在半双工模式下运行时才进行后期冲突检查。
u32 TranHalted : 1; //BIT24;1:下一个数据传输停止;0:下一个数据包正常传输(当MCMDR的TXON被禁用后,会出现传输停止)
u32 TranPaused : 1; //BIT25;1:代表下一个包传输过程暂停;0:下一个包正常传输
u32 SQE_Error : 1; //BIT26;1:代表发送完数据后出现SQE错误;0:未出现SQE错误;SQE指示在10Mbps半双工的数据包传输结束时发现的SQE错误
u32 TimeStampAction : 1; //BIT27;1:代表发送时间戳有效;0:发送时间戳无效
u32 CollsionCount : 4; //BIT31-BIT28;发送碰撞/冲突计数器
}b;
} EMAC_TXDMA_FrameStatus;
//EMAC发送DMA描述符
typedef struct
{
EMAC_TXDMA_FrameControl FrameControl; //帧控制
EMAC_DMA_Addr_Time FrameAddrTimeL; //当前帧发送缓冲区地址或接发送间戳低32bit,写的时候是发送BUFF地址,数据发送完成后,读取的是时间戳
EMAC_TXDMA_FrameStatus FrameStatus; //帧状态
EMAC_DMA_Addr_Time NextAddrTimeH; //指向下一个描述符地址或发送时间戳高32bit,写的时候是指向下一个发送描述符的地址,数据发送成后,读取的时候是时间戳
}EMAC_TXDMA_Struct;
//相关硬件API接口
void EMAC_Init(void); //EMAC控制器初始化
void EMAC_SetTxInt_Callback(void (*pEMACx_TxInt_Callback)(u32 IntStatus));//EMAC控制器发送中断回调设置
void EMAC_SetRxInt_Callback(void (*pEMACx_RxInt_Callback)(u32 IntStatus));//EMAC控制器接收中断回调设置
void EMAC_SetPHYAddr(u8 addr); //EMAC设置当前通道的PHY地址
bool EMAC_WritePHY(u8 RegAddr, u16 data); //EMAC写命令到PHY
bool EMAC_ReadPHY(u8 RegAddr, u16 *pData); //EMAC读取PHY寄存器
void EMAC_EnableRxMacFilter(EMAC_MAC_FILTER MacFilter); //EMAC地址过滤总模式设置
void EMAC_EnableRxBroadcastPacket(bool isEnable); //EMAC广播数据包接收使能
void EMAC_EnableRxMulticastPacket(bool isEnable); //EMAC多播(组播)数据包接收使能
void EMAC_EnableRxUnicastPacket(bool isEnable); //EMAC单播数据包接收使能
void EMAC_EnableRxMacChannelVerification(u16 ChannelBit); //EMAC数据包接收MAC过滤通道使能,每个bit代表一个通道(0-12)
void EMAC_DisableRxMacChannelVerification(u16 ChannelBit); //数据包接收MAC过滤通道关闭,每个bit代表一个通道(0-12)
void EMAC_SetRxMacChannelValue(u8 Channel_n, const u8 MAC[6]); //设置指定的MAC地址过滤通道MAC地址(0-12)
void EMAC_Enable100MpbsMode(bool isEnable); //使能100M模式,否则为10M
void EMAC_EnableFullDuplexMode(bool isEnable); //使能全双工模式,否则为半双工
void EMAC_EnableSQECheeck(bool isEnable); //使能SQE检查(仅用于10M半双工模式)
void EMAC_EnableNDEF(bool isEnable); //使能NDEF延时超时计数器(仅在半双工模式下有效)
void EMAC_EnableWakeUp(bool isEnable); //使能网络唤醒(通过魔术包唤醒)
void EMAC_EnableACP(bool isEnable); //使能接收控制帧(建议仅当EMAC在全双工模式下运行时使用)
void EMAC_EnableRuntARP(bool isEnable); //使能接收不足64字节的ARP数据包
void EMAC_EnableLongPacket(bool isEnable); //使能接收长数据包
void EMAC_EnableTxData(bool isEnable); //使能发送数据
void EMAC_EnableRxData(bool isEnable); //使能接收数据
void EMAC_EnableInt(u32 IntMask); //开启相关中断
void EMAC_DisableInt(u32 IntMask); //关闭相关中断
void EMAC_ClearInt(u32 IntMask); //清除中断
void EMAC_ClearStatus(u32 StatusMask); //清除状态
u32 EMAC_GetIntStatus(void); //获取中断状态
u32 EMAC_GetStatus(void); //获取状态
void EMAC_SetTXDMA_LLA(EMAC_TXDMA_Struct *pLLA); //设置发送数据DMA链表地址
void EMAC_SetRXDMA_LLA(EMAC_RXDMA_Struct *pLLA); //设置接收数据DMA链表地址
void EMAC_TXDMA_Restart(void); //重启发送DMA(当前TX描述符无效后需要进行调用)
void EMAC_RXDMA_Restart(void); //重启接收DMA(当接收描述符无效后需要进行调用)
u64 EMAC_GetTimeStamp(void); //获取时间戳值
void EMAC_SetMDCLK_Speed(u8 MaxClockSpeed); //设置MCLKD速度
void EMAC_SetRxdBuff(u32 BuffIndex, u8 pBuff[]); //初始化接收缓冲区(必须大于等于最大帧大小)
EMAC_RXDMA_Struct* EMAC_GetCurrentRxdDesc(void);//获取当前接收描述符,并切换到下一个描述符
bool EMAC_SendData(u8* pData, u32 PackSize);//发送一个数据包(不会拷贝数据)
#endif //_M48x_EMAC_H_
|