From a157b25f55929cd46188f224b42a267be0cb9915 Mon Sep 17 00:00:00 2001 From: tanek liang Date: Fri, 9 Jun 2017 14:58:33 +0800 Subject: [PATCH] [bsp] added Ethernet driver and lwip in stm32f429-apollo board * use uart1 as default console device * add pcf8574 support(a general-purpose remote I/O expansion chip) --- bsp/stm32f429-apollo/drivers/SConscript | 2 +- bsp/stm32f429-apollo/drivers/board.h | 2 +- bsp/stm32f429-apollo/drivers/drv_eth.c | 596 +++++++++++++++++++++ bsp/stm32f429-apollo/drivers/drv_eth.h | 6 + bsp/stm32f429-apollo/drivers/drv_iic.c | 113 ++++ bsp/stm32f429-apollo/drivers/drv_iic.h | 24 + bsp/stm32f429-apollo/drivers/drv_pcf8574.c | 100 ++++ bsp/stm32f429-apollo/drivers/drv_pcf8574.h | 25 + bsp/stm32f429-apollo/rtconfig.h | 13 +- 9 files changed, 875 insertions(+), 6 deletions(-) create mode 100644 bsp/stm32f429-apollo/drivers/drv_eth.c create mode 100644 bsp/stm32f429-apollo/drivers/drv_eth.h create mode 100644 bsp/stm32f429-apollo/drivers/drv_iic.c create mode 100644 bsp/stm32f429-apollo/drivers/drv_iic.h create mode 100644 bsp/stm32f429-apollo/drivers/drv_pcf8574.c create mode 100644 bsp/stm32f429-apollo/drivers/drv_pcf8574.h diff --git a/bsp/stm32f429-apollo/drivers/SConscript b/bsp/stm32f429-apollo/drivers/SConscript index b73cfc4be..71d829e41 100644 --- a/bsp/stm32f429-apollo/drivers/SConscript +++ b/bsp/stm32f429-apollo/drivers/SConscript @@ -18,7 +18,7 @@ drv_mpu.c # add Ethernet drivers. if GetDepend('RT_USING_LWIP'): - src += ['drv_eth.c'] + src += ['drv_eth.c', 'drv_iic.c', 'drv_pcf8574.c'] # add gpio drivers. if GetDepend('RT_USING_PIN'): diff --git a/bsp/stm32f429-apollo/drivers/board.h b/bsp/stm32f429-apollo/drivers/board.h index 5b3d6f206..5090d04f1 100644 --- a/bsp/stm32f429-apollo/drivers/board.h +++ b/bsp/stm32f429-apollo/drivers/board.h @@ -61,7 +61,7 @@ extern int __bss_end; // Console on USART: <0=> no console <1=>USART 1 <2=>USART 2 <3=> USART 3 // Default: 1 -#define STM32_CONSOLE_USART 2 +#define STM32_CONSOLE_USART 1 void rt_hw_board_init(void); diff --git a/bsp/stm32f429-apollo/drivers/drv_eth.c b/bsp/stm32f429-apollo/drivers/drv_eth.c new file mode 100644 index 000000000..980083f39 --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_eth.c @@ -0,0 +1,596 @@ +/* + * File : application.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2017-06-08 tanek first implementation + */ +#include +#include +#include "lwipopts.h" +#include "board.h" +#include "drv_pcf8574.h" +#include +#include + +/* debug option */ +//#define DEBUG +//#define ETH_RX_DUMP +//#define ETH_TX_DUMP + +#ifdef DEBUG +#define STM32_ETH_PRINTF rt_kprintf +#else +#define STM32_ETH_PRINTF(...) +#endif + +/*网络引脚设置 RMII接口 + ETH_MDIO -------------------------> PA2 + ETH_MDC --------------------------> PC1 + ETH_RMII_REF_CLK------------------> PA1 + ETH_RMII_CRS_DV ------------------> PA7 + ETH_RMII_RXD0 --------------------> PC4 + ETH_RMII_RXD1 --------------------> PC5 + ETH_RMII_TX_EN -------------------> PB11 + ETH_RMII_TXD0 --------------------> PG13 + ETH_RMII_TXD1 --------------------> PG14 + ETH_RESET-------------------------> PCF8574扩展IO +*/ +#define ETH_MDIO_PORN GPIOA +#define ETH_MDIO_PIN GPIO_PIN_2 +#define ETH_MDC_PORN GPIOC +#define ETH_MDC_PIN GPIO_PIN_1 +#define ETH_RMII_REF_CLK_PORN GPIOA +#define ETH_RMII_REF_CLK_PIN GPIO_PIN_1 +#define ETH_RMII_CRS_DV_PORN GPIOA +#define ETH_RMII_CRS_DV_PIN GPIO_PIN_7 +#define ETH_RMII_RXD0_PORN GPIOC +#define ETH_RMII_RXD0_PIN GPIO_PIN_4 +#define ETH_RMII_RXD1_PORN GPIOC +#define ETH_RMII_RXD1_PIN GPIO_PIN_5 +#define ETH_RMII_TX_EN_PORN GPIOB +#define ETH_RMII_TX_EN_PIN GPIO_PIN_11 +#define ETH_RMII_TXD0_PORN GPIOG +#define ETH_RMII_TXD0_PIN GPIO_PIN_13 +#define ETH_RMII_TXD1_PORN GPIOG +#define ETH_RMII_TXD1_PIN GPIO_PIN_14 + +#define LAN8742A_PHY_ADDRESS 0x00 + +#define MAX_ADDR_LEN 6 +struct rt_stm32_eth +{ + /* inherit from ethernet device */ + struct eth_device parent; + + /* interface address info. */ + rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */ + + uint32_t ETH_Speed; /*!< @ref ETH_Speed */ + uint32_t ETH_Mode; /*!< @ref ETH_Duplex_Mode */ +}; + + +static ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB]; +static rt_uint8_t Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE], Tx_Buff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE]; +static rt_bool_t tx_is_waiting = RT_FALSE; +static ETH_HandleTypeDef EthHandle; +static struct rt_stm32_eth stm32_eth_device; +static struct rt_semaphore tx_wait; + +/* interrupt service routine */ +void ETH_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_ETH_IRQHandler(&EthHandle); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + if (tx_is_waiting == RT_TRUE) + { + tx_is_waiting = RT_FALSE; + rt_sem_release(&tx_wait); + } +} + +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + rt_err_t result; + result = eth_device_ready(&(stm32_eth_device.parent)); + if( result != RT_EOK ) + rt_kprintf("RX err =%d\n", result ); +} + +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) +{ + rt_kprintf("eth err\n"); +} + +static void phy_pin_reset(void) +{ + rt_base_t level; + + extern void delay_ms(rt_uint32_t nms); + + level = rt_hw_interrupt_disable(); + + rt_pcf8574_write_bit(ETH_RESET_IO, 1); + delay_ms(100); + rt_pcf8574_write_bit(ETH_RESET_IO, 0); + delay_ms(100); + + rt_hw_interrupt_enable(level); +} +#ifdef DEBUG +FINSH_FUNCTION_EXPORT(phy_pin_reset, phy hardware reset); +#endif + +/* initialize the interface */ +static rt_err_t rt_stm32_eth_init(rt_device_t dev) +{ + STM32_ETH_PRINTF("rt_stm32_eth_init...\n"); + + __HAL_RCC_ETH_CLK_ENABLE(); + + rt_pcf8574_init(); + phy_pin_reset(); + + /* ETHERNET Configuration --------------------------------------------------*/ + EthHandle.Instance = ETH; + EthHandle.Init.MACAddr = (rt_uint8_t*)&stm32_eth_device.dev_addr[0]; + EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; + EthHandle.Init.Speed = ETH_SPEED_100M; + EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX; + EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; + EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; + EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; + //EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; + EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS; + + HAL_ETH_DeInit(&EthHandle); + + /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */ + if (HAL_ETH_Init(&EthHandle) == HAL_OK) + { + STM32_ETH_PRINTF("eth hardware init sucess...\n"); + } + else + { + STM32_ETH_PRINTF("eth hardware init faild...\n"); + } + + /* Initialize Tx Descriptors list: Chain Mode */ + HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); + + /* Initialize Rx Descriptors list: Chain Mode */ + HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); + + /* Enable MAC and DMA transmission and reception */ + if (HAL_ETH_Start(&EthHandle) == HAL_OK) + { + STM32_ETH_PRINTF("eth hardware start success...\n"); + } + else + { + STM32_ETH_PRINTF("eth hardware start faild...\n"); + } + + //phy_monitor_thread_entry(NULL); + + return RT_EOK; +} + +static rt_err_t rt_stm32_eth_open(rt_device_t dev, rt_uint16_t oflag) +{ + STM32_ETH_PRINTF("rt_stm32_eth_open...\n"); + return RT_EOK; +} + +static rt_err_t rt_stm32_eth_close(rt_device_t dev) +{ + STM32_ETH_PRINTF("rt_stm32_eth_close...\n"); + return RT_EOK; +} + +static rt_size_t rt_stm32_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + STM32_ETH_PRINTF("rt_stm32_eth_read...\n"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t rt_stm32_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + STM32_ETH_PRINTF("rt_stm32_eth_write...\n"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t rt_stm32_eth_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + STM32_ETH_PRINTF("rt_stm32_eth_control...\n"); + switch(cmd) + { + case NIOCTL_GADDR: + /* get mac address */ + if(args) rt_memcpy(args, stm32_eth_device.dev_addr, 6); + else return -RT_ERROR; + break; + + default : + break; + } + + return RT_EOK; +} + +/* ethernet device interface */ +/* transmit packet. */ +rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p) +{ + rt_err_t ret = RT_ERROR; + HAL_StatusTypeDef state; + struct pbuf *q; + uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr); + __IO ETH_DMADescTypeDef *DmaTxDesc; + uint32_t framelength = 0; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t payloadoffset = 0; + + DmaTxDesc = EthHandle.TxDesc; + bufferoffset = 0; + + STM32_ETH_PRINTF("rt_stm32_eth_tx...\n"); + + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + while ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + rt_err_t result; + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + tx_is_waiting = RT_TRUE; + rt_hw_interrupt_enable(level); + + /* it's own bit set, wait it */ + result = rt_sem_take(&tx_wait, RT_WAITING_FOREVER); + if (result == RT_EOK) break; + if (result == -RT_ERROR) return -RT_ERROR; + } + + /* copy frame from pbufs to driver buffers */ + for(q = p; q != NULL; q = q->next) + { + /* Is this buffer available? If not, goto error */ + if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + STM32_ETH_PRINTF("buffer not valid ...\n"); + ret = ERR_USE; + goto error; + } + + STM32_ETH_PRINTF("copy one frame\n"); + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) + { + /* Copy data to Tx buffer*/ + memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) ); + + /* Point to next descriptor */ + DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); + + /* Check if the buffer is available */ + if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + STM32_ETH_PRINTF("dmatxdesc buffer not valid ...\n"); + ret = ERR_USE; + goto error; + } + + buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); + framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy ); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + +#ifdef ETH_TX_DUMP + { + rt_uint32_t i; + rt_uint8_t *ptr = buffer; + + STM32_ETH_PRINTF("tx_dump, len:%d\r\n", p->tot_len); + for(i=0; itot_len; i++) + { + STM32_ETH_PRINTF("%02x ",*ptr); + ptr++; + + if(((i+1)%8) == 0) + { + STM32_ETH_PRINTF(" "); + } + if(((i+1)%16) == 0) + { + STM32_ETH_PRINTF("\r\n"); + } + } + STM32_ETH_PRINTF("\r\ndump done!\r\n"); + } +#endif + + /* Prepare transmit descriptors to give to DMA */ + STM32_ETH_PRINTF("transmit frame, length: %d\n", framelength); + state = HAL_ETH_TransmitFrame(&EthHandle, framelength); + if (state != HAL_OK) + { + STM32_ETH_PRINTF("eth transmit frame faild: %d\n", state); + } + + ret = ERR_OK; + +error: + + /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */ + if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) + { + /* Clear TUS ETHERNET DMA flag */ + EthHandle.Instance->DMASR = ETH_DMASR_TUS; + + /* Resume DMA transmission*/ + EthHandle.Instance->DMATPDR = 0; + } + + return ret; +} + +/* reception packet. */ +struct pbuf *rt_stm32_eth_rx(rt_device_t dev) +{ + + struct pbuf *p = NULL; + struct pbuf *q = NULL; + HAL_StatusTypeDef state; + uint16_t len = 0; + uint8_t *buffer; + __IO ETH_DMADescTypeDef *dmarxdesc; + uint32_t bufferoffset = 0; + uint32_t payloadoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t i=0; + + STM32_ETH_PRINTF("rt_stm32_eth_rx\n"); + + /* Get received frame */ + state = HAL_ETH_GetReceivedFrame_IT(&EthHandle); + if (state != HAL_OK) + { + STM32_ETH_PRINTF("receive frame faild\n"); + return NULL; + } + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = EthHandle.RxFrameInfos.length; + buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer; + + STM32_ETH_PRINTF("receive frame len : %d\n", len); + + if (len > 0) + { + /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + } + +#ifdef ETH_RX_DUMP + { + rt_uint32_t i; + rt_uint8_t *ptr = buffer; + + STM32_ETH_PRINTF("rx_dump, len:%d\r\n", p->tot_len); + for (i = 0; i < len; i++) + { + STM32_ETH_PRINTF("%02x ", *ptr); + ptr++; + + if (((i + 1) % 8) == 0) + { + STM32_ETH_PRINTF(" "); + } + if (((i + 1) % 16) == 0) + { + STM32_ETH_PRINTF("\r\n"); + } + } + STM32_ETH_PRINTF("\r\ndump done!\r\n"); + } +#endif + + if (p != NULL) + { + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + bufferoffset = 0; + for(q = p; q != NULL; q = q->next) + { + byteslefttocopy = q->len; + payloadoffset = 0; + + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ + while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE ) + { + /* Copy data to pbuf */ + memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); + buffer = (uint8_t *)(dmarxdesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + /* Copy remaining data in pbuf */ + memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + } + + /* Release descriptors to DMA */ + /* Point to first descriptor */ + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (i=0; i< EthHandle.RxFrameInfos.SegCount; i++) + { + dmarxdesc->Status |= ETH_DMARXDESC_OWN; + dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + EthHandle.RxFrameInfos.SegCount =0; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + EthHandle.Instance->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + EthHandle.Instance->DMARPDR = 0; + } + + return p; +} + +static void NVIC_Configuration(void) +{ + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); +} + +/* + * GPIO Configuration for ETH + */ +static void GPIO_Configuration(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + STM32_ETH_PRINTF("GPIO_Configuration...\n"); + + /* Enable SYSCFG clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pull = GPIO_NOPULL; + + GPIO_InitStructure.Pin = ETH_MDIO_PIN; + HAL_GPIO_Init(ETH_MDIO_PORN,&GPIO_InitStructure); + GPIO_InitStructure.Pin = ETH_MDC_PIN; + HAL_GPIO_Init(ETH_MDC_PORN,&GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RMII_REF_CLK_PIN; + HAL_GPIO_Init(ETH_RMII_REF_CLK_PORN,&GPIO_InitStructure); + GPIO_InitStructure.Pin = ETH_RMII_CRS_DV_PIN; + HAL_GPIO_Init(ETH_RMII_CRS_DV_PORN,&GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RMII_REF_CLK_PIN; + HAL_GPIO_Init(ETH_RMII_REF_CLK_PORN,&GPIO_InitStructure); + GPIO_InitStructure.Pin = ETH_RMII_CRS_DV_PIN; + HAL_GPIO_Init(ETH_RMII_CRS_DV_PORN,&GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RMII_RXD0_PIN; + HAL_GPIO_Init(ETH_RMII_RXD0_PORN,&GPIO_InitStructure); + GPIO_InitStructure.Pin = ETH_RMII_RXD1_PIN; + HAL_GPIO_Init(ETH_RMII_RXD1_PORN,&GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RMII_TX_EN_PIN; + HAL_GPIO_Init(ETH_RMII_TX_EN_PORN,&GPIO_InitStructure); + GPIO_InitStructure.Pin = ETH_RMII_TXD0_PIN; + HAL_GPIO_Init(ETH_RMII_TXD0_PORN,&GPIO_InitStructure); + GPIO_InitStructure.Pin = ETH_RMII_TXD1_PIN; + HAL_GPIO_Init(ETH_RMII_TXD1_PORN,&GPIO_InitStructure); + + HAL_NVIC_SetPriority(ETH_IRQn,1,0); + HAL_NVIC_EnableIRQ(ETH_IRQn); +} + + +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_Configuration(); + NVIC_Configuration(); +} + +static int rt_hw_stm32_eth_init(void) +{ + rt_err_t state; + + stm32_eth_device.ETH_Speed = ETH_SPEED_100M; + stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX; + + /* OUI 00-80-E1 STMICROELECTRONICS. */ + stm32_eth_device.dev_addr[0] = 0x00; + stm32_eth_device.dev_addr[1] = 0x80; + stm32_eth_device.dev_addr[2] = 0xE1; + /* generate MAC addr from 96bit unique ID (only for test). */ + stm32_eth_device.dev_addr[3] = *(rt_uint8_t*)(UID_BASE+4); + stm32_eth_device.dev_addr[4] = *(rt_uint8_t*)(UID_BASE+2); + stm32_eth_device.dev_addr[5] = *(rt_uint8_t*)(UID_BASE+0); + + stm32_eth_device.parent.parent.init = rt_stm32_eth_init; + stm32_eth_device.parent.parent.open = rt_stm32_eth_open; + stm32_eth_device.parent.parent.close = rt_stm32_eth_close; + stm32_eth_device.parent.parent.read = rt_stm32_eth_read; + stm32_eth_device.parent.parent.write = rt_stm32_eth_write; + stm32_eth_device.parent.parent.control = rt_stm32_eth_control; + stm32_eth_device.parent.parent.user_data = RT_NULL; + + stm32_eth_device.parent.eth_rx = rt_stm32_eth_rx; + stm32_eth_device.parent.eth_tx = rt_stm32_eth_tx; + + STM32_ETH_PRINTF("sem init: tx_wait\r\n"); + /* init tx semaphore */ + rt_sem_init(&tx_wait, "tx_wait", 0, RT_IPC_FLAG_FIFO); + + /* register eth device */ + STM32_ETH_PRINTF("eth_device_init start\r\n"); + state = eth_device_init(&(stm32_eth_device.parent), "e0"); + if (RT_EOK == state) + { + STM32_ETH_PRINTF("eth_device_init success\r\n"); + } + else + { + STM32_ETH_PRINTF("eth_device_init faild: %d\r\n", state); + } + return state; +} +INIT_DEVICE_EXPORT(rt_hw_stm32_eth_init); diff --git a/bsp/stm32f429-apollo/drivers/drv_eth.h b/bsp/stm32f429-apollo/drivers/drv_eth.h new file mode 100644 index 000000000..b309ba00c --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_eth.h @@ -0,0 +1,6 @@ +#ifndef __DRV_ETH_H__ +#define __DRV_ETH_H__ + +void rt_hw_stm32_eth_init(void); + +#endif diff --git a/bsp/stm32f429-apollo/drivers/drv_iic.c b/bsp/stm32f429-apollo/drivers/drv_iic.c new file mode 100644 index 000000000..fe50970c7 --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_iic.c @@ -0,0 +1,113 @@ +/* + * File : drv_iic.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017 RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2017-06-05 tanek first implementation. + */ + +#include "drv_iic.h" + +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +static void stm32f4_i2c_gpio_init() +{ + GPIO_InitTypeDef GPIO_Initure; + + __HAL_RCC_GPIOH_CLK_ENABLE(); + + GPIO_Initure.Pin = GPIO_PIN_4 | GPIO_PIN_5; + GPIO_Initure.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_Initure.Pull = GPIO_PULLUP; + GPIO_Initure.Speed = GPIO_SPEED_FAST; + HAL_GPIO_Init(GPIOH, &GPIO_Initure); + + HAL_GPIO_WritePin(GPIOH, GPIO_PIN_5, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOH, GPIO_PIN_4, GPIO_PIN_SET); +} + +static void stm32f4_set_sda(void *data, rt_int32_t state) +{ + HAL_GPIO_WritePin(GPIOH, GPIO_PIN_5, (GPIO_PinState)state); +} + +static void stm32f4_set_scl(void *data, rt_int32_t state) +{ + HAL_GPIO_WritePin(GPIOH, GPIO_PIN_4, (GPIO_PinState)state); +} + +static rt_int32_t stm32f4_get_sda(void *data) +{ + return (rt_int32_t)HAL_GPIO_ReadPin(GPIOH, GPIO_PIN_5); +} + +static rt_int32_t stm32f4_get_scl(void *data) +{ + return (rt_int32_t)HAL_GPIO_ReadPin(GPIOH, GPIO_PIN_4); +} + +static void stm32f4_udelay(rt_uint32_t us) +{ + rt_int32_t i; + for (; us > 0; us--) + { + i = 50; + while (i > 0) + { + i--; + } + } +} + +static const struct rt_i2c_bit_ops bit_ops = { + RT_NULL, + stm32f4_set_sda, + stm32f4_set_scl, + stm32f4_get_sda, + stm32f4_get_scl, + + stm32f4_udelay, + + 5, + 100 +}; + +int stm32f4_i2c_init(void) +{ + struct rt_i2c_bus_device *bus; + + bus = rt_malloc(sizeof(struct rt_i2c_bus_device)); + if (bus == RT_NULL) + { + rt_kprintf("rt_malloc failed\n"); + return -RT_ENOMEM; + } + + rt_memset((void *)bus, 0, sizeof(struct rt_i2c_bus_device)); + + bus->priv = (void *)&bit_ops; + + stm32f4_i2c_gpio_init(); + + rt_i2c_bit_add_bus(bus, "i2c0"); + + return RT_EOK; +} +INIT_DEVICE_EXPORT(stm32f4_i2c_init); diff --git a/bsp/stm32f429-apollo/drivers/drv_iic.h b/bsp/stm32f429-apollo/drivers/drv_iic.h new file mode 100644 index 000000000..f31890e98 --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_iic.h @@ -0,0 +1,24 @@ +/* +* File : drv_iic.c +* This file is part of RT-Thread RTOS +* COPYRIGHT (C) 2017 RT-Thread Develop Team +* +* The license and distribution terms for this file may be +* found in the file LICENSE in this distribution or at +* http://www.rt-thread.org/license/LICENSE +* +* Change Logs: +* Date Author Notes +* 2017-06-05 tanek first implementation. +*/ + +#ifndef STM32F4XX_IIC_INCLUDED +#define STM32F4XX_IIC_INCLUDED + +#include +#include + +#include "stm32f4xx_hal.h" + + +#endif // STM32F20X_40X_SPI_H_INCLUDED diff --git a/bsp/stm32f429-apollo/drivers/drv_pcf8574.c b/bsp/stm32f429-apollo/drivers/drv_pcf8574.c new file mode 100644 index 000000000..4801a92bc --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_pcf8574.c @@ -0,0 +1,100 @@ +/* + * File : drv_iic.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017 RT-Thread Develop Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2017-06-09 tanek first implementation. + */ +#include "drv_pcf8574.h" +#include +#include +#include + +//#define DEBUG + +#ifdef DEBUG +#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +#define I2C_BUS_NAME "i2c0" +#define PCF8574_ADDR 0x20 + +static uint8_t rt_pcf8574_read_onebyte(void); +static void rt_pcf8574_write_onebyte(rt_uint8_t value); + +static struct rt_i2c_bus_device * i2c_bus; + +rt_err_t rt_pcf8574_init(void) +{ + rt_uint8_t buffer[] = { 0xFF }; + rt_off_t pos = PCF8574_ADDR; + + __HAL_RCC_GPIOB_CLK_ENABLE(); + + i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C_BUS_NAME); + if (i2c_bus == RT_NULL) + { + DEBUG_PRINTF("\ni2c_bus %s for PCF8574 not found!\n", I2C_BUS_NAME); + return -RT_ENOSYS; + } + + if (rt_device_open(&i2c_bus->parent, RT_NULL) != RT_EOK) + { + DEBUG_PRINTF("\ni2c_bus %s for cs43l22 opened failed!\n", I2C_BUS_NAME); + return -RT_EEMPTY; + } + + rt_device_write(&i2c_bus->parent, pos, &buffer, 1); + + return RT_EOK; +} + +static uint8_t rt_pcf8574_read_onebyte(void) +{ + rt_uint8_t value; + + rt_device_read(&i2c_bus->parent, PCF8574_ADDR, &value, 1); + + return value; +} + + +static void rt_pcf8574_write_onebyte(rt_uint8_t value) +{ + rt_device_write(&i2c_bus->parent, PCF8574_ADDR, &value, 1); +} + + +void rt_pcf8574_write_bit(rt_uint8_t bit, rt_uint8_t state) +{ + rt_uint8_t data; + data = rt_pcf8574_read_onebyte(); + + if (state == 0) + data &= ~(1 << bit); + else + data |= 1 << bit; + + rt_pcf8574_write_onebyte(data); +} + + +rt_uint8_t rt_pcf8574_read_bit(rt_uint8_t bit) +{ + rt_uint8_t data; + data = rt_pcf8574_read_onebyte(); + + if (data&(1 << bit)) + return 1; + else + return 0; +} + diff --git a/bsp/stm32f429-apollo/drivers/drv_pcf8574.h b/bsp/stm32f429-apollo/drivers/drv_pcf8574.h new file mode 100644 index 000000000..8940982c2 --- /dev/null +++ b/bsp/stm32f429-apollo/drivers/drv_pcf8574.h @@ -0,0 +1,25 @@ +#ifndef __DRV_PCF8574_H +#define __DRV_PCF8574_H + +#include +#include +#include +#include + +//PCF8574各个IO的功能 +#define BEEP_IO 0 //蜂鸣器控制引脚 P0 +#define AP_INT_IO 1 //AP3216C中断引脚 P1 +#define DCMI_PWDN_IO 2 //DCMI的电源控制引脚 P2 +#define USB_PWR_IO 3 //USB电源控制引脚 P3 +#define EX_IO 4 //扩展IO,自定义使用 P4 +#define MPU_INT_IO 5 //MPU9250中断引脚 P5 +#define RS485_RE_IO 6 //RS485_RE引脚 P6 +#define ETH_RESET_IO 7 //以太网复位引脚 P7 + +rt_err_t rt_pcf8574_init(void); + +void rt_pcf8574_write_bit(rt_uint8_t bit, rt_uint8_t state); +rt_uint8_t rt_pcf8574_read_bit(rt_uint8_t bit); + +#endif + diff --git a/bsp/stm32f429-apollo/rtconfig.h b/bsp/stm32f429-apollo/rtconfig.h index f175a11f3..09392f906 100644 --- a/bsp/stm32f429-apollo/rtconfig.h +++ b/bsp/stm32f429-apollo/rtconfig.h @@ -186,7 +186,9 @@ /* Enable DNS */ #define RT_LWIP_DNS /* Enable DHCP */ -//#define RT_LWIP_DHCP +#define RT_LWIP_DHCP +/* Enable DEBUG */ +//#define RT_LWIP_DEBUG /* the number of simulatenously active TCP connections*/ #define RT_LWIP_TCP_PCB_NUM 5 @@ -228,9 +230,9 @@ #define CHECKSUM_CHECK_IP 0 #define CHECKSUM_CHECK_UDP 0 -#define CHECKSUM_GEN_TCP 0 -#define CHECKSUM_GEN_IP 0 -#define CHECKSUM_GEN_UDP 0 +//#define CHECKSUM_GEN_TCP 0 +//#define CHECKSUM_GEN_IP 0 +//#define CHECKSUM_GEN_UDP 0 /* RT_GDB_STUB */ //#define RT_USING_GDB @@ -246,4 +248,7 @@ /* serial flash discoverable parameters by JEDEC standard */ #define RT_SFUD_USING_SFDP +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS + #endif -- GitLab