2021年花了两个月时间捣鼓了rt thread smart操作系统,其是一款国产开源操作系统,用起来的感觉和linux、freertos很像。其支持带mmu的芯片,理论上是支持linux端的程序移植的,因此可以取代一部分的嵌入式linux系统。下图摘自rt thread smart官网。

rt smart是2020年新推出的操作系统,目前支持的板子不多,想学习的话只能拿imx6ull板子来练练手了。我测试了art-pi samrt开发板、韦东山imx6ull和野火的imx6ull,都可以成功运行。
在linux上开发ethercat主站,需要配合xenomai。我想用rt thread smart操作系统来替换掉Linux,由于rt smart本身就是实时操作系统,因此也就不需要xenomai了。把之前基于linux开发的运动控制器程序,移植一下,理论上应该能在rt thread smart系统上跑起来。我打算先移植一下soem主站试试。
大概捣鼓了两周,终于跑起来了。imx6ull的网卡感觉存在bug,其芯片本身是内置enet1和enet0外设的,但是mdio只能访问一个phy外设,没法实时检测两个phy,一开启就会出错,所以只好都关了。这部分折腾了我好久,也没找到更好的解决办法。
调试后的效果就是,一个网口可以进行tcp/ip通讯,一个网口进行ethercat通讯。实验效果如下:

soem主站移植到rt thread smart操作系统

整个移植步骤和移植到stm32上的步骤差不多,主要就是网卡驱动部分比较繁琐。tcp/ip网口我是保留了rt smart的驱动框架,ethercat那个网口基本就是裸机程序。然后把ethercat网卡初始化代码嵌入tcp/ip网口驱动代码中。
驱动部分代码如下:

drv_eth.h

/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2021-06-16     songchao   first version* 2021-08-13     songchao   add more device info*/#ifndef __DRV_ETH_H__
#define __DRV_ETH_H__#include <rtthread.h>
#include <netif/ethernetif.h>
#include "fsl_phy.h"
#include "imx6ull.h"
#include "drv_common.h"#ifdef __cplusplus
extern "C" {
#endif#define MAX_ADDR_LEN 6
struct rt_imx6ul_ethps
{/* inherit from ethernet device */struct eth_device parent;/* interface address info, hw address */rt_uint8_t  dev_addr[MAX_ADDR_LEN];/* ETH_Speed */uint32_t    ETH_Speed;/* ETH_Duplex_Mode */uint32_t    ETH_Mode;rt_bool_t phy_link_status;const char *mac_name;const char *irq_name;enum _imx_interrupts irq_num;uint8_t phy_num;const ENET_Type *enet_phy_base_addr;ENET_Type *enet_virtual_base_addr;uint32_t mac_num;enet_buffer_config_t buffConfig;enet_config_t config;enet_handle_t handle;GPIO_Type *phy_base_addr;uint32_t phy_gpio_pin;uint32_t phy_id;
};struct rt_imx6ul_lan8720
{/* interface address info, hw address */rt_uint8_t  dev_addr[MAX_ADDR_LEN];/* ETH_Speed */uint32_t    ETH_Speed;/* ETH_Duplex_Mode */uint32_t    ETH_Mode;rt_bool_t phy_link_status;const char *mac_name;uint8_t phy_num;const ENET_Type *enet_phy_base_addr;ENET_Type *enet_virtual_base_addr;uint32_t mac_num;enet_buffer_config_t buffConfig;enet_config_t config;enet_handle_t handle;GPIO_Type *phy_base_addr;uint32_t phy_gpio_pin;uint32_t phy_id;
};int32_t get_instance_by_base(void *base);
void enable_mdio_enet1(void);
void enable_mdio_enet2(void);
void enable_enet_gpio(void);
rt_err_t rt_imx6ul_lan8720_init(void);#ifdef __cplusplus
}
#endif#endif /* __DRV_ETH_H__ */

drv_eth.c

/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2021-06-16     songchao   support emac driver* 2021-06-29     songchao   add phy link detect* 2021-08-13     songchao   support dual mac and reduse copy*/#include "drv_eth.h"
#define DBG_TAG "drv.enet"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>#if (defined(RT_USING_ENET1)) || (defined(RT_USING_ENET2))static struct imx6ull_iomuxc mdio_gpio_enet1[2] =
{{IOMUXC_GPIO1_IO06_ENET1_MDIO,0U,0xB029},{IOMUXC_GPIO1_IO07_ENET1_MDC,0U,0xB0E9}
};static struct imx6ull_iomuxc mdio_gpio_enet2[2] =
{{IOMUXC_GPIO1_IO06_ENET2_MDIO,0U,0xB029},{IOMUXC_GPIO1_IO07_ENET2_MDC,0U,0xB0E9},
};static struct imx6ull_iomuxc enet1_gpio[9] =
{{IOMUXC_SNVS_SNVS_TAMPER9_GPIO5_IO09,0U,0x110B0},{IOMUXC_ENET1_RX_DATA0_ENET1_RDATA00,0U,0xB0E9},{IOMUXC_ENET1_RX_DATA1_ENET1_RDATA01,0U,0xB0E9},{IOMUXC_ENET1_RX_EN_ENET1_RX_EN,0U,0xB0E9},{IOMUXC_ENET1_RX_ER_ENET1_RX_ER,0U,0xB0E9},{IOMUXC_ENET1_TX_CLK_ENET1_REF_CLK1,1U,0x00F0},{IOMUXC_ENET1_TX_DATA0_ENET1_TDATA00,0U,0xB0E9},{IOMUXC_ENET1_TX_DATA1_ENET1_TDATA01,0U,0xB0E9},{IOMUXC_ENET1_TX_EN_ENET1_TX_EN,0U,0xB0E9}
};static struct imx6ull_iomuxc lan8720_gpio[9] =
{{IOMUXC_SNVS_SNVS_TAMPER6_GPIO5_IO06,0U,0x110B0},{IOMUXC_ENET2_RX_DATA0_ENET2_RDATA00,0U,0xB0E9},{IOMUXC_ENET2_RX_DATA1_ENET2_RDATA01,0U,0xB0E9},{IOMUXC_ENET2_RX_EN_ENET2_RX_EN,0U,0xB0E9},{IOMUXC_ENET2_RX_ER_ENET2_RX_ER,0U,0xB0E9},{IOMUXC_ENET2_TX_CLK_ENET2_REF_CLK2,1U,0x00F0},{IOMUXC_ENET2_TX_DATA0_ENET2_TDATA00,0U,0xB0E9},{IOMUXC_ENET2_TX_DATA1_ENET2_TDATA01,0U,0xB0E9},{IOMUXC_ENET2_TX_EN_ENET2_TX_EN,0U,0xB0E9}
};static struct rt_imx6ul_lan8720 _imx6ul_lan8720_device =
{.dev_addr = {0xa8,0x5e,0x45,0x01,0x02,0x03},.mac_name = "e2",.enet_phy_base_addr = ENET2,.phy_num = ENET_PHY2,.mac_num = 2,.phy_base_addr = GPIO5,.phy_gpio_pin = 6,.phy_id = 7,.buffConfig ={ENET_RXBD_NUM,ENET_TXBD_NUM,ENET_RXBUFF_ALIGN_SIZE,ENET_TXBUFF_ALIGN_SIZE,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,ENET_RXBUFF_TOTAL_SIZE,ENET_TXBUFF_TOTAL_SIZE},
};#define DEV_ENET_MAX 1static struct rt_imx6ul_ethps _imx6ul_eth_device[DEV_ENET_MAX] =
{
#ifdef RT_USING_ENET1{.dev_addr = {0xa8,0x5e,0x45,0x91,0x92,0x93},.mac_name = "e1",.irq_name = "emac1_intr",.enet_phy_base_addr = ENET1,.irq_num = IMX_INT_ENET1,.phy_num = ENET_PHY1,.mac_num = 1,.phy_base_addr = GPIO5,.phy_gpio_pin = 9,.phy_id = 7,.buffConfig ={ENET_RXBD_NUM,ENET_TXBD_NUM,ENET_RXBUFF_ALIGN_SIZE,ENET_TXBUFF_ALIGN_SIZE,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,ENET_RXBUFF_TOTAL_SIZE,ENET_TXBUFF_TOTAL_SIZE},},
#endif#ifdef RT_USING_ENET2{.dev_addr = {0xa8,0x5e,0x45,0x01,0x02,0x03},.mac_name = "e2",.irq_name = "emac2_intr",.enet_phy_base_addr = ENET2,.irq_num = IMX_INT_ENET2,.phy_num = ENET_PHY2,.mac_num = 2,.phy_base_addr = GPIO5,.phy_gpio_pin = 6,.phy_id = 7,.buffConfig ={ENET_RXBD_NUM,ENET_TXBD_NUM,ENET_RXBUFF_ALIGN_SIZE,ENET_TXBUFF_ALIGN_SIZE,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,RT_NULL,ENET_RXBUFF_TOTAL_SIZE,ENET_TXBUFF_TOTAL_SIZE},},
#endif
};void imx6ul_eth_link_change(struct rt_imx6ul_ethps *imx6ul_device,rt_bool_t up)
{if(up){LOG_D("enet%d link up\n",imx6ul_device->mac_num);eth_device_linkchange(&imx6ul_device->parent, RT_TRUE);imx6ul_device->phy_link_status = RT_TRUE;}else{LOG_D("enet%d link down\n",imx6ul_device->mac_num);eth_device_linkchange(&imx6ul_device->parent, RT_FALSE);imx6ul_device->phy_link_status = RT_FALSE;}
}void imx6ul_lan8720_link_change(struct rt_imx6ul_lan8720 *imx6ul_device,rt_bool_t up)
{if(up){LOG_D("enet%d link up\n",imx6ul_device->mac_num);imx6ul_device->phy_link_status = RT_TRUE;}else{LOG_D("enet%d link down\n",imx6ul_device->mac_num);imx6ul_device->phy_link_status = RT_FALSE;}
}void ENET_InitModuleClock(void)
{const clock_enet_pll_config_t config = {true, true, false, 1, 1};CLOCK_InitEnetPll(&config);
}rt_err_t enet_buffer_init(enet_buffer_config_t *buffConfig)
{void *tx_buff_addr = RT_NULL;void *rx_buff_addr = RT_NULL;void *tx_bd_addr = RT_NULL;void *rx_bd_addr = RT_NULL;if(((SYS_PAGE_SIZE<<RX_BUFFER_INDEX_NUM)<buffConfig->rxBufferTotalSize)||((SYS_PAGE_SIZE<<TX_BUFFER_INDEX_NUM)<buffConfig->txBufferTotalSize)){LOG_E("ERROR: alloc mem not enough for enet driver\n");return RT_ERROR;}rx_buff_addr = rt_pages_alloc(RX_BUFFER_INDEX_NUM);if(!rx_buff_addr){LOG_E("ERROR: rx buff page alloc failed\n");return RT_ERROR;}buffConfig->rxBufferAlign = (void *)rt_ioremap_nocache(virtual_to_physical(rx_buff_addr), (SYS_PAGE_SIZE<<RX_BUFFER_INDEX_NUM));buffConfig->rxPhyBufferAlign = (void *)virtual_to_physical(rx_buff_addr);tx_buff_addr = rt_pages_alloc(TX_BUFFER_INDEX_NUM);if(!tx_buff_addr){LOG_E("ERROR: tx buff page alloc failed\n");return RT_ERROR;}buffConfig->txBufferAlign = (void *)rt_ioremap_nocache(virtual_to_physical(tx_buff_addr), (SYS_PAGE_SIZE<<TX_BUFFER_INDEX_NUM));buffConfig->txPhyBufferAlign = (void *)virtual_to_physical(tx_buff_addr);rx_bd_addr = rt_pages_alloc(RX_BD_INDEX_NUM);if(!rx_bd_addr){LOG_E("ERROR: rx bd page alloc failed\n");return RT_ERROR;}buffConfig->rxBdStartAddrAlign = (void *)rt_ioremap_nocache(virtual_to_physical(rx_bd_addr), (SYS_PAGE_SIZE<<RX_BD_INDEX_NUM));buffConfig->rxPhyBdStartAddrAlign = virtual_to_physical(rx_bd_addr);tx_bd_addr = rt_pages_alloc(TX_BD_INDEX_NUM);if(!tx_bd_addr){LOG_E("ERROR: tx bd page alloc failed\n");return RT_ERROR;}buffConfig->txBdStartAddrAlign = (void *)rt_ioremap_nocache(virtual_to_physical(tx_bd_addr), (SYS_PAGE_SIZE<<TX_BD_INDEX_NUM));buffConfig->txPhyBdStartAddrAlign = virtual_to_physical(tx_bd_addr);return RT_EOK;
}rt_err_t rt_imx6ul_lan8720_init(void)
{rt_kprintf("\r\nrt_imx6ul_lan8720_init\r\n");rt_err_t state;struct rt_imx6ul_lan8720 *lan8720_device = &_imx6ul_lan8720_device;ENET_Type *base_addr = RT_NULL;enet_config_t *config;enet_handle_t *handle;enet_buffer_config_t *buffConfig;base_addr = lan8720_device->enet_virtual_base_addr;config = &lan8720_device->config;handle = &lan8720_device->handle;buffConfig = &lan8720_device->buffConfig;ENET_GetDefaultConfig(config);state = enet_buffer_init(buffConfig);if(state != RT_EOK){return state;}ENET_Init_lan8720(base_addr, handle, config, buffConfig, &lan8720_device->dev_addr[0], SYS_CLOCK_HZ);ENET_ActiveRead(base_addr);rt_kprintf("\r\nrt_imx6ul_lan8720_init end\r\n");return RT_EOK;
}/* EMAC initialization function */
static rt_err_t rt_imx6ul_eth_init(rt_device_t dev)
{rt_err_t state;struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;ENET_Type *base_addr = RT_NULL;enet_config_t *config;enet_handle_t *handle;enet_buffer_config_t *buffConfig;base_addr = imx6ul_device->enet_virtual_base_addr;config = &imx6ul_device->config;handle = &imx6ul_device->handle;buffConfig = &imx6ul_device->buffConfig;ENET_GetDefaultConfig(config);config->interrupt |= (ENET_RX_INTERRUPT);state = enet_buffer_init(buffConfig);if(state != RT_EOK){return state;}ENET_Init(base_addr, handle, config, buffConfig, &imx6ul_device->dev_addr[0], SYS_CLOCK_HZ);ENET_ActiveRead(base_addr);rt_hw_interrupt_install(imx6ul_device->irq_num, (rt_isr_handler_t)ENET_DriverIRQHandler, (void *)base_addr,imx6ul_device->irq_name);rt_hw_interrupt_umask(imx6ul_device->irq_num);return RT_EOK;
}static rt_err_t rt_imx6ul_eth_open(rt_device_t dev, rt_uint16_t oflag)
{return RT_EOK;
}static rt_err_t rt_imx6ul_eth_close(rt_device_t dev)
{return RT_EOK;
}static rt_size_t rt_imx6ul_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{return 0;
}static rt_size_t rt_imx6ul_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{return 0;
}static rt_err_t rt_imx6ul_eth_control(rt_device_t dev, int cmd, void *args)
{struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;switch (cmd){case NIOCTL_GADDR:/* get MAC address */if (args){rt_memcpy(args, imx6ul_device->dev_addr, MAX_ADDR_LEN);}else{return -RT_ERROR;}break;default :break;}return RT_EOK;
}static status_t read_data_from_eth(rt_device_t dev,void *read_data,uint16_t *read_length)
{status_t status = 0;uint16_t length = 0;ENET_Type *base_addr = RT_NULL;enet_config_t *config;enet_handle_t *handle;enet_buffer_config_t *buffConfig;struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;base_addr = imx6ul_device->enet_virtual_base_addr;config = &imx6ul_device->config;handle = &imx6ul_device->handle;buffConfig = &imx6ul_device->buffConfig;/* Get the Frame size */status = ENET_ReadFrame(base_addr,handle,config,read_data,&length);if((status == kStatus_ENET_RxFrameEmpty)||(status == kStatus_ENET_RxFrameError)){ENET_EnableInterrupts(base_addr,ENET_RX_INTERRUPT);if(status == kStatus_ENET_RxFrameError){/*recv error happend reinitialize mac*/ENET_Init(base_addr, handle, config, buffConfig, &imx6ul_device->dev_addr[0], SYS_CLOCK_HZ);ENET_ActiveRead(base_addr);return kStatus_ENET_RxFrameError;}else if(status == kStatus_ENET_RxFrameEmpty){return kStatus_ENET_RxFrameEmpty;}}*read_length = length;return status;
}/* transmit data*/
rt_err_t rt_imx6ul_eth_tx(rt_device_t dev, struct pbuf *p)
{rt_err_t ret = RT_ERROR;struct pbuf *q = RT_NULL;uint16_t offset = 0;uint32_t last_flag = 0;status_t status;ENET_Type *base_addr = RT_NULL;enet_handle_t *handle;struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev;base_addr = imx6ul_device->enet_virtual_base_addr;handle = &imx6ul_device->handle;RT_ASSERT(p);for(q = p;q != RT_NULL;q=q->next){if(q->next == RT_NULL){last_flag = 1;}else{last_flag = 0;}status = ENET_SendFrame(base_addr, handle, q->payload, q->len,last_flag);offset = offset + q->len;if(status == kStatus_Success){}else{return RT_ERROR;}}if(offset > ENET_FRAME_MAX_FRAMELEN){LOG_E("net error send length %d exceed max length\n",offset);}return ret;
}struct pbuf *rt_imx6ul_eth_rx(rt_device_t dev)
{static struct pbuf *p_s = RT_NULL;struct pbuf *p = RT_NULL;status_t status;uint16_t length = 0;if(p_s == RT_NULL){p_s = pbuf_alloc(PBUF_RAW, ENET_FRAME_MAX_FRAMELEN, PBUF_POOL);if(p_s == RT_NULL){return RT_NULL;}}p = p_s;status = read_data_from_eth(dev,p->payload,&length);if(status == kStatus_ENET_RxFrameEmpty){return RT_NULL;}else if(status == kStatus_ENET_RxFrameError){return RT_NULL;}if(length > ENET_FRAME_MAX_FRAMELEN){LOG_E("net error recv length %d exceed max length\n",length);return RT_NULL;}pbuf_realloc(p, length);p_s = RT_NULL;return p;
}int32_t get_instance_by_base(void *base)
{int32_t i = 0;int32_t instance = 0;for(i = 0; i < DEV_ENET_MAX; i ++){if((void *)_imx6ul_eth_device[i].enet_virtual_base_addr == base){break;}}if(i == DEV_ENET_MAX){return -1;}return instance;}
void rx_enet_callback(void *base)
{int32_t instance = 0;instance = get_instance_by_base(base);if(instance == -1){LOG_E("interrput match base addr error \n");return;}eth_device_ready(&(_imx6ul_eth_device[instance].parent));ENET_DisableInterrupts(base,ENET_RX_INTERRUPT);
}void tx_enet_callback(void *base)
{ENET_DisableInterrupts(base,ENET_TX_INTERRUPT);
}/*phy link detect thread*/
static void phy_detect_thread_entry(void *param)
{rt_kprintf("phy_detect_thread_entry!\n");bool link = false;ENET_Type *base_addr = RT_NULL;struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)param;base_addr = imx6ul_device->enet_virtual_base_addr;while(1){PHY_GetLinkStatus(base_addr, imx6ul_device->phy_num, &link);if(link != imx6ul_device->phy_link_status){          imx6ul_eth_link_change(imx6ul_device,link);}rt_thread_delay(DETECT_DELAY_ONE_SECOND);}
}/*phy link detect thread*/
static void lan8720_detect_thread_entry(void *param)
{rt_kprintf("lan8720_detect_thread_entry!\n");bool link_lan8720 = false;ENET_Type *lan8720_addr = RT_NULL;struct rt_imx6ul_lan8720 *lan8720_device =  (struct rt_imx6ul_lan8720 *)param;lan8720_addr = lan8720_device->enet_virtual_base_addr;while(1){     PHY_GetLinkStatus(lan8720_addr, lan8720_device->phy_num, &link_lan8720);if(link_lan8720 != lan8720_device->phy_link_status){         imx6ul_lan8720_link_change(lan8720_device,link_lan8720);}rt_thread_delay(DETECT_DELAY_ONE_SECOND);}
}_internal_ro struct rt_device_ops _k_enet_ops =
{rt_imx6ul_eth_init,rt_imx6ul_eth_open,rt_imx6ul_eth_close,rt_imx6ul_eth_read,rt_imx6ul_eth_write,rt_imx6ul_eth_control,
};void enable_mdio_enet1(void)
{imx6ull_gpio_init(&mdio_gpio_enet1[0]);imx6ull_gpio_init(&mdio_gpio_enet1[1]);
}void enable_mdio_enet2(void)
{imx6ull_gpio_init(&mdio_gpio_enet2[0]);imx6ull_gpio_init(&mdio_gpio_enet2[1]);
}void enable_enet_gpio(void)
{for (int i=0; i<GET_ARRAY_NUM(enet1_gpio); i++){imx6ull_gpio_init(&enet1_gpio[i]);}for (int i=0; i<GET_ARRAY_NUM(lan8720_gpio); i++){imx6ull_gpio_init(&lan8720_gpio[i]);}
}static int imx6ul_eth_init(void)
{rt_err_t state = RT_EOK;rt_uint32_t init_flag;phy_speed_t speed;phy_duplex_t duplex;bool link = false;bool link_lan8720 = false;// enable_mdio_enet2();enable_enet_gpio();phy_reset_all();rt_uint32_t reg_value;IOMUXC_GPR_Type *GPR1 = (IOMUXC_GPR_Type *)rt_ioremap((void *)IOMUXC_GPR,0x1000);reg_value = GPR1->GPR1;reg_value &= ~(IOMUXC_GPR_GPR1_ENET1_CLK_SEL_MASK| IOMUXC_GPR_GPR1_ENET1_CLK_SEL_MASK);reg_value |=  IOMUXC_GPR_GPR1_ENET1_TX_CLK_DIR(1);reg_value |=  IOMUXC_GPR_GPR1_ENET1_CLK_SEL(0);GPR1->GPR1 = reg_value;reg_value = GPR1->GPR1;reg_value &= ~(IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK| IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK);reg_value |=  IOMUXC_GPR_GPR1_ENET2_TX_CLK_DIR(1);reg_value |=  IOMUXC_GPR_GPR1_ENET2_CLK_SEL(0);GPR1->GPR1 = reg_value;ENET_InitModuleClock();_imx6ul_eth_device[0].enet_virtual_base_addr = (ENET_Type *)rt_ioremap((void *)ENET1,SYS_PAGE_SIZE);_imx6ul_lan8720_device.enet_virtual_base_addr = (ENET_Type *)rt_ioremap((void *)ENET2,SYS_PAGE_SIZE);_imx6ul_eth_device[0].phy_link_status   = RT_FALSE;_imx6ul_lan8720_device.phy_link_status = RT_FALSE;/****************************************************************************************/_imx6ul_eth_device[0].parent.parent.ops = &_k_enet_ops;_imx6ul_eth_device[0].parent.eth_rx     = rt_imx6ul_eth_rx;_imx6ul_eth_device[0].parent.eth_tx     = rt_imx6ul_eth_tx;/* register eth device */state = eth_device_init(&(_imx6ul_eth_device[0].parent), _imx6ul_eth_device[0].mac_name);if (RT_EOK == state){LOG_E("emac device init success\n");}else{LOG_E("emac device init faild: %d", state);state = -RT_ERROR;}/****************************************************************************************/enable_mdio_enet1();init_flag = PHY_Init_enet1(_imx6ul_eth_device[0].enet_virtual_base_addr,_imx6ul_eth_device[0].phy_num, SYS_CLOCK_HZ);if(init_flag == 0){rt_kprintf("PHY_Init enet1 success!\n");}PHY_GetLinkStatus(_imx6ul_eth_device[0].enet_virtual_base_addr,_imx6ul_eth_device[0].phy_num, &link);if (link){/* Get the actual PHY link speed. */PHY_GetLinkSpeedDuplex(_imx6ul_eth_device[0].enet_virtual_base_addr, _imx6ul_eth_device[0].phy_num, &speed, &duplex);/* Change the MII speed and duplex for actual link status. */_imx6ul_eth_device[0].config.miiSpeed = (enet_mii_speed_t)speed;_imx6ul_eth_device[0].config.miiDuplex = (enet_mii_duplex_t)duplex;rt_kprintf("\r\nenet1 Link up.\r\n");}else{rt_kprintf("\r\nenet1 Link down, please check the cable connection and link partner setting.\r\n");}if(link != _imx6ul_eth_device[0].phy_link_status){       imx6ul_eth_link_change(&_imx6ul_eth_device[0],link);}/****************************************************************************************/enable_mdio_enet2();rt_imx6ul_lan8720_init();init_flag = PHY_Init_enet2(_imx6ul_lan8720_device.enet_virtual_base_addr,_imx6ul_lan8720_device.phy_num, SYS_CLOCK_HZ);if(init_flag == 0){rt_kprintf("PHY_Init enet2 success!\n");}PHY_GetLinkStatus(_imx6ul_lan8720_device.enet_virtual_base_addr,_imx6ul_lan8720_device.phy_num, &link_lan8720);if (link_lan8720){/* Get the actual PHY link speed. */PHY_GetLinkSpeedDuplex(_imx6ul_lan8720_device.enet_virtual_base_addr,_imx6ul_lan8720_device.phy_num, &speed, &duplex);/* Change the MII speed and duplex for actual link status. */_imx6ul_lan8720_device.config.miiSpeed = (enet_mii_speed_t)speed;_imx6ul_lan8720_device.config.miiDuplex = (enet_mii_duplex_t)duplex;rt_kprintf("\r\nenet1 Link up.\r\n");}else{rt_kprintf("\r\nenet2 Link down, please check the cable connection and link partner setting.\r\n");}if(link_lan8720 != _imx6ul_lan8720_device.phy_link_status){       imx6ul_lan8720_link_change(&_imx6ul_lan8720_device,link_lan8720);}// char link_detect[10];// rt_sprintf(link_detect,"link_d%d",_imx6ul_eth_device[0].mac_num);// /* start phy link detect */// rt_thread_t phy_link_tid;// phy_link_tid = rt_thread_create(link_detect,//                         phy_detect_thread_entry,//                         &_imx6ul_eth_device[0],//                         4096,//                         21,//                         2);// if (phy_link_tid != RT_NULL)// {//     rt_thread_startup(phy_link_tid);// }// memset(link_detect,0,sizeof(link_detect));// char lan8720_detect[10];// rt_sprintf(lan8720_detect,"link_d%d",_imx6ul_lan8720_device.mac_num);// /* start phy link detect */// rt_thread_t lan8720_link_tid;// lan8720_link_tid = rt_thread_create(lan8720_detect,//                         lan8720_detect_thread_entry,//                         &_imx6ul_lan8720_device,//                         4096,//                         21,//                         2);// if (lan8720_link_tid != RT_NULL)// {//     rt_thread_startup(lan8720_link_tid);// }// memset(lan8720_detect,0,sizeof(lan8720_detect));return state;
}
INIT_DEVICE_EXPORT(imx6ul_eth_init);
#endif

soem主站移植到rt thread smart操作系统相关推荐

  1. 基于rt thread smart构建EtherCAT主站

    我把源码开源到到了gitee,https://gitee.com/rathon/rt-thread-smart-soem 有兴趣的去可以下载下来跑一下 软件工程推荐用vscode 打开.rt thre ...

  2. 正点原子delay函数移植到rt thread操作系统(HAL库)

    正点原子教程中涉及到的操作系统只涉及了UCOS的教程,其中例程的system文件夹中的delay.c函数只是适配了UCOS. 下面将delay.c函数移植到rt thread中,使用的bsp是rt t ...

  3. rt smart操作系统在“正点原子-阿尔法”开发板开箱使用

    1.准备 正点原子阿尔法linux开发板,SD卡,网络,USB线.由于正点原子的开发板和ART-PI-smart开发板使用的是一样的MPU,所以可以运行ART-PI-smart的程序. 下载ART-P ...

  4. RT Thread Free Modbus移植问题整理

    RT Thread Free Modbus移植问题整理 问题描述: 在读写寄存器中,写数据正常,只能读1个寄存器的值,多个值会异常. 在移植过程中发现串口(或RS485)数据接收长度异常. 一.环境描 ...

  5. 关于RT thread系统节拍时钟的配置

    关于RT thread系统节拍时钟的配置                  -----本文基于rt-thread-3.1.3版本编写 首先,使用RTthread OS时,要配置(或者明白)它的系统节拍 ...

  6. rt thread studio使用QBOOT和片外flash实现OTA升级

    我们这里要使用单片机外部flash作为OTA的下载分区,外部flash硬件连接关系 PB3-->SPI3_CLK PB4-->SPI3_MISO PB5-->SPI3_MOSI PE ...

  7. Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32

    1.前言     [2014年4月重写该博文]     经过若干时间的努力终于搞定了STM32+LwIP和yeelink平台的数据互通,在学习的过程中大部分时间花在以太网协议栈学习上,但是在RT Th ...

  8. RT Thread根据开发板制作BSP方法

    之前一直不懂怎么使用RT Thread的软件包,感谢网上的大神,看了你们的博客后大概了解一些,在此做下记录.用RT Thread软件包需要RT Thread的系统,但是RT Thread和RT Thr ...

  9. RT Thread利用STM32CUBEMX和RT Thread studio来创建模板工程

    (1)RT Thread利用STM32CUBEMX来创建模板工程 1.参考文档: 基于 CubeMX 移植 RT-Thread Nano:RT-Thread 文档中心 注意:串口2必须使能异步模式(启 ...

  10. xpt 2046的触摸屏 rt thread设备驱动框架

    1 基于rtt 开发触摸屏驱动 准备使用rtt 框架 , 驱动xpt 2046的触摸屏, 翻阅大量资料发现, 大部分文章强调的是时序图, 而且很多代码要么直接操作寄存器, 要么是io 口模拟, 只能用 ...

最新文章

  1. python中的逻辑关系
  2. Java多线程(十二)之线程池深入分析(下)
  3. java执行python路径_java调用其它语言脚本(python、js)
  4. leetcode 617. 合并二叉树 思考分析
  5. 图像对齐(image alignment)
  6. 特征级融合_遥感影像融合的方法有哪些
  7. 如何设置jquery的ajax方法为同步
  8. mybatis 中的![CDATA[ ]]
  9. 信息安全问题频发:四成人讨厌大数据 六成人称微信谣言最多
  10. C#编写的打印排版控件拖拽软件
  11. 如何用自签名证书为.sis文件签名
  12. 解析DNA甲基化临床科研 | 无论什么科室,一定要有project的经典视角|易基因
  13. 阿里云cdn以及阿里云负载均衡配置方法
  14. 对绝对地址0x100000赋值 让程序跳转到绝对地址是0x100000去执行
  15. Markdown表格中换行、合并单元格
  16. VGA、DVI、HDMI、DP 接口介绍及优劣
  17. 给旧安卓手机安卓linux系统,手机秒变服务器(Linux Deploy)
  18. Docker下运行两个ClickHouse容器后 ReplicatedMergeTree引擎借助Zookeeper将数据无法同步的解决方案,提示错误为“DNS_ERROR”
  19. 百度飞桨图像分类------第三天(实现蝴蝶图像分类)
  20. 读书笔记《硬件十万个为什么——开发流程篇》

热门文章

  1. 【渝粤题库】广东开放大学 组织行为学 形成性考核
  2. 关于WebBrowser(浏览器)控件的调用
  3. java taglib开发_Java WEB开发实战 之 第六部分:Taglib基本知识和基本开发【私塾在线原创】...
  4. 【捡肥皂】,sql挂起清除工具 MS SQL2000挂起工具,无毒绿色,MSSQL手动清除挂起方法
  5. 清除html宏病毒,表格宏病毒怎么查杀 Excel宏病毒怎么清除?
  6. [BZOJ4653 区间]
  7. 安卓 电话黑名单拦截
  8. vue+elementui+quill富文本框+秀米编辑器和135编辑器
  9. 谷歌pixel手机解BL锁、刷机、破解电信(史上最详细的帖子)
  10. maya多边形建模怎样做曲面_maya中的曲面模型怎么转换成多边形?