瑞萨R7FA6M3配置PYH并对接lwip的PYH接口

本文详细介绍了如何使用FSP工具创建和配置以太网组件,包括选择PHY芯片、配置中断回调函数以及PHY芯片的IO。接着,通过调用R_ETHER_Open和R_ETHER_LinkProcess等API进行验证。最后,讨论了如何对接LWIP中的ethernetif.c接口,实现了网络接口的初始化和数据收发功能。
摘要由CSDN通过智能技术生成

目录

1.FSP创建以太网组件

2.修改r_ether相应的配置

3.修改r_ether_phy相应的配置 

3.1选择PHY芯片

3.2配置PHY芯片IO

4.验证

4.1点击生成工程代码

4.2编写phy_Callback函数

4.3调用API进行验证 

5.对接lwip中ethernetif.c的接口


1.FSP创建以太网组件

使用FSP工具选择Driver->Network->Ethernet Driver on r_ether

2.修改r_ether相应的配置

在配置中添加中断回调函数,工程中的回调函数需要自己另外编写

  PHY的地址需要根据硬件电路进行配置

3.修改r_ether_phy相应的配置 

3.1选择PHY芯片

根据硬件选择相应型号的PHY芯片,对于没有的芯片需要自己实现void ether_phy_targets_initialize (ether_phy_instance_ctrl_t *p_instance_ctrl);函数功能,我这里硬件上是KSZ8081和KSZ8091RNB的寄存器一样的,所以直接选择KSZ8091RNB

3.2配置PHY芯片IO

通过其Settings中的Pins跳转到IO配置页面。Pin Group Selection 修改为Mixed,相应的IO口根据硬件电路进行修改

4.验证

4.1点击生成工程代码

4.2编写phy_Callback函数

4.3调用API进行验证 

先调用R_ETHER_Open函数对PHY相关配置进行初始化,之后需要定时调用R_ETHER_LinkProcess函数刷新PHY的相应状态即可。配置成功后网口插上网线,灯会亮

5.对接lwip中ethernetif.c的接口

具体LWIP移植这边不过多解析,网上资源很多


/*
========================================================================================================================
*【本地宏定义】                                       【本地宏定义】                                       【本地宏定义】
========================================================================================================================
*/
#define    ETHERNETIF_INPUT_SIZE                    (128)             //任务堆栈大小
#define    ETHERNETIF_INPUT_PTIO                    (5)              //任务优先级


#define    CHECK_LINK_STATUS_SIZE                   (128)            //任务堆栈大小
#define    CHECK_LINK_STATUS_PRIO                   (11)              //任务优先级

#define NETIF_MTU                                   (1524)
#define netifGUARD_BLOCK_TIME                       (250)

#define ETHER_EDMAC_INTERRUPT_FACTOR_RECEPTION      (0x01070000)

//网卡的名字
#define IFNAME0 'e'
#define IFNAME1 'n'
/*
========================================================================================================================
*【本地数据类型定义】                              【本地数据类型定义】                              【本地数据类型定义】
========================================================================================================================
*/
typedef enum
{ 
    Link_Down = 0,
    Link_Up = 1
}LinkState_T;

/*
========================================================================================================================
*【变量定义 & 各种声明】                          【变量定义 & 各种声明】                         【变量定义 & 各种声明】    
========================================================================================================================
*/
SemaphoreHandle_t s_xSemaphore;

static void CheckLinkStatusTask (void * pvParameters);

/*
========================================================================================================================
*【函数定义】                                          【函数定义】                                          【函数定义】
========================================================================================================================
*/
//由ethernetif_init()调用用于初始化硬件
//netif:网卡结构体指针 
//返回值:ERR_OK,正常
//       其他,失败
static err_t low_level_init(struct netif *netif)
{
    fsp_err_t  err;
    
    netif->hwaddr_len = ETHARP_HWADDR_LEN; //设置MAC地址长度,为6个字节
    //初始化MAC地址,设置什么地址由用户自己设置,但是不能与网络中其他设备MAC地址重复
    netif->hwaddr[0]=lwipdev.mac[0]; 
    netif->hwaddr[1]=lwipdev.mac[1]; 
    netif->hwaddr[2]=lwipdev.mac[2];
    netif->hwaddr[3]=lwipdev.mac[3];
    netif->hwaddr[4]=lwipdev.mac[4];
    netif->hwaddr[5]=lwipdev.mac[5];
    
    memcpy(g_ether0.p_cfg->p_mac_address, netif->hwaddr, 6);

    netif->mtu = NETIF_MTU; //最大允许传输单元,允许该网卡广播和ARP功能
    netif->flags = NETIF_FLAG_BROADCAST|NETIF_FLAG_ETHARP;		

    
    vSemaphoreCreateBinary(s_xSemaphore);
    xSemaphoreTake(s_xSemaphore, portMAX_DELAY );
    err = R_ETHER_Open(g_ether0.p_ctrl, g_ether0.p_cfg);
    
    taskENTER_CRITICAL(); //进入临界区
     sys_thread_new("ethernetif_input",
                     ethernetif_input,          /* 任务入口函数 */
                     netif,                     /* 任务入口函数参数 */
                     ETHERNETIF_INPUT_SIZE,     /* 任务栈大小 */
                     ETHERNETIF_INPUT_PTIO);    /* 任务的优先级 */
                     
     sys_thread_new("CheckLinkStatusTask",
                     CheckLinkStatusTask,       /* 任务入口函数 */
                     netif,                     /* 任务入口函数参数 */
                     CHECK_LINK_STATUS_SIZE,    /* 任务栈大小 */
                     CHECK_LINK_STATUS_PRIO);   /* 任务的优先级 */
                     
    taskEXIT_CRITICAL(); //退出临界区
	return err;
} 


//用于发送数据包的最底层函数(lwip通过netif->linkoutput指向该函数)
//netif:网卡结构体指针
//p:pbuf数据结构体指针
//返回值:ERR_OK,发送正常
//       ERR_MEM,发送失败;
static err_t low_level_output(struct netif *netif,struct pbuf *p)
{
    static xSemaphoreHandle xTxSemaphore = NULL;
    struct pbuf *q;
    int l=0;
    uint8_t *buffer;
    
    if (xTxSemaphore == NULL)
    {
        vSemaphoreCreateBinary (xTxSemaphore);
    }
    
    if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME))
    {
        buffer = pvPortMalloc(NETIF_MTU);                       //申请内存
        if(buffer==NULL)
        {
            printf("发送数据缓冲区内存申请失败\r\n");
            return ERR_MEM;
        }
        for(q=p;q!=NULL;q=q->next) 
        {
            memcpy((u8_t*)&buffer[l], q->payload, q->len);
            l=l+q->len;
        } 

        R_ETHER_Write(g_ether0.p_ctrl, buffer, l);              /*网口发送数据*/

        vPortFree(buffer);                                      //释放内存
        xSemaphoreGive(xTxSemaphore);
    }
    
	return ERR_OK;
}  


///用于接收数据包的最底层函数
//neitif:网卡结构体指针
//返回值:pbuf数据结构体指针
static struct pbuf * low_level_input(struct netif *netif)
{  
    struct pbuf     *p,*q;
    fsp_err_t       err;
    uint32_t        len;
    uint8_t         *buffer;
    uint16_t        l=0;

    buffer = pvPortMalloc(NETIF_MTU);                   //申请内存
    if (NULL == buffer)
    {
        return NULL;
    }
    err = R_ETHER_Read(g_ether0.p_ctrl, buffer, &len);
    if ((FSP_SUCCESS == err) || (FSP_ERR_ETHER_ERROR_NO_DATA == err))
    {

    }
    else
    {
        len = 0;
        printf("接收数据缓冲区内存申请失败\r\n");
        vPortFree(buffer);
        return NULL;
    }
    
    if (0 == len)
    {
        vPortFree( ( void * ) buffer );
        return NULL;
    }
    
    p = pbuf_alloc(PBUF_RAW, (uint16_t)len, PBUF_POOL); //pbufs内存池分配pbuf
    if(p != NULL)
    {
        for(q=p;q!=NULL;q=q->next)
        {
            memcpy((u8_t*)q->payload,(u8_t*)&buffer[l], q->len);
            l=l+q->len;
        }    
    }
    vPortFree(buffer);                                  //释放内存
    return p;
}



//网卡接收数据(lwip直接调用)
//netif:网卡结构体指针
//返回值:ERR_OK,发送正常
//       ERR_MEM,发送失败
void ethernetif_input(void *pParams)
{
	err_t err;
    struct netif *netif;
	struct pbuf *p = NULL;
    netif = (struct netif*) pParams;
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
    
    while(1)
    {
        if (xSemaphoreTake(s_xSemaphore, portMAX_DELAY ) == pdTRUE) //网卡不给释放信号量 任务就一直进入阻塞态
        {
            while(1)
            {
                taskENTER_CRITICAL();                               //进入临界区
                p=low_level_input(netif);                           //调用low_level_input函数接收数据
                taskEXIT_CRITICAL();                                //退出临界区
                if(p!=NULL)
                {
                    taskENTER_CRITICAL();                           //进入临界区
                     if (netif->input(p, netif) != ERR_OK)
                     {
                         LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
                         pbuf_free(p);
                         p = NULL;
                     }
                    taskEXIT_CRITICAL();                            //退出临界区
                }
                else
                {
                    break;
                }
            }
        }
    }
} 


//使用low_level_init()函数来初始化网络
//netif:网卡结构体指针
//返回值:ERR_OK,正常
//       其他,失败
err_t ethernetif_init(struct netif *netif)
{
	LWIP_ASSERT("netif!=NULL",(netif!=NULL));
#if LWIP_NETIF_HOSTNAME                 //LWIP_NETIF_HOSTNAME 
	netif->hostname="lwip";             //初始化名称
#endif 
	netif->name[0]=IFNAME0;             //初始化变量netif的name字段
	netif->name[1]=IFNAME1;             //在文件外定义这里不用关心具体值
	netif->output=etharp_output;        //IP层发送数据包函数
	netif->linkoutput=low_level_output; //ARP模块发送数据包函数
	low_level_init(netif);              //底层硬件初始化函数
	return ERR_OK;
}

//定时执行CheckLinkStatusTask获取网卡连接状态
static void CheckLinkStatusTask (void * pParams) 
{
    static LinkState_T LinkStateCur,LinkStateHis;
    struct netif *netif;
    
    netif = (struct netif*) pParams;

    while(1)
    {
        vTaskDelay(100);
        #if LWIP_NETIF_LINK_CALLBACK
        if(NULL == netif->link_callback)
        {
            continue;
        }
        #endif
        if(FSP_SUCCESS == R_ETHER_LinkProcess(g_ether0.p_ctrl))/*获取网卡连接状态*/
        {
            LinkStateCur = Link_Up;
        }
        else
        {
            LinkStateCur = Link_Down;
        }
        if(LinkStateCur != LinkStateHis)
        {
            if(Link_Down == LinkStateCur)
            {
                netif_set_link_down(pParams);
            }
            else
            {
                netif_set_link_up(pParams);
            }
            LinkStateHis = LinkStateCur;
        }
    }
}

//中断处理函数
void phy_Callback(ether_callback_args_t * p_args) 
{
    /* If EDMAC FR (Frame Receive Event) or FDE (Receive Descriptor Empty Event)
     * interrupt occurs, wake up xRxHanderTask. */
    if (p_args->status_eesr & ETHER_EDMAC_INTERRUPT_FACTOR_RECEPTION)
    {
        portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;                   //一般和portYIELD_FROM_ISR任务切换一起使用
        xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );   //释放信号量作用是用来和ethernetif_input网卡接收线程同步
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);                       //判断是否进行任务切换
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值