/** * @file main.c * @brief * * Copyright (c) 2021 Bouffalolab team * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * */ #include "bflb_platform.h" #include "hal_emac.h" #include "lwip/opt.h" #include "lwip/init.h" #include "netif/etharp.h" #include "lwip/netif.h" #include "lwip/tcpip.h" #if LWIP_DHCP #include "lwip/dhcp.h" #endif #include "ethernetif.h" #include "FreeRTOS.h" #include "task.h" #include "udp_echo.h" // Local IP address define /*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ #define IP_ADDR0 (uint8_t)192 #define IP_ADDR1 (uint8_t)168 #define IP_ADDR2 (uint8_t)1 #define IP_ADDR3 (uint8_t)221 // Local NET Mask address define /*NETMASK*/ #define NETMASK_ADDR0 (uint8_t)255 #define NETMASK_ADDR1 (uint8_t)255 #define NETMASK_ADDR2 (uint8_t)255 #define NETMASK_ADDR3 (uint8_t)0 // Local Gateway address define /*Gateway Address*/ #define GW_ADDR0 (uint8_t)192 #define GW_ADDR1 (uint8_t)168 #define GW_ADDR2 (uint8_t)1 #define GW_ADDR3 (uint8_t)1 static uint8_t freertos_heap[4096 * 6]; struct netif gnetif; static HeapRegion_t xHeapRegions[] = { { (uint8_t *)freertos_heap, sizeof(freertos_heap) }, { NULL, 0 }, /* Terminates the array. */ { NULL, 0 } /* Terminates the array. */ }; /* For emac tx and rx,we put here to make controlling it's size easy */ #define ETH_RXBUFNB 5 #define ETH_TXBUFNB 5 uint8_t ethRxBuff[ETH_RXBUFNB][ETH_RX_BUFFER_SIZE] ATTR_EALIGN(4) = { 0 }; /* Ethernet Receive Buffers */ uint8_t ethTxBuff[ETH_TXBUFNB][ETH_TX_BUFFER_SIZE] ATTR_EALIGN(4); /* Ethernet Transmit Buffers */ void vAssertCalled(void) { uint32_t val; MSG("vAssertCalled\r\n"); __asm volatile("csrr %0, mcause" : "=r"(val)); MSG("RA=%08x\r\n", val); while (1) ; } void vApplicationTickHook(void) { //MSG("vApplicationTickHook\r\n"); } void vApplicationStackOverflowHook(void) { MSG("vApplicationStackOverflowHook\r\n"); while (1) ; } void vApplicationMallocFailedHook(void) { MSG("vApplicationMallocFailedHook\r\n"); while (1) ; } void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) { /* If the buffers to be provided to the Idle task are declared inside this function then they must be declared static - otherwise they will be allocated on the stack and so not exists after this function exits. */ static StaticTask_t xIdleTaskTCB; static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE]; /* Pass out a pointer to the StaticTask_t structure in which the Idle task's state will be stored. */ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; /* Pass out the array that will be used as the Idle task's stack. */ *ppxIdleTaskStackBuffer = uxIdleTaskStack; /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. Note that, as the array is necessarily of type StackType_t, configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } /* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the application must provide an implementation of vApplicationGetTimerTaskMemory() to provide the memory that is used by the Timer service task. */ void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) { /* If the buffers to be provided to the Timer task are declared inside this function then they must be declared static - otherwise they will be allocated on the stack and so not exists after this function exits. */ static StaticTask_t xTimerTaskTCB; static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH]; /* Pass out a pointer to the StaticTask_t structure in which the Timer task's state will be stored. */ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; /* Pass out the array that will be used as the Timer task's stack. */ *ppxTimerTaskStackBuffer = uxTimerTaskStack; /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. Note that, as the array is necessarily of type StackType_t, configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } /** * @brief Setup the network interface * @param None * @retval None */ static void netif_config(void) { ip_addr_t ipaddr; ip_addr_t netmask; ip_addr_t gw; #if LWIP_DHCP ip_addr_set_zero_ip4(&ipaddr); ip_addr_set_zero_ip4(&netmask); ip_addr_set_zero_ip4(&gw); #else /* IP address default setting */ IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); #endif /* add the network interface */ netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input); /* Registers the default network interface */ netif_set_default(&gnetif); ethernet_link_status_updated(&gnetif); #if LWIP_NETIF_LINK_CALLBACK netif_set_link_callback(&gnetif, ethernet_link_status_updated); #endif } static void emac_lwip_init() { MSG("lwip_init\r\n"); /* Initialize the LwIP stack */ tcpip_init(NULL, NULL); MSG("netif_config\r\n"); /* Configure the Network interface */ netif_config(); } void emac_init_txrx_buffer(void) { emac_bd_init((uint8_t *)ethTxBuff, ETH_TXBUFNB, (uint8_t *)ethRxBuff, ETH_RXBUFNB); } int main(void) { bflb_platform_init(0); MSG("EMAC lwip case\n"); cpu_global_irq_disable(); vPortDefineHeapRegions(xHeapRegions); emac_lwip_init(); // emac_stop_tx(); MSG("[OS] Starting udp echo task...\r\n"); udp_echo_init(); // udp_echo_raw_init(); vTaskStartScheduler(); BL_CASE_SUCCESS; while (1) { } }