打印
[新唐博主]

M480 EMAC驱动01-EMAC底层接口

[复制链接]
2450|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2021-11-3 16:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
寄存器:




//EMAC========================================================================================================
#define EMAC_BASE                       (0x4000B000)                      //寄存器基址

typedef struct
{
        vu32 CAMCTL;                                                        //EMAC CAM命令寄存器
        vu32 CAMEN;                                                                //EMAC CAM使能寄存器
        vu32 CAM_Channel[16][2];                                //[0]:EMAC  CAM X最高有效字寄存器; [1]:EMAC  CAM X最低有效字寄存器; 用于筛选指定MAC的数据包
        vu32 TXDSA;                                                                //EMAC 发送描述符链接列表起始地址
        vu32 RXDSA;                                                                //EMAC 接收描述符链接列表起始地址
        vu32 CTL;                                                                //EMAC MAC命令寄存器
        vu32 MIIMDAT;                                                        //EMAC MII管理数据寄存器
        vu32 MIIMCTL;                                                        //EMAC MII管理控制和地址寄存器
        vu32 FIFOCTL;                                                        //EMAC FIFO阈值控制寄存器
        vu32 TXST;                                                                //EMAC 发送开始需求寄存器
        vu32 RXST;                                                                //EMAC 接收启动需求寄存器
        vu32 MRFL;                                                                //EMAC 最大接收帧控制寄存器
        vu32 INTEN;                                                                //EMAC MAC中断允许寄存器
        vu32 INTSTS;                                                        //EMAC MAC中断状态寄存器
        vu32 GENSTS;                                                        //EMAC MAC常规状态寄存器
        vu32 MPCNT;                                                                //EMAC n丢失的数据包计数寄存器
        vu32 RPSTS;                                                                //MAC上的EMACS接收暂停计数寄存器
        u32 Reserved2[2];
       
        vu32 FRSTS;                                                                //EMAC DMA接收帧状态寄存器
        vu32 CTXDSA;                                                        //EMAC 当前发送描述符起始地址
        vu32 CTXBSA;                                                        //EMAC 当前发送缓冲区起始地址寄存器
        vu32 CRXDSA;                                                        //EMAC 当前接收描述符起始地址
        vu32 CRXBSA;                                                        //EMAC 当前接收缓冲区起始地址寄存器
        u32 Reserved3[9];
        vu32 TSCTL;                                                                //EMAC 时间戳控制寄存器
        u32 Reserved4[3];
        vu32 TSSEC;                                                                //EMAC 时间戳计数器第二个寄存器
        vu32 TSSUBSEC;                                                        //EMAC 时间戳计数器次秒寄存器
        vu32 TSINC;                                                                //EMAC 时间戳增量寄存器
        vu32 TSADDEND;                                                        //EMAC 时间戳加法寄存器
        vu32 UPDSEC;                                                        //EMAC 时间戳更新第二个寄存器
        vu32 UPDSUBSEC;                                                        //EMAC 时间戳更新子秒寄存器
        vu32 ALMSEC;                                                        //EMAC 时间戳警报第二个寄存器
        vu32 ALMSUBSEC;                                                        //EMAC 时间戳警报子秒寄存器
}EMAC_TypeDef;

#define EMAC                                      ((EMAC_TypeDef *) EMAC_BASE)

使用特权

评论回复
沙发
tpgf|  楼主 | 2021-11-3 16:42 | 只看该作者
//代码


/*************************************************************************************************************
* 文件名:                        EMAC.c
* 功能:                        M48x EMAC控制器驱动
* 作者:                        cp1300@139.com
* 创建时间:                2021-10-09
* 最后修改时间:        2021-10-09
* 详细:                       
*************************************************************************************************************/
#include "m48x_system.h"
#include "m48x_emac.h"
#include "typedef.h"


static u8 sg_PHY_Addr;                                                                                        //用于存储PHY地址用
void EMAC_EnableTimeStamp( bool isEnable);                                                //时间戳功能开关设置

typedef void (*EMAC_IntCallBackType)(u32);
void NullCallback(u32 Status) {}       
static EMAC_IntCallBackType sg_EMAC_TxIntCallback = NullCallback;                                //发送中断回调接口
static EMAC_IntCallBackType sg_EMAC_RxIntCallback = NullCallback;                                //接收中断回调接口



#if(EMAC_RXD_DESC_SIZE<2||EMAC_TXD_DESC_SIZE<2)
#error("描述符大小不能小于2!");
#endif //EMAC_RXD_DESC_SIZE


static volatile EMAC_TXDMA_Struct sg_TxdDescBuff[EMAC_TXD_DESC_SIZE];        //发送描述符集合
static volatile EMAC_RXDMA_Struct sg_RxdDescBuff[EMAC_RXD_DESC_SIZE];        //接收描述符集合
static volatile EMAC_TXDMA_Struct *sg_pNestTxdDesc;                                                //指向下一个描述符
static volatile EMAC_TXDMA_Struct* sg_pCurrentTxdDesc;                                        //当前使用的描述符
static volatile EMAC_RXDMA_Struct* sg_pCurrentRxdDesc;                                        //当前使用的描述符

void EMAC_TxdDescInit(void);//发送描述符初始化
void EMAC_RxdDescInit(void);//接收描述符初始化

/*************************************************************************************************************************
* 函数                        :        void EMAC_TxdDescInit(void)
* 功能                        :        发送描述符初始化
* 参数                        :        无
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-21
* 最后修改时间         :         2020-09-21
* 说明                        :        必须在初始化发送之前进行初始化
*************************************************************************************************************************/
void EMAC_TxdDescInit(void)
{
        u32 i;

        sg_pCurrentTxdDesc = sg_pNestTxdDesc = &sg_TxdDescBuff[0];                        //初始化指向
        EMAC->TXDSA = (u32)sg_pCurrentTxdDesc;
        for (i = 0; i < EMAC_TXD_DESC_SIZE; i++)
        {
                sg_TxdDescBuff.FrameStatus.FrameStatus_u32 = 0;
                sg_TxdDescBuff.FrameStatus.b.TranCount = 0;                                        //BIT15-BIT0;当前发送缓冲区中帧的长度
                sg_TxdDescBuff.FrameControl.FrameControl_u32 = 0;
                sg_TxdDescBuff.FrameControl.b.EnablePadding = TRUE;                        //BIT0;1:使能此帧填充功能(不足60字节帧需要进行填充);0:不使能填充
                sg_TxdDescBuff.FrameControl.b.EnableCRC = TRUE;                                //BIT1;1:使能此帧添加CRC校验(4B);0:不使能此帧添加校验
                sg_TxdDescBuff.FrameControl.b.EnableInterrupt = FALSE;                //BIT2;1:使能此帧发送完后触发中断;0:不使能中断
                sg_TxdDescBuff.FrameControl.b.EnableTimeStamp = TRUE;                //BIT3;1:使能发送时间戳;0:不使能时间戳
                sg_TxdDescBuff.FrameControl.b.Ownership = FALSE;                                //BIT31;1:代表DMA还未将数据发送完;0:DMA已经将数据发送完了
                sg_TxdDescBuff.FrameAddrTimeL.BuffAddr = (u32)NULL;
                sg_TxdDescBuff.NextAddrTimeH.BuffAddr = (u32)&sg_TxdDescBuff[(i+1)% EMAC_TXD_DESC_SIZE];
        }
}


/*************************************************************************************************************************
* 函数                        :        bool EMAC_SendData(u8 *pData, u32 PackSize)
* 功能                        :        发送一个数据包(不会拷贝数据)
* 参数                        :        pData:数据包缓冲区;PackSize:数据包大小
* 返回                        :        TRUE:写入发送缓冲区成功;FALSE:写入发送缓冲区失败
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-21
* 最后修改时间         :         2020-09-21
* 说明                        :        注意:数据包缓冲区在数据包发送完成之前不能修改,此处不进行数据拷贝
*************************************************************************************************************************/
bool EMAC_SendData(u8 *pData, u32 PackSize)
{
        EMAC_TXDMA_Struct* desc;
        u32 status;
        u32 i;

        uart_printf("开始发送数据:(%dB) ", PackSize);
        for (i = 0; i < EMAC_TXD_DESC_SIZE; i++)
        {
                uart_printf("%d ", sg_TxdDescBuff.FrameControl.b.Ownership);
        }
        uart_printf("\r\n");

        desc = (EMAC_TXDMA_Struct*)sg_pNestTxdDesc;
        if (desc->FrameControl.b.Ownership == 0) //当前处于CPU,也就是空闲的
        {
                desc->FrameStatus.FrameStatus_u32 = 0;
                desc->FrameStatus.b.TranCount = PackSize;                //BIT15-BIT0;当前发送缓冲区中帧的长度
                desc->FrameControl.FrameControl_u32 = 0;
                desc->FrameControl.b.EnablePadding = FALSE;                //BIT0;1:使能此帧填充功能(不足60字节帧需要进行填充);0:不使能填充
                desc->FrameControl.b.EnableCRC = TRUE;                //BIT1;1:使能此帧添加CRC校验(4B);0:不使能此帧添加校验
                desc->FrameControl.b.EnableInterrupt = TRUE;                //BIT2;1:使能此帧发送完后触发中断;0:不使能中断
                desc->FrameControl.b.EnableTimeStamp = TRUE;                //BIT3;1:使能发送时间戳;0:不使能时间戳
                desc->FrameControl.b.Ownership = TRUE;                //BIT31;1:代表DMA还未将数据发送完;0:DMA已经将数据发送完了
                desc->FrameAddrTimeL.BuffAddr = (u32)pData;

                EMAC_EnableTxData(TRUE);                                                        //使能发送数据
                sg_pNestTxdDesc = (EMAC_TXDMA_Struct*)desc->NextAddrTimeH.BuffAddr;                //指向下一个
                EMAC_TXDMA_Restart();                                                                                                        //重启发送DMA(当前TX描述符无效后需要进行调用)

                return TRUE;
        }
        DEBUG("EMAC:发送失败,之前数据未发送成功\r\n");
        return FALSE;
}




使用特权

评论回复
板凳
tpgf|  楼主 | 2021-11-3 16:42 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void EMAC_RxdDescInit(void)
* 功能                        :        接收描述符初始化
* 参数                        :        无
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-21
* 最后修改时间         :         2020-09-21
* 说明                        :        必须在初始化接收之前进行初始化
*************************************************************************************************************************/
void EMAC_RxdDescInit(void)
{
        u32 i;

        sg_pCurrentRxdDesc = &sg_RxdDescBuff[0];        //初始化指向
        EMAC->RXDSA = (u32)sg_pCurrentRxdDesc;
        for (i = 0; i < EMAC_RXD_DESC_SIZE; i++)
        {
                sg_RxdDescBuff.FrameStatus.FrameStatus_u32 = 0;
                sg_RxdDescBuff.FrameStatus.b.Ownership = 1;                                        //DMA还未开始传输
                sg_RxdDescBuff.FrameAddrTimeL.BuffAddr =  (u32)NULL;
                sg_RxdDescBuff.RxBuffAddr = NULL;                                                        //接收缓冲区地址无效
                sg_RxdDescBuff.NextAddrTimeH.BuffAddr = (u32)&sg_RxdDescBuff[(i + 1) % EMAC_RXD_DESC_SIZE];
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_SetRxdBuff(u32 BuffIndex, u8 pBuff[])
* 功能                        :        初始化接收缓冲区(必须大于等于最大帧大小)
* 参数                        :        BuffIndex:buff索引,0-(EMAC_RXD_DESC_SIZE-1);pBuff:缓冲区指针
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-21
* 最后修改时间         :         2020-09-21
* 说明                        :        必须在接收数据之前初始化
*************************************************************************************************************************/
void EMAC_SetRxdBuff(u32 BuffIndex, u8 pBuff[])
{
        if (BuffIndex > (EMAC_RXD_DESC_SIZE - 1)) return;

        sg_RxdDescBuff[BuffIndex].FrameStatus.FrameStatus_u32 = 0;
        sg_RxdDescBuff[BuffIndex].FrameStatus.b.Ownership = 1;                                        //DMA还未开始传输
        sg_RxdDescBuff[BuffIndex].FrameAddrTimeL.BuffAddr = (u32)pBuff;
        sg_RxdDescBuff[BuffIndex].RxBuffAddr = (u32)pBuff;                                                //记录接收缓冲区地址
       
        //sg_pCurrentRxdDesc->FrameStatus.FrameStatus_u32 = 0;
        //sg_pCurrentRxdDesc->FrameStatus.b.Ownership = TRUE;                                        //DMA还未开始传输
        //sg_pCurrentRxdDesc->FrameAddrTimeL.BuffAddr = (vu32)pBuff;
}

/*************************************************************************************************************************
* 函数                        :        EMAC_RXDMA_Struct* EMAC_GetCurrentRxdDesc(void)
* 功能                        :        获取当前接收描述符,并切换到下一个描述符
* 参数                        :        无
* 返回                        :        当前接收使用的描述符
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-21
* 最后修改时间         :         2020-09-21
* 说明                        :        用于接收数据后切换
*************************************************************************************************************************/
EMAC_RXDMA_Struct* EMAC_GetCurrentRxdDesc(void)
{
        u32 i;
        EMAC_RXDMA_Struct* p = sg_pCurrentRxdDesc;        //获取当前接收描述符
       
        uart_printf("Ownership:");
        for (i = 0; i < EMAC_RXD_DESC_SIZE; i++)
        {
                uart_printf("%d ", sg_RxdDescBuff.FrameStatus.b.Ownership);
        }
        uart_printf("\r\n");


        sg_pCurrentRxdDesc = (EMAC_RXDMA_Struct*)sg_pCurrentRxdDesc->NextAddrTimeH.BuffAddr; //切换到下一个描述符

        return p;
}


/*************************************************************************************************************************
* 函数                        :        void EMAC_Init(EMAC_CH ch)
* 功能                        :        EMAC控制器初始化
* 参数                        :        ch:通道,见EMAC_CHx
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-21
* 最后修改时间         :         2020-09-21
* 说明                        :       
*************************************************************************************************************************/
void EMAC_Init(void)
{
        //复位并初始化时钟
        SYS_DeviceClockEnable(DEV_EMAC, TRUE);                //使能时钟
        SYS_DeviceReset(DEV_RESET_EMAC);                        //复位外设

       
        EMAC_SetMDCLK_Speed(2);                                                //设置MCLKD速度,最大时钟不能超过2.5MHz
        Delay_US(10);       
        EMAC->CTL |= BIT24;                                                                                                //软复位
        while(EMAC->CTL & BIT24);                                                                                //等待软复位结束
       
        EMAC->CAMCTL = BIT4|BIT3;                                                                                //不开启任何MAC地址过滤,关闭广播,多播,单播数据包接收
        EMAC->CTL = BIT22 |BIT5;                                                                                //CTL BIT22必须为1 RMIIEN = 1;如果bit19设置为1,则会导致CRC错误,原因未知
        EMAC->MIIMCTL = 0;
        //EMAC->FIFOCTL = (0x0<<20) | (0x1<<8)  | (0x1<<0);                                //突发传输为4个字,发送阈值为96-192,接收阈值为 32-64
        EMAC->MRFL = EMAC_RXMS_LENGTH;                                                                        //数据帧长度限制
        EMAC_EnableTimeStamp(TRUE);                                                                                //时间戳功能开关设置-开启时间戳功能
        //先开启总中断
        SYS_NVIC_IntEnable(IRQ_EMAC_TX, TRUE);                //TX中断 NVIC全局中断使能
        SYS_NVIC_IntEnable(IRQ_EMAC_RX, TRUE);                //RX中断 NVIC全局中断使能
        EMAC_TxdDescInit();                                                        //发送描述符初始化
        EMAC_RxdDescInit();                                                        //接收描述符初始化
}



使用特权

评论回复
地板
tpgf|  楼主 | 2021-11-3 16:42 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void EMAC_SetTxInt_Callback(void (*pEMACx_TxInt_Callback)(u32 IntStatus))
* 功能                        :        EMAC控制器发送中断回调设置
* 参数                        :        ch:通道,见EMAC_CHx;pEMACx_TxInt_Callback:发送中断回调函数(IntStatus:中断状态值)
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-28
* 最后修改时间         :         2020-09-28
* 说明                        :        无需清除中断状态
*************************************************************************************************************************/
void EMAC_SetTxInt_Callback(void (*pEMACx_TxInt_Callback)(u32 IntStatus))
{
        if(pEMACx_TxInt_Callback == NULL)
        {
                sg_EMAC_TxIntCallback = NullCallback;        //无效则设置一个默认的回调函数接口
        }
        else
        {
                sg_EMAC_TxIntCallback = pEMACx_TxInt_Callback;
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_SetRxInt_Callback(void (*pEMACx_RxInt_Callback)(u32 IntStatus))
* 功能                        :        EMAC控制器接收中断回调设置
* 参数                        :        ch:通道,见EMAC_CHx;pEMACx_RxInt_Callback:接收中断回调函数(IntStatus:中断状态值)
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-28
* 最后修改时间         :         2020-09-28
* 说明                        :        无需清除中断状态
*************************************************************************************************************************/
void EMAC_SetRxInt_Callback(void (*pEMACx_RxInt_Callback)(u32 IntStatus))
{
        if(pEMACx_RxInt_Callback == NULL)
        {
                sg_EMAC_RxIntCallback = NullCallback;        //无效则设置一个默认的回调函数接口
        }
        else
        {
                sg_EMAC_RxIntCallback = pEMACx_RxInt_Callback;
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableRxMacFilter( EMAC_MAC_FILTER MacFilter)
* 功能                        :        EMAC地址过滤总模式设置
* 参数                        :        ch:通道,见EMAC_CHx;MacFilter:过滤模式
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableRxMacFilter( EMAC_MAC_FILTER MacFilter)
{
        switch(MacFilter)
        {
                case MAC_FILTER_ENABLE_TARGET:        //允许目标MAC地址
                {
                        EMAC->CAMCTL |= BIT4;
                        EMAC->CAMCTL &= ~BIT3;
                }break;
                case MAC_FILTER_DISABLE_TARGET:        //禁止目标MAC地址数据包接收
                {
                        EMAC->CAMCTL |= BIT4 | BIT3;
                }break;
                default: //不开启任何过滤
                {
                        EMAC->CAMCTL &= ~(BIT4 | BIT3);
                }break;
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableRxBroadcastPacket( bool isEnable)
* 功能                        :        EMAC广播数据包接收使能
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:使能接收
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :        同时需要设置其中一组CAM为FF-FF-FF-FF-FF-FF
*************************************************************************************************************************/
void EMAC_EnableRxBroadcastPacket( bool isEnable)
{
        if(isEnable)        //使能广播数据包接收
        {
                EMAC->CAMCTL |= BIT2;
        }
        else
        {
                EMAC->CAMCTL &= ~BIT2;
        }
}



使用特权

评论回复
5
tpgf|  楼主 | 2021-11-3 16:43 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableRxMulticastPacket( bool isEnable)
* 功能                        :        EMAC多播(组播)数据包接收使能
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:使能接收
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :        同时需要设置其中一组CAM为组播地址
*************************************************************************************************************************/
void EMAC_EnableRxMulticastPacket( bool isEnable)
{
        if(isEnable)        //多播数据包接收使能
        {
                EMAC->CAMCTL |= BIT1;
        }
        else
        {
                EMAC->CAMCTL &= ~BIT1;
        }
}


/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableRxUnicastPacket( bool isEnable)
* 功能                        :        EMAC单播数据包接收使能
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:使能接收
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :        同时需要设置其中一组CAM为本机MAC地址
*************************************************************************************************************************/
void EMAC_EnableRxUnicastPacket( bool isEnable)
{
        if(isEnable)        //单播数据包接收使能
        {
                EMAC->CAMCTL |= BIT0;
        }
        else
        {
                EMAC->CAMCTL &= ~BIT0;
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableRxMacChannelVerification( u16 ChannelBit)
* 功能                        :        EMAC数据包接收MAC过滤通道使能,每个bit代表一个通道(0-12)
* 参数                        :        ch:通道,见EMAC_CHx;ChannelBit:过滤通道0-12
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableRxMacChannelVerification( u16 ChannelBit)
{
        EMAC->CAMEN |= ChannelBit&0x1FFF;
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_DisableRxMacChannelVerification( u16 ChannelBit)
* 功能                        :        数据包接收MAC过滤通道关闭,每个bit代表一个通道(0-12)
* 参数                        :        ch:通道,见EMAC_CHx;ChannelBit:过滤通道0-12
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_DisableRxMacChannelVerification( u16 ChannelBit)
{
        EMAC->CAMEN &= ~(ChannelBit&0x1FFF);
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_SetRxMacChannelValue( u8  Channel_n,const  u8 MAC[6])
* 功能                        :        设置指定的MAC地址过滤通道MAC地址(0-12)
* 参数                        :        ch:通道,见EMAC_CHx;ChannelBit:过滤通道0-12;MAC:需要设置的MAC地址
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_SetRxMacChannelValue( u8  Channel_n, const u8 MAC[6])
{
        u32 temp;

        if(Channel_n > 12) return;
       
        temp = MAC[0];
        temp <<= 8;
        temp |= MAC[1];
        temp <<= 8;
        temp |= MAC[2];
        temp <<= 8;
        temp |= MAC[3];
        EMAC->CAM_Channel[Channel_n][0] = temp;
        temp = MAC[4];
        temp <<= 8;
        temp |= MAC[5];
        temp <<= 24;
        EMAC->CAM_Channel[Channel_n][1] = temp;
}



使用特权

评论回复
6
tpgf|  楼主 | 2021-11-3 16:43 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void EMAC_Enable100MpbsMode( bool isEnable)
* 功能                        :        使能100M模式,否则为10M
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_Enable100MpbsMode( bool isEnable)
{
        if(isEnable)        //使能100M模式
        {
                EMAC->CTL |= BIT20;                        //100M
        }
        else
        {
                EMAC->CTL &= ~BIT20;                        //10M
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableFullDuplexMode( bool isEnable)
* 功能                        :        使能全双工模式,否则为半双工
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableFullDuplexMode( bool isEnable)
{
        if(isEnable)        //使能全双工
        {
                EMAC->CTL |= BIT18;                        //全双工
        }
        else
        {
                EMAC->CTL &= ~BIT18;                        //半双工
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableSQECheeck( bool isEnable)
* 功能                        :        使能SQE检查(仅用于10M半双工模式)
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :        在EMAC以10M bps和半双工模式运行时可用。 换句话说,如果EMAC以100M bps或全速率运行,则SQECHKEN不会影响EMAC的运行
*************************************************************************************************************************/
void EMAC_EnableSQECheeck( bool isEnable)
{
        if(isEnable)        //启用SQE检查
        {
                EMAC->CTL |= BIT17;                        //启用SQE检查
        }
        else
        {
                EMAC->CTL &= ~BIT17;                        //SQE检查禁用
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableNDEF( bool isEnable)
* 功能                        :        使能NDEF延时超时计数器(仅在半双工模式下有效)
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2021-10-11
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableNDEF( bool isEnable)
{
        if(isEnable)        //使能,注意:0是开启
        {
                EMAC->CTL &= ~BIT9;                        //延迟超过计数器已启用
        }
        else
        {
                EMAC->CTL |= BIT9;                        //延迟超过计数器禁用 -- 此处之前错误的设置为BIT19了,2021-10-11修正
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableWakeUp( bool isEnable)
* 功能                        :        使能网络唤醒(通过魔术包唤醒)
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableWakeUp( bool isEnable)
{
        if(isEnable)        //使能数据包唤醒
        {
                EMAC->CTL |= BIT6;                        //启用
        }
        else
        {
                EMAC->CTL &= ~BIT6;                        //禁用
        }
}



使用特权

评论回复
7
tpgf|  楼主 | 2021-11-3 16:43 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableACP( bool isEnable)
* 功能                        :        使能接收控制帧(建议仅当EMAC在全双工模式下运行时使用)
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableACP( bool isEnable)
{
        if(isEnable)       
        {
                EMAC->CTL |= BIT3;                        //启用
        }
        else
        {
                EMAC->CTL &= ~BIT3;                        //禁用
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableRuntARP( bool isEnable)
* 功能                        :        使能接收不足64字节的ARP数据包
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableRuntARP( bool isEnable)
{
        if(isEnable)       
        {
                EMAC->CTL |= BIT2;                        //启用
        }
        else
        {
                EMAC->CTL &= ~BIT2;                        //禁用
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableLongPacket( bool isEnable)
* 功能                        :        使能接收长数据包
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableLongPacket( bool isEnable)
{
        if(isEnable)       
        {
                EMAC->CTL |= BIT1;                        //启用
        }
        else
        {
                EMAC->CTL &= ~BIT1;                        //禁用
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableTxData( bool isEnable)
* 功能                        :        使能发送数据
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableTxData( bool isEnable)
{
        if(isEnable)       
        {
                EMAC->CTL |= BIT8;                        //启用
        }
        else
        {
                EMAC->CTL &= ~BIT8;                        //禁用
        }
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableRxData( bool isEnable)
* 功能                        :        使能接收数据
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:TRUE:使能
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableRxData( bool isEnable)
{
        if(isEnable)       
        {
                EMAC->CTL |= BIT0;                        //启用
                EMAC_RXDMA_Restart();
        }
        else
        {
                EMAC->CTL &= ~BIT0;                        //禁用
        }
}



使用特权

评论回复
8
tpgf|  楼主 | 2021-11-3 16:43 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        void EMAC_SetPHYAddr( u8 addr)
* 功能                        :        EMAC设置当前通道的PHY地址
* 参数                        :        ch:通道,见EMAC_CHx;addr:PHY地址
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-22
* 最后修改时间         :         2020-09-22
* 说明                        :        地址缓存在sg_PHY_Addr中
*************************************************************************************************************************/
void EMAC_SetPHYAddr( u8 addr)
{
        sg_PHY_Addr = addr & 0x1F;
}


/*************************************************************************************************************************
* 函数                        :        bool EMAC_WritePHY( u8 RegAddr, u16 data)
* 功能                        :        EMAC写命令到PHY
* 参数                        :        ch:通道,见EMAC_CHx;RegAddr:寄存器地址;data:要写入的数据
* 返回                        :        TRUE:成功;FALSE:失败
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-22
* 最后修改时间         :         2020-09-22
* 说明                        :        需要提前设置PHY地址
*************************************************************************************************************************/
bool EMAC_WritePHY( u8 RegAddr, u16 data)
{
        u32 tempreg;
        u32 TimeOutMS;
        TimeOutMS = 1000;
        while(EMAC->MIIMCTL & BIT17 && TimeOutMS)        //等待上一个命令执行完成
        {
                SYS_DelayMS(1);
                TimeOutMS--;
        }
        tempreg = EMAC->MIIMCTL;
        tempreg &= ~0x1FFFF;                                                //清除最低17位
        tempreg |= BIT16;        //写命令
        tempreg |= (sg_PHY_Addr & 0x1F) << 8;                //PHY地址
        tempreg |= (RegAddr & 0x1F) << 0;                        //PHY寄存器地址
        EMAC->MIIMDAT = data;                                                //写入数据
        tempreg |= BIT17;                                                        //准备读写PHY
        EMAC->MIIMCTL = tempreg;
        TimeOutMS = 1000;
        while(EMAC->MIIMCTL & BIT17 && TimeOutMS)                //等待命令执行完成       
        {
                SYS_DelayMS(1);
                TimeOutMS--;
        }       
        if(EMAC->MIIMCTL & BIT17) return FALSE;
        else return TRUE;
}


/*************************************************************************************************************************
* 函数                        :        bool EMAC_ReadPHY( u8 RegAddr, u16 *pData)
* 功能                        :        EMAC读取PHY寄存器
* 参数                        :        ch:通道,见EMAC_CHx;RegAddr:寄存器地址;pData:读取的数据
* 返回                        :        TRUE:成功;FALSE:失败
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-22
* 最后修改时间         :         2020-09-22
* 说明                        :        需要提前设置PHY地址
*************************************************************************************************************************/
bool EMAC_ReadPHY( u8 RegAddr, u16 *pData)
{
        u32 tempreg;
        u32 TimeOutMS;
       
        TimeOutMS = 1000;
        while(EMAC->MIIMCTL & BIT17 && TimeOutMS)        //等待上一个命令执行完成
        {
                SYS_DelayMS(1);
                TimeOutMS--;
        }
        tempreg = EMAC->MIIMCTL;
        tempreg &= ~0x1FFFF;                                                        //清除最低17位
        tempreg &= ~BIT16;                                                                //读命令
        tempreg |= (sg_PHY_Addr & 0x1F) << 8;                        //PHY地址
        tempreg |= (RegAddr & 0x1F) << 0;                                //PHY寄存器地址
        tempreg |= BIT17;                                                                //准备读写PHY
        EMAC->MIIMCTL = tempreg;
        TimeOutMS = 1000;
        while((EMAC->MIIMCTL & BIT17) && TimeOutMS)                //等待命令执行完成       
        {
                SYS_DelayMS(1);
                TimeOutMS--;
        }       
        if(EMAC->MIIMCTL & BIT17) return FALSE;
        else
        {
                *pData = EMAC->MIIMDAT;
                return TRUE;
        }
}



使用特权

评论回复
9
tpgf|  楼主 | 2021-11-3 16:44 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableInt( u32 IntMask)
* 功能                        :        开启相关中断
* 参数                        :        ch:通道,见EMAC_CHx;IntMask:多个中断使用 | 控制
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-22
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableInt( u32 IntMask)
{
        EMAC->INTEN |= IntMask;
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_DisableInt( u32 IntMask)
* 功能                        :        关闭相关中断
* 参数                        :        ch:通道,见EMAC_CHx;IntMask:多个中断使用 | 控制
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-22
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_DisableInt( u32 IntMask)
{
        EMAC->INTEN &= ~IntMask;
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_ClearInt( u32 IntMask)
* 功能                        :        清除中断
* 参数                        :        ch:通道,见EMAC_CHx;IntMask:多个中断使用 | 控制
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-22
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_ClearInt( u32 IntMask)
{
        EMAC->INTSTS |= IntMask;
}

/*************************************************************************************************************************
* 函数                        :        u32 EMAC_GetIntStatus(void)
* 功能                        :        获取中断状态
* 参数                        :        ch:通道,见EMAC_CHx
* 返回                        :        中断状态,见宏定义
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-28
* 最后修改时间         :         2020-09-28
* 说明                        :       
*************************************************************************************************************************/
u32 EMAC_GetIntStatus(void)
{
        return EMAC->INTSTS;
}


/*************************************************************************************************************************
* 函数                        :        void EMAC_ClearStatus( u32 StatusMask)
* 功能                        :        清除状态
* 参数                        :        ch:通道,见EMAC_CHx;IntMask:多个中断使用 | 控制
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-22
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_ClearStatus( u32 StatusMask)
{
        EMAC->GENSTS |= StatusMask;
}

/*************************************************************************************************************************
* 函数                        :        u32 EMAC_GetStatus(void)
* 功能                        :        获取状态
* 参数                        :        ch:通道,见EMAC_CHx
* 返回                        :        中断状态,见宏定义
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-28
* 最后修改时间         :         2020-09-28
* 说明                        :       
*************************************************************************************************************************/
u32 EMAC_GetStatus(void)
{
        return EMAC->GENSTS;
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_SetTXDMA_LLA( EMAC_TXDMA_Struct *pLLA)
* 功能                        :        设置发送数据DMA链表地址
* 参数                        :        ch:通道,见EMAC_CHx;pLLA:链表地址
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_SetTXDMA_LLA( EMAC_TXDMA_Struct *pLLA)
{
        EMAC->TXDSA = (u32)pLLA;
}



使用特权

评论回复
10
tpgf|  楼主 | 2021-11-3 16:44 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        void EMAC_SetRXDMA_LLA( EMAC_RXDMA_Struct *pLLA)
* 功能                        :        设置接收数据DMA链表地址
* 参数                        :        ch:通道,见EMAC_CHx;pLLA:链表地址
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_SetRXDMA_LLA( EMAC_RXDMA_Struct *pLLA)
{
        EMAC->RXDSA = (u32)pLLA;
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_TXDMA_Restart(void)
* 功能                        :        重启发送DMA
* 参数                        :        ch:通道,见EMAC_CHx;
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :        如果TXON之后TX描述符不可用,但是TXDMA(EMACn_CTL [8])被启用,TXDMA的FSM(有限状态机)进入暂停状态,然后停止帧传输。
                                        在软件准备好新的TX描述符之后,它必须向EMACn_TXST发出写命令以使TXDMA退出暂停状态并继续帧传输。
                                        EMACn_TXST是只写寄存器,从该寄存器读取的值为未定义。仅当TXDMA保持在暂停状态时,对EMACn_TXST寄存器的写操作才有效
*************************************************************************************************************************/
void EMAC_TXDMA_Restart(void)
{
        EMAC->TXST = 0;                                                //随便写个啥进去就行
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_RXDMA_Restart(void)
* 功能                        :        重启接收DMA
* 参数                        :        ch:通道,见EMAC_CHx;
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :        如果在RXON之后RX描述符不可用于RXDMA(EMACn_CTL [0]),RXDMA的FSM(有限状态机)进入暂停状态,并且帧接收停止。
                                        在软件准备好新的RX描述符之后,它必须向EMACn_RXST寄存器发出写命令使RXDMA退出暂停状态并继续帧接收。
                                        EMACn_RXST是只写寄存器,从该寄存器读取的值为未定义。仅当RXDMA处于暂停状态时,对EMACn_RXST寄存器的写操作才会生效
*************************************************************************************************************************/
void EMAC_RXDMA_Restart(void)
{
        EMAC->RXST = 0;        //随便写个啥进去就行
}

/*************************************************************************************************************************
* 函数                        :        void EMAC_EnableTimeStamp( bool isEnable)
* 功能                        :        时间戳功能开关设置
* 参数                        :        ch:通道,见EMAC_CHx;isEnable:是否开启
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :       
*************************************************************************************************************************/
void EMAC_EnableTimeStamp( bool isEnable)
{
        if(isEnable)        //开启
        {
                EMAC->TSINC = 1;                //时间戳增量控制
                EMAC->TSADDEND = (0XFFFFFFFF/(SYS_GetHCLKSpeed()/1000))-1;        //在每个HCLK周期内+TSADDEND,溢出后将时间戳计数器增加TSINC
                EMAC->TSSEC = 0;                //时间戳初值清零
                EMAC->TSSUBSEC = 0;        //时间戳初值清零
                EMAC->UPDSEC = 0;                //时间戳初值清零
                EMAC->UPDSUBSEC = 0;        //时间戳初值清零
                EMAC->TSCTL =  0
                                                        //| BIT5         //时间戳报警功能使能
                                                        | BIT3        //时间戳更新使能,将UPDSEC更新到TSSEC;UPDSUBSEC更新到TSSUBSEC
                                                        | BIT2        //精密计数模式
                                                        | BIT1  //使能时间戳初始化
                                                        | BIT0;        //启用IEEE 1588 PTP时间戳功能       
        }                       
        else
        {
                EMAC->TSCTL = 0;        //关闭时间戳功能
        }
}

/*************************************************************************************************************************
* 函数                        :        u64 EMAC_GetTimeStamp(void)
* 功能                        :        获取时间戳值
* 参数                        :        ch:通道,见EMAC_CHx;
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-27
* 最后修改时间         :         2020-09-27
* 说明                        :        必须使能了IEEE 1588 PTP时间戳功能才行
*************************************************************************************************************************/
u64 EMAC_GetTimeStamp(void)
{
        u64 ltemp;
       
        ltemp = EMAC->TSSEC;
        ltemp <<= 32;
        ltemp |= EMAC->TSSUBSEC;
       
        return ltemp;
}


//EMAC 发送中断服务程序
void EMAC_TX_IRQHandler(void)
{
        sg_EMAC_TxIntCallback(EMAC->INTSTS & 0xFFFF0000);
        EMAC->INTSTS = EMAC->INTSTS  & 0xFFFF0000;        //清除中断信息
}

//EMAC 接收中断服务程序
void EMAC_RX_IRQHandler(void)
{
        sg_EMAC_RxIntCallback(EMAC->INTSTS & 0xFFFF);
        EMAC->INTSTS = EMAC->INTSTS & 0xFFFF;                //清除中断信息
}


/*************************************************************************************************************************
* 函数                        :        void EMAC_SetMDCLK_Speed(u8 MaxClockSpeed)
* 功能                        :        设置MCLKD速度
* 参数                        :        MaxClockSpeed:最大时钟速度,单位MHz
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2021-10-10
* 最后修改时间         :         2021-10-10
* 说明                        :        使用HCLK分频得到MDCLK,最大256分频
*************************************************************************************************************************/
void EMAC_SetMDCLK_Speed(u8 MaxClockSpeed)
{
        u32 HCLK_Speed = SYS_GetHCLKSpeed() / 1000000;        //获取HCLK速度,单位MHz
        u32 div;

        div = HCLK_Speed / MaxClockSpeed;
        if (HCLK_Speed % MaxClockSpeed) div += 1;
        if (div > 256) div = 256;
        if (div < 1) div = 1;
        div -= 1;
        CLOCK->CLKDIV[3] &= ~(0xFF < 16);        //清除之前设置
        CLOCK->CLKDIV[3] |= div << 16;                //重新设置EMAC MDCLK时钟分频
}


使用特权

评论回复
11
tpgf|  楼主 | 2021-11-3 16:44 | 只看该作者
/*************************************************************************************************************
* 文件名:                        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_



使用特权

评论回复
12
chenjun89| | 2021-11-3 20:32 | 只看该作者
直接上传附件不行嘛?

使用特权

评论回复
13
cyclefly| | 2021-11-6 11:39 | 只看该作者
我看成了EMC~~~~

使用特权

评论回复
14
littlelida| | 2021-11-19 15:24 | 只看该作者
我可能,不太适合,只看代码

使用特权

评论回复
15
asmine| | 2021-12-16 15:31 | 只看该作者
好复杂

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2026

主题

15898

帖子

13

粉丝