From dcdeffff9a2559357176e5d88c61b7e813686284 Mon Sep 17 00:00:00 2001 From: cpq Date: Sat, 27 Aug 2022 16:45:31 +0100 Subject: [PATCH] MIP refactor: use mg_hton*, move driver_data to ifp, parametrise f746 PLL setup --- examples/device-dashboard/net.c | 4 +- examples/stm32/nucleo-f746zg-baremetal/main.c | 9 +- examples/stm32/nucleo-f746zg-baremetal/mcu.h | 29 ++++--- mip/driver_stm32.c | 8 +- mip/mip.c | 75 +++++++++-------- mip/mip.h | 5 +- mongoose.c | 83 +++++++++---------- mongoose.h | 5 +- 8 files changed, 110 insertions(+), 108 deletions(-) diff --git a/examples/device-dashboard/net.c b/examples/device-dashboard/net.c index fbc6dfec..093eb522 100644 --- a/examples/device-dashboard/net.c +++ b/examples/device-dashboard/net.c @@ -211,7 +211,7 @@ void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data, #endif mg_http_serve_dir(c, ev_data, &opts); } - MG_INFO(("%.*s %.*s -> %.*s", (int) hm->method.len, hm->method.ptr, - (int) hm->uri.len, hm->uri.ptr, (int) 3, &c->send.buf[9])); + MG_DEBUG(("%.*s %.*s -> %.*s", (int) hm->method.len, hm->method.ptr, + (int) hm->uri.len, hm->uri.ptr, (int) 3, &c->send.buf[9])); } } diff --git a/examples/stm32/nucleo-f746zg-baremetal/main.c b/examples/stm32/nucleo-f746zg-baremetal/main.c index 202f32f5..9e54e909 100644 --- a/examples/stm32/nucleo-f746zg-baremetal/main.c +++ b/examples/stm32/nucleo-f746zg-baremetal/main.c @@ -30,7 +30,7 @@ void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms s_ticks++; } -void EXTI15_10_IRQHandler(void) { // External interrupt handler +void EXTI15_10_IRQHandler(void) { // External interrupt handler s_exti++; if (EXTI->PR & BIT(PINNO(BTN1))) EXTI->PR = BIT(PINNO(BTN1)); gpio_write(LED1, gpio_read(BTN1)); // No debounce. Turn LED if button pressed @@ -65,14 +65,13 @@ int main(void) { struct mg_mgr mgr; // Initialise Mongoose event manager mg_mgr_init(&mgr); // and attach it to the MIP interface mg_log_set(MG_LL_DEBUG); // Set log level - mg_timer_add(&mgr, 1000, MG_TIMER_REPEAT, blink_cb, &mgr); + mg_timer_add(&mgr, 500, MG_TIMER_REPEAT, blink_cb, &mgr); // Initialise Mongoose network stack // Specify MAC address, and use 0 for IP, mask, GW - i.e. use DHCP // For static configuration, specify IP/mask/GW in network byte order - struct mip_ipcfg ipcfg = { - .mac = {0xaa, 0xbb, 0xcc, 1, 2, 3}, .ip = 0, .mask = 0, .gw = 0}; - mip_init(&mgr, &ipcfg, &mip_driver_stm32); + struct mip_ipcfg c = {.mac = {0, 0, 1, 2, 3, 4}, .ip = 0, .mask = 0, .gw = 0}; + mip_init(&mgr, &c, &mip_driver_stm32, NULL); MG_INFO(("Init done, starting main loop")); extern void device_dashboard_fn(struct mg_connection *, int, void *, void *); diff --git a/examples/stm32/nucleo-f746zg-baremetal/mcu.h b/examples/stm32/nucleo-f746zg-baremetal/mcu.h index 675b3f9b..d5714e11 100644 --- a/examples/stm32/nucleo-f746zg-baremetal/mcu.h +++ b/examples/stm32/nucleo-f746zg-baremetal/mcu.h @@ -14,8 +14,13 @@ #define PIN(bank, num) ((((bank) - 'A') << 8) | (num)) #define PINNO(pin) (pin & 255) #define PINBANK(pin) (pin >> 8) -//#define FREQ 16000000 -#define FREQ 216000000 + +// System clock +enum { APB1_PRE = 5 /* AHB clock / 4*/, APB2_PRE = 4 /* AHB clock / 2 */ }; +enum { PLL_HSI = 16, PLL_M = 8, PLL_N = 216, PLL_P = 2 }; // Run at 216 Mhz +//#define PLL_FREQ PLL_HSI +#define PLL_FREQ (PLL_HSI * PLL_N / PLL_M / PLL_P) +#define FREQ (PLL_FREQ * 1000000) static inline void spin(volatile uint32_t count) { while (count--) asm("nop"); @@ -168,7 +173,7 @@ static inline void uart_init(struct uart *uart, unsigned long baud) { gpio_init(tx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af); gpio_init(rx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af); uart->CR1 = 0; // Disable this UART - uart->BRR = FREQ / 4 / baud; // Baud rate. /4 is a PLL prescaler + uart->BRR = FREQ / APB2_PRE / baud; // Baud rate. /4 is a PLL prescaler uart->CR1 |= BIT(0) | BIT(2) | BIT(3); // Set UE, RE, TE } static inline void uart_write_byte(struct uart *uart, uint8_t byte) { @@ -186,7 +191,7 @@ static inline uint8_t uart_read_byte(struct uart *uart) { } static inline void clock_init(void) { // Set clock to 216Mhz -#if 1 +#if 0 RCC->APB1ENR |= BIT(28); // Power enable PWR->CR1 |= 3UL << 14; // Voltage regulator scale 3 PWR->CR1 |= BIT(16); // Enable overdrive @@ -195,11 +200,13 @@ static inline void clock_init(void) { // Set clock to 216Mhz while ((PWR->CSR1 & BIT(17)) == 0) spin(1); // Wait until done SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU #endif - FLASH->ACR |= 7 | BIT(8) | BIT(9); // Flash latency 7, prefetch - RCC->PLLCFGR &= ~((BIT(15) - 1)); // PLL = HSI * N / M / P - RCC->PLLCFGR |= 8UL | (216UL << 6); // M = 8, N = 216, P = 2. 216Mhz - RCC->CR |= BIT(24); // Enable PLL - while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done - RCC->CFGR = 2 | (5UL << 10) | (4UL << 13); // Set prescalers and PLL clock - while ((RCC->CFGR & 12) == 0) spin(1); // Wait until done + FLASH->ACR |= 7 | BIT(8) | BIT(9); // Flash latency 7, prefetch + RCC->PLLCFGR &= ~((BIT(17) - 1)); // Clear PLL multipliers + RCC->PLLCFGR |= (((PLL_P - 2) / 2) & 3) << 16; // Set PLL_P + RCC->PLLCFGR |= PLL_M | (PLL_N << 6); // Set PLL_M and PLL_N + RCC->CR |= BIT(24); // Enable PLL + while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done + RCC->CFGR = (APB1_PRE << 10) | (APB2_PRE << 13); // Set prescalers + RCC->CFGR |= 2; // Set clock source to PLL + while ((RCC->CFGR & 12) == 0) spin(1); // Wait until done } diff --git a/mip/driver_stm32.c b/mip/driver_stm32.c index 132b5f68..c3c4c448 100644 --- a/mip/driver_stm32.c +++ b/mip/driver_stm32.c @@ -31,7 +31,6 @@ static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers static void (*s_rx)(void *, size_t, void *); // Recv callback static void *s_rxdata; // Recv callback data -static void *s_userdata; // Driver data enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; // PHY constants static inline void spin(volatile uint32_t count) { @@ -54,9 +53,7 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) { while (ETH->MACMIIAR & BIT(0)) spin(1); } -static void mip_driver_stm32_init(void *userdata) { - s_userdata = userdata; - +static void mip_driver_stm32_init(uint8_t *mac, void *userdata) { // Init RX descriptors for (int i = 0; i < ETH_DESC_CNT; i++) { s_rxdesc[i][0] = BIT(31); // Own @@ -89,6 +86,9 @@ static void mip_driver_stm32_init(void *userdata) { ETH->DMAIER = BIT(6) | BIT(16); // RIE, NISE ETH->MACCR = BIT(2) | BIT(3) | BIT(11) | BIT(14); // RE, TE, Duplex, Fast ETH->DMAOMR = BIT(1) | BIT(13) | BIT(21) | BIT(25); // SR, ST, TSF, RSF + + // TODO(cpq): setup MAC filtering + (void) userdata, (void) mac; } static void mip_driver_stm32_setrx(void (*rx)(void *, size_t, void *), diff --git a/mip/mip.c b/mip/mip.c index 00d0ef4d..cf4b50bd 100644 --- a/mip/mip.c +++ b/mip/mip.c @@ -4,12 +4,8 @@ #if defined(_MSC_VER) #define _Atomic -#define NET16(x) _byteswap_ushort(x) -#define NET32(x) _byteswap_ulong(x) #else #include -#define NET16(x) __builtin_bswap16(x) -#define NET32(x) __builtin_bswap32(x) #endif #define MIP_ETHEMERAL_PORT 49152 @@ -43,6 +39,7 @@ struct mip_if { struct str tx; // Input (RX) buffer bool use_dhcp; // Enable DCHP struct mip_driver *driver; // Low level driver + void *driver_data; // Driver-specific data struct mg_mgr *mgr; // Mongoose event manager // Internal state, user can use it but should not change it @@ -220,7 +217,7 @@ static uint32_t csumup(uint32_t sum, const void *buf, size_t len) { static uint16_t csumfin(uint32_t sum) { while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); - return NET16(~sum & 0xffff); + return mg_htons(~sum & 0xffff); } static uint16_t ipcsum(const void *buf, size_t len) { @@ -264,7 +261,7 @@ static void arp_cache_add(struct mip_if *ifp, uint32_t ip, uint8_t mac[6]) { memcpy(p + p[0] + 2, &ip, sizeof(ip)); // Replace last entry: IP address memcpy(p + p[0] + 6, mac, 6); // And MAC address p[1] = p[0], p[0] = p[p[1]]; // Point list head to us - MG_DEBUG(("ARP cache: added %#lx @ %x:%x:%x:%x:%x:%x", (long) NET32(ip), + MG_DEBUG(("ARP cache: added %#lx @ %x:%x:%x:%x:%x:%x", (long) mg_htonl(ip), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); } @@ -273,12 +270,13 @@ static void arp_ask(struct mip_if *ifp, uint32_t ip) { struct arp *arp = (struct arp *) (eth + 1); memset(eth->dst, 255, sizeof(eth->dst)); memcpy(eth->src, ifp->mac, sizeof(eth->src)); - eth->type = NET16(0x806); + eth->type = mg_htons(0x806); memset(arp, 0, sizeof(*arp)); - arp->fmt = NET16(1), arp->pro = NET16(0x800), arp->hlen = 6, arp->plen = 4; - arp->op = NET16(1), arp->tpa = ip, arp->spa = ifp->ip; + arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6, + arp->plen = 4; + arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip; memcpy(arp->sha, ifp->mac, sizeof(arp->sha)); - ifp->driver->tx(eth, PDIFF(eth, arp + 1), ifp->driver->data); + ifp->driver->tx(eth, PDIFF(eth, arp + 1), ifp->driver_data); } static void onstatechange(struct mip_if *ifp) { @@ -303,11 +301,11 @@ static struct ip *tx_ip(struct mip_if *ifp, uint8_t proto, uint32_t ip_src, if (mac) memcpy(eth->dst, mac, sizeof(eth->dst)); // Found? Use it if (!mac) memset(eth->dst, 255, sizeof(eth->dst)); // No? Use broadcast memcpy(eth->src, ifp->mac, sizeof(eth->src)); // TODO(cpq): ARP lookup - eth->type = NET16(0x800); + eth->type = mg_htons(0x800); memset(ip, 0, sizeof(*ip)); ip->ver = 0x45; // Version 4, header length 5 words ip->frag = 0x40; // Don't fragment - ip->len = NET16((uint16_t) (sizeof(*ip) + plen)); + ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen)); ip->ttl = 64; ip->proto = proto; ip->src = ip_src; @@ -324,7 +322,7 @@ static void tx_udp(struct mip_if *ifp, uint32_t ip_src, uint16_t sport, // MG_DEBUG(("UDP XX LEN %d %d", (int) len, (int) ifp->tx.len)); udp->sport = sport; udp->dport = dport; - udp->len = NET16((uint16_t) (sizeof(*udp) + len)); + udp->len = mg_htons((uint16_t) (sizeof(*udp) + len)); udp->csum = 0; uint32_t cs = csumup(0, udp, sizeof(*udp)); cs = csumup(cs, buf, len); @@ -336,7 +334,7 @@ static void tx_udp(struct mip_if *ifp, uint32_t ip_src, uint16_t sport, // MG_DEBUG(("UDP LEN %d %d\n", (int) len, (int) ifp->frame_len)); ifp->driver->tx(ifp->tx.buf, sizeof(struct eth) + sizeof(*ip) + sizeof(*udp) + len, - ifp->driver->data); + ifp->driver_data); } static void tx_dhcp(struct mip_if *ifp, uint32_t src, uint32_t dst, @@ -345,11 +343,11 @@ static void tx_dhcp(struct mip_if *ifp, uint32_t src, uint32_t dst, .htype = 1, .hlen = 6, .ciaddr = src, - .magic = NET32(0x63825363)}; + .magic = mg_htonl(0x63825363)}; memcpy(&dhcp.hwaddr, ifp->mac, sizeof(ifp->mac)); memcpy(&dhcp.xid, ifp->mac + 2, sizeof(dhcp.xid)); memcpy(&dhcp.options, opts, optslen); - tx_udp(ifp, src, NET16(68), dst, NET16(67), &dhcp, sizeof(dhcp)); + tx_udp(ifp, src, mg_htons(68), dst, mg_htons(67), &dhcp, sizeof(dhcp)); } static void tx_dhcp_request(struct mip_if *ifp, uint32_t src, uint32_t dst) { @@ -376,23 +374,23 @@ static void tx_dhcp_discover(struct mip_if *ifp) { } static void rx_arp(struct mip_if *ifp, struct pkt *pkt) { - if (pkt->arp->op == NET16(1) && pkt->arp->tpa == ifp->ip) { + if (pkt->arp->op == mg_htons(1) && pkt->arp->tpa == ifp->ip) { // ARP request. Make a response, then send struct eth *eth = (struct eth *) ifp->tx.buf; struct arp *arp = (struct arp *) (eth + 1); - MG_DEBUG(("ARP op %d %#x %#x", NET16(arp->op), arp->spa, arp->tpa)); + MG_DEBUG(("ARP op %d %#x %#x", mg_htons(arp->op), arp->spa, arp->tpa)); memcpy(eth->dst, pkt->eth->src, sizeof(eth->dst)); memcpy(eth->src, ifp->mac, sizeof(eth->src)); - eth->type = NET16(0x806); + eth->type = mg_htons(0x806); *arp = *pkt->arp; - arp->op = NET16(2); + arp->op = mg_htons(2); memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha)); memcpy(arp->sha, ifp->mac, sizeof(pkt->arp->sha)); arp->tpa = pkt->arp->spa; arp->spa = ifp->ip; - MG_DEBUG(("ARP response: we're %#lx", (long) ifp->ip)); - ifp->driver->tx(ifp->tx.buf, PDIFF(eth, arp + 1), ifp->driver->data); - } else if (pkt->arp->op == NET16(2)) { + MG_DEBUG(("ARP response: we're %#lx", (long) mg_ntohl(ifp->ip))); + ifp->driver->tx(ifp->tx.buf, PDIFF(eth, arp + 1), ifp->driver_data); + } else if (pkt->arp->op == mg_htons(2)) { if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return; // MG_INFO(("ARP RESPONSE")); arp_cache_add(ifp, pkt->arp->spa, pkt->arp->sha); @@ -409,7 +407,7 @@ static void rx_icmp(struct mip_if *ifp, struct pkt *pkt) { memcpy(icmp + 1, pkt->pay.buf, pkt->pay.len); icmp->csum = ipcsum(icmp, sizeof(*icmp) + pkt->pay.len); ifp->driver->tx(ifp->tx.buf, PDIFF(ifp->tx.buf, icmp + 1) + pkt->pay.len, - ifp->driver->data); + ifp->driver_data); } } @@ -501,7 +499,7 @@ static size_t tx_tcp(struct mip_if *ifp, uint32_t dst_ip, uint8_t flags, cs = csumup(cs, pseudo, sizeof(pseudo)); tcp->csum = csumfin(cs); return ifp->driver->tx(ifp->tx.buf, PDIFF(ifp->tx.buf, tcp + 1) + len, - ifp->driver->data); + ifp->driver_data); } static size_t tx_tcp_pkt(struct mip_if *ifp, struct pkt *pkt, uint8_t flags, @@ -603,10 +601,10 @@ static void rx_ip(struct mip_if *ifp, struct pkt *pkt) { } else if (pkt->ip->proto == 17) { pkt->udp = (struct udp *) (pkt->ip + 1); if (pkt->pay.len < sizeof(*pkt->udp)) return; - // MG_DEBUG((" UDP %u %u -> %u\n", len, NET16(udp->sport), - // NET16(udp->dport))); + // MG_DEBUG((" UDP %u %u -> %u\n", len, mg_htons(udp->sport), + // mg_htons(udp->dport))); mkpay(pkt, pkt->udp + 1); - if (pkt->udp->dport == NET16(68)) { + if (pkt->udp->dport == mg_htons(68)) { pkt->dhcp = (struct dhcp *) (pkt->udp + 1); mkpay(pkt, pkt->dhcp + 1); rx_dhcp(ifp, pkt); @@ -634,8 +632,8 @@ static void rx_ip6(struct mip_if *ifp, struct pkt *pkt) { } else if (pkt->ip->proto == 17) { pkt->udp = (struct udp *) (pkt->ip6 + 1); if (pkt->pay.len < sizeof(*pkt->udp)) return; - // MG_DEBUG((" UDP %u %u -> %u\n", len, NET16(udp->sport), - // NET16(udp->dport))); + // MG_DEBUG((" UDP %u %u -> %u\n", len, mg_htons(udp->sport), + // mg_htons(udp->dport))); mkpay(pkt, pkt->udp + 1); } } @@ -648,24 +646,24 @@ static void mip_rx(struct mip_if *ifp, void *buf, size_t len) { if (memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 && memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0) { // Not for us. Drop silently - } else if (pkt.eth->type == NET16(0x806)) { + } else if (pkt.eth->type == mg_htons(0x806)) { pkt.arp = (struct arp *) (pkt.eth + 1); if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated rx_arp(ifp, &pkt); - } else if (pkt.eth->type == NET16(0x86dd)) { + } else if (pkt.eth->type == mg_htons(0x86dd)) { pkt.ip6 = (struct ip6 *) (pkt.eth + 1); if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip6)) return; // Truncated if ((pkt.ip6->ver >> 4) != 0x6) return; // Not IP mkpay(&pkt, pkt.ip6 + 1); rx_ip6(ifp, &pkt); - } else if (pkt.eth->type == NET16(0x800)) { + } else if (pkt.eth->type == mg_htons(0x800)) { pkt.ip = (struct ip *) (pkt.eth + 1); if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return; // Truncated if ((pkt.ip->ver >> 4) != 4) return; // Not IP mkpay(&pkt, pkt.ip + 1); rx_ip(ifp, &pkt); } else { - MG_DEBUG((" Unknown eth type %x\n", NET16(pkt.eth->type))); + MG_DEBUG((" Unknown eth type %x\n", mg_htons(pkt.eth->type))); } } @@ -684,7 +682,7 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) { // Handle physical interface up/down status if (ifp->driver->status) { - bool up = ifp->driver->status(ifp->driver->data); + bool up = ifp->driver->status(ifp->driver_data); bool current = ifp->state != MIP_STATE_DOWN; if (up != current) { ifp->state = up == false ? MIP_STATE_DOWN @@ -699,7 +697,7 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) { for (;;) { size_t len = ifp->queue.len > 0 ? q_read(&ifp->queue, ifp->rx.buf) : ifp->driver->rx(ifp->rx.buf, ifp->rx.len, - ifp->driver->data); + ifp->driver_data); if (len == 0) break; mip_rx(ifp, ifp->rx.buf, len); } @@ -714,7 +712,7 @@ static void on_rx(void *buf, size_t len, void *userdata) { } void mip_init(struct mg_mgr *mgr, struct mip_ipcfg *ipcfg, - struct mip_driver *driver) { + struct mip_driver *driver, void *driver_data) { size_t maxpktsize = 1500, qlen = driver->rxcb ? 1024 * 16 : 0; struct mip_if *ifp = (struct mip_if *) calloc(1, sizeof(*ifp) + 2 * maxpktsize + qlen); @@ -724,10 +722,11 @@ void mip_init(struct mg_mgr *mgr, struct mip_ipcfg *ipcfg, ifp->rx.buf = (uint8_t *) (ifp + 1), ifp->rx.len = maxpktsize; ifp->tx.buf = ifp->rx.buf + maxpktsize, ifp->tx.len = maxpktsize; ifp->driver = driver; + ifp->driver_data = driver_data; ifp->mgr = mgr; ifp->queue.buf = ifp->tx.buf + maxpktsize; ifp->queue.len = qlen; - if (driver->init) driver->init(driver->data); + if (driver->init) driver->init(ipcfg->mac, driver_data); if (driver->rxcb) driver->rxcb(on_rx, ifp); mgr->priv = ifp; mgr->extraconnsize = sizeof(struct tcpstate); diff --git a/mip/mip.h b/mip/mip.h index 33b7ea55..9908a5f3 100644 --- a/mip/mip.h +++ b/mip/mip.h @@ -4,8 +4,7 @@ #include "net.h" struct mip_driver { - void *data; // Driver-specific data - void (*init)(void *data); // Initialise driver + void (*init)(uint8_t *mac, void *data); // Initialise driver size_t (*tx)(const void *, size_t, void *data); // Transmit frame size_t (*rx)(void *buf, size_t len, void *data); // Receive frame (polling) bool (*status)(void *data); // Up/down status @@ -18,6 +17,6 @@ struct mip_ipcfg { uint32_t ip, mask, gw; // IP, netmask, GW. If IP is 0, DHCP is used }; -void mip_init(struct mg_mgr *, struct mip_ipcfg *, struct mip_driver *); +void mip_init(struct mg_mgr *, struct mip_ipcfg *, struct mip_driver *, void *); extern struct mip_driver mip_driver_stm32; diff --git a/mongoose.c b/mongoose.c index af4ced9c..98398983 100644 --- a/mongoose.c +++ b/mongoose.c @@ -5957,7 +5957,6 @@ static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers static void (*s_rx)(void *, size_t, void *); // Recv callback static void *s_rxdata; // Recv callback data -static void *s_userdata; // Driver data enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; // PHY constants static inline void spin(volatile uint32_t count) { @@ -5980,9 +5979,7 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) { while (ETH->MACMIIAR & BIT(0)) spin(1); } -static void mip_driver_stm32_init(void *userdata) { - s_userdata = userdata; - +static void mip_driver_stm32_init(uint8_t *mac, void *userdata) { // Init RX descriptors for (int i = 0; i < ETH_DESC_CNT; i++) { s_rxdesc[i][0] = BIT(31); // Own @@ -6015,6 +6012,9 @@ static void mip_driver_stm32_init(void *userdata) { ETH->DMAIER = BIT(6) | BIT(16); // RIE, NISE ETH->MACCR = BIT(2) | BIT(3) | BIT(11) | BIT(14); // RE, TE, Duplex, Fast ETH->DMAOMR = BIT(1) | BIT(13) | BIT(21) | BIT(25); // SR, ST, TSF, RSF + + // TODO(cpq): setup MAC filtering + (void) userdata, (void) mac; } static void mip_driver_stm32_setrx(void (*rx)(void *, size_t, void *), @@ -6083,12 +6083,8 @@ struct mip_driver mip_driver_stm32 = {.init = mip_driver_stm32_init, #if defined(_MSC_VER) #define _Atomic -#define NET16(x) _byteswap_ushort(x) -#define NET32(x) _byteswap_ulong(x) #else #include -#define NET16(x) __builtin_bswap16(x) -#define NET32(x) __builtin_bswap32(x) #endif #define MIP_ETHEMERAL_PORT 49152 @@ -6122,6 +6118,7 @@ struct mip_if { struct str tx; // Input (RX) buffer bool use_dhcp; // Enable DCHP struct mip_driver *driver; // Low level driver + void *driver_data; // Driver-specific data struct mg_mgr *mgr; // Mongoose event manager // Internal state, user can use it but should not change it @@ -6299,7 +6296,7 @@ static uint32_t csumup(uint32_t sum, const void *buf, size_t len) { static uint16_t csumfin(uint32_t sum) { while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); - return NET16(~sum & 0xffff); + return mg_htons(~sum & 0xffff); } static uint16_t ipcsum(const void *buf, size_t len) { @@ -6343,7 +6340,7 @@ static void arp_cache_add(struct mip_if *ifp, uint32_t ip, uint8_t mac[6]) { memcpy(p + p[0] + 2, &ip, sizeof(ip)); // Replace last entry: IP address memcpy(p + p[0] + 6, mac, 6); // And MAC address p[1] = p[0], p[0] = p[p[1]]; // Point list head to us - MG_DEBUG(("ARP cache: added %#lx @ %x:%x:%x:%x:%x:%x", (long) NET32(ip), + MG_DEBUG(("ARP cache: added %#lx @ %x:%x:%x:%x:%x:%x", (long) mg_htonl(ip), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); } @@ -6352,12 +6349,13 @@ static void arp_ask(struct mip_if *ifp, uint32_t ip) { struct arp *arp = (struct arp *) (eth + 1); memset(eth->dst, 255, sizeof(eth->dst)); memcpy(eth->src, ifp->mac, sizeof(eth->src)); - eth->type = NET16(0x806); + eth->type = mg_htons(0x806); memset(arp, 0, sizeof(*arp)); - arp->fmt = NET16(1), arp->pro = NET16(0x800), arp->hlen = 6, arp->plen = 4; - arp->op = NET16(1), arp->tpa = ip, arp->spa = ifp->ip; + arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6, + arp->plen = 4; + arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip; memcpy(arp->sha, ifp->mac, sizeof(arp->sha)); - ifp->driver->tx(eth, PDIFF(eth, arp + 1), ifp->driver->data); + ifp->driver->tx(eth, PDIFF(eth, arp + 1), ifp->driver_data); } static void onstatechange(struct mip_if *ifp) { @@ -6382,11 +6380,11 @@ static struct ip *tx_ip(struct mip_if *ifp, uint8_t proto, uint32_t ip_src, if (mac) memcpy(eth->dst, mac, sizeof(eth->dst)); // Found? Use it if (!mac) memset(eth->dst, 255, sizeof(eth->dst)); // No? Use broadcast memcpy(eth->src, ifp->mac, sizeof(eth->src)); // TODO(cpq): ARP lookup - eth->type = NET16(0x800); + eth->type = mg_htons(0x800); memset(ip, 0, sizeof(*ip)); ip->ver = 0x45; // Version 4, header length 5 words ip->frag = 0x40; // Don't fragment - ip->len = NET16((uint16_t) (sizeof(*ip) + plen)); + ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen)); ip->ttl = 64; ip->proto = proto; ip->src = ip_src; @@ -6403,7 +6401,7 @@ static void tx_udp(struct mip_if *ifp, uint32_t ip_src, uint16_t sport, // MG_DEBUG(("UDP XX LEN %d %d", (int) len, (int) ifp->tx.len)); udp->sport = sport; udp->dport = dport; - udp->len = NET16((uint16_t) (sizeof(*udp) + len)); + udp->len = mg_htons((uint16_t) (sizeof(*udp) + len)); udp->csum = 0; uint32_t cs = csumup(0, udp, sizeof(*udp)); cs = csumup(cs, buf, len); @@ -6415,7 +6413,7 @@ static void tx_udp(struct mip_if *ifp, uint32_t ip_src, uint16_t sport, // MG_DEBUG(("UDP LEN %d %d\n", (int) len, (int) ifp->frame_len)); ifp->driver->tx(ifp->tx.buf, sizeof(struct eth) + sizeof(*ip) + sizeof(*udp) + len, - ifp->driver->data); + ifp->driver_data); } static void tx_dhcp(struct mip_if *ifp, uint32_t src, uint32_t dst, @@ -6424,11 +6422,11 @@ static void tx_dhcp(struct mip_if *ifp, uint32_t src, uint32_t dst, .htype = 1, .hlen = 6, .ciaddr = src, - .magic = NET32(0x63825363)}; + .magic = mg_htonl(0x63825363)}; memcpy(&dhcp.hwaddr, ifp->mac, sizeof(ifp->mac)); memcpy(&dhcp.xid, ifp->mac + 2, sizeof(dhcp.xid)); memcpy(&dhcp.options, opts, optslen); - tx_udp(ifp, src, NET16(68), dst, NET16(67), &dhcp, sizeof(dhcp)); + tx_udp(ifp, src, mg_htons(68), dst, mg_htons(67), &dhcp, sizeof(dhcp)); } static void tx_dhcp_request(struct mip_if *ifp, uint32_t src, uint32_t dst) { @@ -6455,23 +6453,23 @@ static void tx_dhcp_discover(struct mip_if *ifp) { } static void rx_arp(struct mip_if *ifp, struct pkt *pkt) { - if (pkt->arp->op == NET16(1) && pkt->arp->tpa == ifp->ip) { + if (pkt->arp->op == mg_htons(1) && pkt->arp->tpa == ifp->ip) { // ARP request. Make a response, then send struct eth *eth = (struct eth *) ifp->tx.buf; struct arp *arp = (struct arp *) (eth + 1); - MG_DEBUG(("ARP op %d %#x %#x", NET16(arp->op), arp->spa, arp->tpa)); + MG_DEBUG(("ARP op %d %#x %#x", mg_htons(arp->op), arp->spa, arp->tpa)); memcpy(eth->dst, pkt->eth->src, sizeof(eth->dst)); memcpy(eth->src, ifp->mac, sizeof(eth->src)); - eth->type = NET16(0x806); + eth->type = mg_htons(0x806); *arp = *pkt->arp; - arp->op = NET16(2); + arp->op = mg_htons(2); memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha)); memcpy(arp->sha, ifp->mac, sizeof(pkt->arp->sha)); arp->tpa = pkt->arp->spa; arp->spa = ifp->ip; - MG_DEBUG(("ARP response: we're %#lx", (long) ifp->ip)); - ifp->driver->tx(ifp->tx.buf, PDIFF(eth, arp + 1), ifp->driver->data); - } else if (pkt->arp->op == NET16(2)) { + MG_DEBUG(("ARP response: we're %#lx", (long) mg_ntohl(ifp->ip))); + ifp->driver->tx(ifp->tx.buf, PDIFF(eth, arp + 1), ifp->driver_data); + } else if (pkt->arp->op == mg_htons(2)) { if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return; // MG_INFO(("ARP RESPONSE")); arp_cache_add(ifp, pkt->arp->spa, pkt->arp->sha); @@ -6488,7 +6486,7 @@ static void rx_icmp(struct mip_if *ifp, struct pkt *pkt) { memcpy(icmp + 1, pkt->pay.buf, pkt->pay.len); icmp->csum = ipcsum(icmp, sizeof(*icmp) + pkt->pay.len); ifp->driver->tx(ifp->tx.buf, PDIFF(ifp->tx.buf, icmp + 1) + pkt->pay.len, - ifp->driver->data); + ifp->driver_data); } } @@ -6580,7 +6578,7 @@ static size_t tx_tcp(struct mip_if *ifp, uint32_t dst_ip, uint8_t flags, cs = csumup(cs, pseudo, sizeof(pseudo)); tcp->csum = csumfin(cs); return ifp->driver->tx(ifp->tx.buf, PDIFF(ifp->tx.buf, tcp + 1) + len, - ifp->driver->data); + ifp->driver_data); } static size_t tx_tcp_pkt(struct mip_if *ifp, struct pkt *pkt, uint8_t flags, @@ -6682,10 +6680,10 @@ static void rx_ip(struct mip_if *ifp, struct pkt *pkt) { } else if (pkt->ip->proto == 17) { pkt->udp = (struct udp *) (pkt->ip + 1); if (pkt->pay.len < sizeof(*pkt->udp)) return; - // MG_DEBUG((" UDP %u %u -> %u\n", len, NET16(udp->sport), - // NET16(udp->dport))); + // MG_DEBUG((" UDP %u %u -> %u\n", len, mg_htons(udp->sport), + // mg_htons(udp->dport))); mkpay(pkt, pkt->udp + 1); - if (pkt->udp->dport == NET16(68)) { + if (pkt->udp->dport == mg_htons(68)) { pkt->dhcp = (struct dhcp *) (pkt->udp + 1); mkpay(pkt, pkt->dhcp + 1); rx_dhcp(ifp, pkt); @@ -6713,8 +6711,8 @@ static void rx_ip6(struct mip_if *ifp, struct pkt *pkt) { } else if (pkt->ip->proto == 17) { pkt->udp = (struct udp *) (pkt->ip6 + 1); if (pkt->pay.len < sizeof(*pkt->udp)) return; - // MG_DEBUG((" UDP %u %u -> %u\n", len, NET16(udp->sport), - // NET16(udp->dport))); + // MG_DEBUG((" UDP %u %u -> %u\n", len, mg_htons(udp->sport), + // mg_htons(udp->dport))); mkpay(pkt, pkt->udp + 1); } } @@ -6727,24 +6725,24 @@ static void mip_rx(struct mip_if *ifp, void *buf, size_t len) { if (memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 && memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0) { // Not for us. Drop silently - } else if (pkt.eth->type == NET16(0x806)) { + } else if (pkt.eth->type == mg_htons(0x806)) { pkt.arp = (struct arp *) (pkt.eth + 1); if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated rx_arp(ifp, &pkt); - } else if (pkt.eth->type == NET16(0x86dd)) { + } else if (pkt.eth->type == mg_htons(0x86dd)) { pkt.ip6 = (struct ip6 *) (pkt.eth + 1); if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip6)) return; // Truncated if ((pkt.ip6->ver >> 4) != 0x6) return; // Not IP mkpay(&pkt, pkt.ip6 + 1); rx_ip6(ifp, &pkt); - } else if (pkt.eth->type == NET16(0x800)) { + } else if (pkt.eth->type == mg_htons(0x800)) { pkt.ip = (struct ip *) (pkt.eth + 1); if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return; // Truncated if ((pkt.ip->ver >> 4) != 4) return; // Not IP mkpay(&pkt, pkt.ip + 1); rx_ip(ifp, &pkt); } else { - MG_DEBUG((" Unknown eth type %x\n", NET16(pkt.eth->type))); + MG_DEBUG((" Unknown eth type %x\n", mg_htons(pkt.eth->type))); } } @@ -6763,7 +6761,7 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) { // Handle physical interface up/down status if (ifp->driver->status) { - bool up = ifp->driver->status(ifp->driver->data); + bool up = ifp->driver->status(ifp->driver_data); bool current = ifp->state != MIP_STATE_DOWN; if (up != current) { ifp->state = up == false ? MIP_STATE_DOWN @@ -6778,7 +6776,7 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) { for (;;) { size_t len = ifp->queue.len > 0 ? q_read(&ifp->queue, ifp->rx.buf) : ifp->driver->rx(ifp->rx.buf, ifp->rx.len, - ifp->driver->data); + ifp->driver_data); if (len == 0) break; mip_rx(ifp, ifp->rx.buf, len); } @@ -6793,7 +6791,7 @@ static void on_rx(void *buf, size_t len, void *userdata) { } void mip_init(struct mg_mgr *mgr, struct mip_ipcfg *ipcfg, - struct mip_driver *driver) { + struct mip_driver *driver, void *driver_data) { size_t maxpktsize = 1500, qlen = driver->rxcb ? 1024 * 16 : 0; struct mip_if *ifp = (struct mip_if *) calloc(1, sizeof(*ifp) + 2 * maxpktsize + qlen); @@ -6803,10 +6801,11 @@ void mip_init(struct mg_mgr *mgr, struct mip_ipcfg *ipcfg, ifp->rx.buf = (uint8_t *) (ifp + 1), ifp->rx.len = maxpktsize; ifp->tx.buf = ifp->rx.buf + maxpktsize, ifp->tx.len = maxpktsize; ifp->driver = driver; + ifp->driver_data = driver_data; ifp->mgr = mgr; ifp->queue.buf = ifp->tx.buf + maxpktsize; ifp->queue.len = qlen; - if (driver->init) driver->init(driver->data); + if (driver->init) driver->init(ipcfg->mac, driver_data); if (driver->rxcb) driver->rxcb(on_rx, ifp); mgr->priv = ifp; mgr->extraconnsize = sizeof(struct tcpstate); diff --git a/mongoose.h b/mongoose.h index a86d9128..3d98f88c 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1423,8 +1423,7 @@ void mg_rpc_list(struct mg_rpc_req *r); struct mip_driver { - void *data; // Driver-specific data - void (*init)(void *data); // Initialise driver + void (*init)(uint8_t *mac, void *data); // Initialise driver size_t (*tx)(const void *, size_t, void *data); // Transmit frame size_t (*rx)(void *buf, size_t len, void *data); // Receive frame (polling) bool (*status)(void *data); // Up/down status @@ -1437,7 +1436,7 @@ struct mip_ipcfg { uint32_t ip, mask, gw; // IP, netmask, GW. If IP is 0, DHCP is used }; -void mip_init(struct mg_mgr *, struct mip_ipcfg *, struct mip_driver *); +void mip_init(struct mg_mgr *, struct mip_ipcfg *, struct mip_driver *, void *); extern struct mip_driver mip_driver_stm32;