diff --git a/software/tests/brain_eth/config b/software/tests/brain_eth/config index 76115490c76378986764b97851214f32e7ecc3f9..6da89897d1509b2157447ccb3cf92bb364e0e155 100644 --- a/software/tests/brain_eth/config +++ b/software/tests/brain_eth/config @@ -8,4 +8,6 @@ CONFIG_LICENSE_APP_BSD %inherit ethernet %include bmaaa.build -CONFIG_APP_START \ No newline at end of file +CONFIG_APP_START +CONFIG_INET +CONFIG_INET_IPV4 diff --git a/software/tests/brain_eth/main.c b/software/tests/brain_eth/main.c index 743fd381c317b9957326468ce1585783b93fea31..3f454e06b7d932d13c622c7ab13d8125ba37553d 100644 --- a/software/tests/brain_eth/main.c +++ b/software/tests/brain_eth/main.c @@ -1,60 +1,153 @@ -#include - -#include -#include #include +#include +#include +#include +#include +#include +#include + +#include +#include -#include -#include +#include +#include +#include +#include +#include +#include -static uint16_t smi_read(uint_fast8_t phy, - uint_fast8_t reg) +#define MTU 128 + +struct app_s +{ + struct device_net_s net; + struct net_scheduler_s scheduler; + struct buffer_pool_s packet_pool; + struct net_layer_s *eth; + struct net_layer_s *ipv4; + struct net_layer_s *icmp; +}; + +static +void eth_link_changed(void *delegate, struct net_layer_s *layer, bool_t connected) { - uint16_t val; - - cpu_mem_write_32(STM32_ETHERNET_MAC_ADDR + DWC_MAC_MIIAR_ADDR, 0 - | DWC_MAC_MIIAR_PA(phy) - | DWC_MAC_MIIAR_MR(reg) - | DWC_MAC_MIIAR_MB); + struct app_s *app = delegate; + + printk("Ethernet link now %s\n", connected ? "up" : "down"); +} - while (cpu_mem_read_32(STM32_ETHERNET_MAC_ADDR + DWC_MAC_MIIAR_ADDR) & DWC_MAC_MIIAR_MB) - ; +static +void eth_destroyed(void *delegate, struct net_layer_s *layer) +{ + struct app_s *app = delegate; - val = cpu_mem_read_32(STM32_ETHERNET_MAC_ADDR + DWC_MAC_MIIDR_ADDR); + printk("%s\n", __FUNCTION__); - return val; + assert(app->eth == layer); + app->eth = NULL; } -static void smi_write(uint_fast8_t phy, - uint_fast8_t reg, - uint16_t value) +static +void ipv4_destroyed(void *delegate, struct net_layer_s *layer) { - cpu_mem_write_32(STM32_ETHERNET_MAC_ADDR + DWC_MAC_MIIDR_ADDR, value); - cpu_mem_write_32(STM32_ETHERNET_MAC_ADDR + DWC_MAC_MIIAR_ADDR, 0 - | DWC_MAC_MIIAR_PA(phy) - | DWC_MAC_MIIAR_MR(reg) - | DWC_MAC_MIIAR_MW - | DWC_MAC_MIIAR_MB); - - while (cpu_mem_read_32(STM32_ETHERNET_MAC_ADDR + DWC_MAC_MIIAR_ADDR) & DWC_MAC_MIIAR_MB) - ; + struct app_s *app = delegate; + + printk("%s\n", __FUNCTION__); + + assert(app->ipv4 == layer); + app->ipv4 = NULL; } -static CONTEXT_ENTRY(main) +static +void icmp_destroyed(void *delegate, struct net_layer_s *layer) { - for (uint32_t phy = 0; phy < 32; ++phy) { - for (uint32_t reg = 0; reg < 8; ++reg) { - printk(" %d: %04x", reg, smi_read(phy, reg)); - } - printk("\n"); - } + struct app_s *app = delegate; + + printk("%s\n", __FUNCTION__); + + assert(app->icmp == layer); + app->icmp = NULL; } -void app_start(void) +static +SLAB_GROW(packet_pool_grow) { - struct thread_attr_s attr = { - .stack_size = 2048, - }; + return 5; +} + +static const struct net_ethernet_delegate_vtable_s eth_delegate_vtable = { + .base.release = eth_destroyed, + .link_changed = eth_link_changed, +}; - thread_create(main, 0, &attr); +static const struct net_layer_delegate_vtable_s ipv4_delegate_vtable = { + .release = ipv4_destroyed, +}; + +static const struct net_layer_delegate_vtable_s icmp_delegate_vtable = { + .release = icmp_destroyed, +}; + +void app_start() +{ + error_t err; + struct app_s *app; + + app = mem_alloc(sizeof(*app), mem_scope_sys); + if (!app) { + printk("Failed to create app context\n"); + return; + } + + err = device_get_accessor_by_path(&app->net.base, NULL, "eth*", DRIVER_CLASS_NET); + if (err) { + printk("Failed to get Ethernet device\n"); + return; + } + + buffer_pool_init(&app->packet_pool, MTU, packet_pool_grow, mem_scope_sys); + + err = net_scheduler_init(&app->scheduler, &app->packet_pool, "timer* rtc*"); + if (err) { + printk("Error while initializing net scheduler: %d\n", err); + return; + } + + err = DEVICE_OP(&app->net, layer_create, &app->scheduler, + NET_LAYER_ETHERNET, NULL, + app, ð_delegate_vtable.base, + &app->eth); + if (err) { + printk("Error while creating Ethernet layer: %d\n", err); + return; + } + + err = inet_ipv4_create(&app->scheduler, app, &ipv4_delegate_vtable, &app->ipv4); + if (err) { + printk("Error while creating ipv4 layer: %d\n", err); + return; + } + + err = net_layer_bind(app->eth, NULL, app->ipv4); + if (err) { + printk("Unable to bind ipv4 layer above ethernet: %d\n", err); + return; + } + + net_layer_refdec(app->ipv4); + + err = inet_icmp_create(&app->scheduler, app, &icmp_delegate_vtable, &app->icmp); + if (err) { + printk("Error while creating icmp layer: %d\n", err); + return; + } + + err = net_layer_bind(app->ipv4, (const uint8_t[]){ INET_IP_PROTO_ICMP }, app->icmp); + if (err) { + printk("Unable to bind icmp layer above ethernet: %d\n", err); + return; + } + + net_layer_refdec(app->icmp); } +