mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-26 22:41:03 +08:00
MIP refactor: use mg_hton*, move driver_data to ifp, parametrise f746 PLL setup
This commit is contained in:
parent
229b492ccc
commit
dcdeffff9a
@ -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]));
|
||||
}
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 *),
|
||||
|
75
mip/mip.c
75
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 <stdatomic.h>
|
||||
#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);
|
||||
|
@ -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;
|
||||
|
83
mongoose.c
83
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 <stdatomic.h>
|
||||
#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);
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user