Merge pull request #2096 from cesanta/fixrmii

Update RMII example, enhance MIP
This commit is contained in:
Sergey Lyubka 2023-02-28 08:34:20 +00:00 committed by GitHub
commit da028d1af9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 73 additions and 90 deletions

View File

@ -216,21 +216,6 @@ static inline void smi_rd_init(PIO pio, uint sm, uint addr, uint gpio) {
pio_sm_init(pio, sm, addr, &c); pio_sm_init(pio, sm, addr, &c);
} }
static inline uint32_t crc_calc(const uint8_t *data, int length) {
static const uint32_t crclut[16] = {
// table for polynomial 0xEDB88320 (reflected)
0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
uint32_t crc = 0xFFFFFFFF;
while (--length >= 0) {
uint8_t byte = *data++;
crc = crclut[(crc ^ byte) & 0x0F] ^ (crc >> 4);
crc = crclut[(crc ^ (byte >> 4)) & 0x0F] ^ (crc >> 4);
}
return ~crc;
}
static void eth_write_phy(int addr, int reg, int val, uint8_t gpio) { static void eth_write_phy(int addr, int reg, int val, uint8_t gpio) {
uint16_t op = 0x5002 | (addr << 7) | (reg << 2); // b0101aaaaarrrrr10 uint16_t op = 0x5002 | (addr << 7) | (reg << 2); // b0101aaaaarrrrr10
smi_wr_init(pio0, SMITXSM, smi_wr_addr, gpio); smi_wr_init(pio0, SMITXSM, smi_wr_addr, gpio);
@ -304,7 +289,7 @@ static size_t mg_tcpip_driver_rp2040_rmii_tx(const void *buf, size_t len,
memset(s_txbuf, 0, 60); // pre-pad memset(s_txbuf, 0, 60); // pre-pad
memcpy(s_txbuf, buf, len); memcpy(s_txbuf, buf, len);
if (len < 60) len = 60; // pad if (len < 60) len = 60; // pad
uint32_t crc = crc_calc(s_txbuf, len); // host is little-endian uint32_t crc = mg_crc32(0, s_txbuf, len); // host is little-endian
memcpy(s_txbuf + len, (uint8_t *) &crc, 4); memcpy(s_txbuf + len, (uint8_t *) &crc, 4);
len += 4; len += 4;
sleep_us(10); // enforce IFG in case software has been lightning fast... sleep_us(10); // enforce IFG in case software has been lightning fast...
@ -328,27 +313,13 @@ static void rx_irq(void) {
pio_interrupt_clear(pio0, pio_interrupt_clear(pio0,
0); // ACK PIO IRQ so the state machine resumes receiving 0); // ACK PIO IRQ so the state machine resumes receiving
// NOTE(scaprile) Here we could check addressing to avoid queuing frames not // NOTE(scaprile) Here we could check addressing to avoid queuing frames not
// for us, or we can defer that for later as we do with CRC The max amount of // for us. The max amount of time we can linger here is what it takes for the
// time we can linger here is what it takes for the other buffer to fill // other buffer to fill (<8us) and that includes irq chaining
// (<8us) and that includes irq chaining
if (len >= 64 && len <= ETH_PKT_SIZE) if (len >= 64 && len <= ETH_PKT_SIZE)
mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
s_rxno = rxno; s_rxno = rxno;
} }
static size_t mg_tcpip_driver_rp2040_rmii_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
size_t len = 0; // mg_tcpip_qread(buf, ifp);
if (len == 0) return 0;
len -= 4; // exclude CRC from frame length
uint32_t crc = crc_calc(buf, len); // calculate CRC and compare
// NOTE(scaprile) Here we could check addressing to avoid delivering frames
// not for us, though MIP already does that (now ?)
if (memcmp(&((uint8_t *) buf)[len], &crc,
sizeof(crc))) // host is little-endian
return 0;
return len;
}
static bool mg_tcpip_driver_rp2040_rmii_up(struct mg_tcpip_if *ifp) { static bool mg_tcpip_driver_rp2040_rmii_up(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_rp2040_rmii_data *d = struct mg_tcpip_driver_rp2040_rmii_data *d =
(struct mg_tcpip_driver_rp2040_rmii_data *) ifp->driver_data; (struct mg_tcpip_driver_rp2040_rmii_data *) ifp->driver_data;
@ -360,6 +331,6 @@ static bool mg_tcpip_driver_rp2040_rmii_up(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver mg_tcpip_driver_rp2040_rmii = { struct mg_tcpip_driver mg_tcpip_driver_rp2040_rmii = {
mg_tcpip_driver_rp2040_rmii_init, mg_tcpip_driver_rp2040_rmii_init,
mg_tcpip_driver_rp2040_rmii_tx, mg_tcpip_driver_rp2040_rmii_tx,
mg_tcpip_driver_rp2040_rmii_rx, NULL,
mg_tcpip_driver_rp2040_rmii_up, mg_tcpip_driver_rp2040_rmii_up,
}; };

View File

@ -42,6 +42,8 @@ int main(void) {
struct mg_tcpip_if mif = { struct mg_tcpip_if mif = {
.mac = {2, 0, 1, 2, 3, 5}, .mac = {2, 0, 1, 2, 3, 5},
.ip = 0, .ip = 0,
.enable_mac_check = true,
.enable_crc32_check = true,
.driver = &mg_tcpip_driver_rp2040_rmii, .driver = &mg_tcpip_driver_rp2040_rmii,
.driver_data = &driver_data, .driver_data = &driver_data,
}; };

View File

@ -5672,11 +5672,16 @@ uint16_t mg_ntohs(uint16_t net) {
} }
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) { uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
int i; static const uint32_t crclut[16] = {
// table for polynomial 0xEDB88320 (reflected)
0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
crc = ~crc; crc = ~crc;
while (len--) { while (len--) {
crc ^= *(unsigned char *) buf++; uint8_t byte = *(uint8_t *)buf++;
for (i = 0; i < 8; i++) crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1; crc = crclut[(crc ^ byte) & 0x0F] ^ (crc >> 4);
crc = crclut[(crc ^ (byte >> 4)) & 0x0F] ^ (crc >> 4);
} }
return ~crc; return ~crc;
} }
@ -5755,7 +5760,6 @@ uint64_t mg_millis(void) {
} }
#endif #endif
#ifdef MG_ENABLE_LINES #ifdef MG_ENABLE_LINES
#line 1 "src/ws.c" #line 1 "src/ws.c"
#endif #endif
@ -7867,10 +7871,16 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
pkt.raw.len = len; pkt.raw.len = len;
pkt.eth = (struct eth *) buf; pkt.eth = (struct eth *) buf;
if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt? if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt?
if (memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 && if (ifp->enable_mac_check &&
memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0) { memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&
// Not for us. Drop silently memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
} else if (pkt.eth->type == mg_htons(0x806)) { return;
if (ifp->enable_crc32_check && len > 4) {
len -= 4; // TODO(scaprile): check on bigendian
uint32_t crc = mg_crc32(0, (const char *) buf, len);
if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
}
if (pkt.eth->type == mg_htons(0x806)) {
pkt.arp = (struct arp *) (pkt.eth + 1); pkt.arp = (struct arp *) (pkt.eth + 1);
if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated
rx_arp(ifp, &pkt); rx_arp(ifp, &pkt);
@ -7971,11 +7981,6 @@ void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp) {
} }
} }
size_t mg_tcpip_driver_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
(void) buf, (void) len, (void) ifp;
return 0;
}
void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
// If MAC address is not set, make a random one // If MAC address is not set, make a random one
if (ifp->mac[0] == 0 && ifp->mac[1] == 0 && ifp->mac[2] == 0 && if (ifp->mac[0] == 0 && ifp->mac[1] == 0 && ifp->mac[2] == 0 &&
@ -7990,6 +7995,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
} else { } else {
size_t framesize = 1540; size_t framesize = 1540;
ifp->tx.ptr = (char *) calloc(1, framesize), ifp->tx.len = framesize; ifp->tx.ptr = (char *) calloc(1, framesize), ifp->tx.len = framesize;
if (ifp->recv_queue.size == 0)
ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192; ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192;
ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size); ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size);
ifp->timer_1000ms = mg_millis(); ifp->timer_1000ms = mg_millis();

View File

@ -1519,6 +1519,8 @@ struct mg_tcpip_if {
struct mg_str tx; // Output (TX) buffer struct mg_str tx; // Output (TX) buffer
bool enable_dhcp_client; // Enable DCHP client bool enable_dhcp_client; // Enable DCHP client
bool enable_dhcp_server; // Enable DCHP server bool enable_dhcp_server; // Enable DCHP server
bool enable_crc32_check; // Do a CRC check on rx frames and strip it
bool enable_mac_check; // Do a MAC check on rx frames
struct mg_tcpip_driver *driver; // Low level driver struct mg_tcpip_driver *driver; // Low level driver
void *driver_data; // Driver-specific data void *driver_data; // Driver-specific data
struct mg_mgr *mgr; // Mongoose event manager struct mg_mgr *mgr; // Mongoose event manager
@ -1543,9 +1545,6 @@ struct mg_tcpip_if {
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *); void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
void mg_tcpip_free(struct mg_tcpip_if *); void mg_tcpip_free(struct mg_tcpip_if *);
void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp); void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
size_t mg_tcpip_qread(void *buf, struct mg_tcpip_if *ifp);
// conveniency rx function for IRQ-driven drivers
size_t mg_tcpip_driver_rx(void *buf, size_t len, struct mg_tcpip_if *ifp);
extern struct mg_tcpip_driver mg_tcpip_driver_stm32; extern struct mg_tcpip_driver mg_tcpip_driver_stm32;
extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_w5500;

View File

@ -693,10 +693,16 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
pkt.raw.len = len; pkt.raw.len = len;
pkt.eth = (struct eth *) buf; pkt.eth = (struct eth *) buf;
if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt? if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt?
if (memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 && if (ifp->enable_mac_check &&
memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0) { memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&
// Not for us. Drop silently memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
} else if (pkt.eth->type == mg_htons(0x806)) { return;
if (ifp->enable_crc32_check && len > 4) {
len -= 4; // TODO(scaprile): check on bigendian
uint32_t crc = mg_crc32(0, (const char *) buf, len);
if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
}
if (pkt.eth->type == mg_htons(0x806)) {
pkt.arp = (struct arp *) (pkt.eth + 1); pkt.arp = (struct arp *) (pkt.eth + 1);
if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated
rx_arp(ifp, &pkt); rx_arp(ifp, &pkt);
@ -797,11 +803,6 @@ void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp) {
} }
} }
size_t mg_tcpip_driver_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
(void) buf, (void) len, (void) ifp;
return 0;
}
void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
// If MAC address is not set, make a random one // If MAC address is not set, make a random one
if (ifp->mac[0] == 0 && ifp->mac[1] == 0 && ifp->mac[2] == 0 && if (ifp->mac[0] == 0 && ifp->mac[1] == 0 && ifp->mac[2] == 0 &&
@ -816,6 +817,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
} else { } else {
size_t framesize = 1540; size_t framesize = 1540;
ifp->tx.ptr = (char *) calloc(1, framesize), ifp->tx.len = framesize; ifp->tx.ptr = (char *) calloc(1, framesize), ifp->tx.len = framesize;
if (ifp->recv_queue.size == 0)
ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192; ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192;
ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size); ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size);
ifp->timer_1000ms = mg_millis(); ifp->timer_1000ms = mg_millis();

View File

@ -20,6 +20,8 @@ struct mg_tcpip_if {
struct mg_str tx; // Output (TX) buffer struct mg_str tx; // Output (TX) buffer
bool enable_dhcp_client; // Enable DCHP client bool enable_dhcp_client; // Enable DCHP client
bool enable_dhcp_server; // Enable DCHP server bool enable_dhcp_server; // Enable DCHP server
bool enable_crc32_check; // Do a CRC check on rx frames and strip it
bool enable_mac_check; // Do a MAC check on rx frames
struct mg_tcpip_driver *driver; // Low level driver struct mg_tcpip_driver *driver; // Low level driver
void *driver_data; // Driver-specific data void *driver_data; // Driver-specific data
struct mg_mgr *mgr; // Mongoose event manager struct mg_mgr *mgr; // Mongoose event manager
@ -44,9 +46,6 @@ struct mg_tcpip_if {
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *); void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
void mg_tcpip_free(struct mg_tcpip_if *); void mg_tcpip_free(struct mg_tcpip_if *);
void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp); void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
size_t mg_tcpip_qread(void *buf, struct mg_tcpip_if *ifp);
// conveniency rx function for IRQ-driven drivers
size_t mg_tcpip_driver_rx(void *buf, size_t len, struct mg_tcpip_if *ifp);
extern struct mg_tcpip_driver mg_tcpip_driver_stm32; extern struct mg_tcpip_driver mg_tcpip_driver_stm32;
extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
@ -64,8 +63,8 @@ struct mg_tcpip_spi {
#if MG_ENABLE_TCPIP #if MG_ENABLE_TCPIP
#if !defined(MG_ENABLE_DRIVER_STM32H) && !defined(MG_ENABLE_DRIVER_TM4C) #if !defined(MG_ENABLE_DRIVER_STM32H) && !defined(MG_ENABLE_DRIVER_TM4C)
#define MG_ENABLE_DRIVER_STM32 1 #define MG_ENABLE_DRIVER_STM32 1
#else #else
#define MG_ENABLE_DRIVER_STM32 0 #define MG_ENABLE_DRIVER_STM32 0
#endif #endif
#endif #endif

View File

@ -48,11 +48,16 @@ uint16_t mg_ntohs(uint16_t net) {
} }
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) { uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
int i; static const uint32_t crclut[16] = {
// table for polynomial 0xEDB88320 (reflected)
0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
crc = ~crc; crc = ~crc;
while (len--) { while (len--) {
crc ^= *(unsigned char *) buf++; uint8_t byte = *(uint8_t *)buf++;
for (i = 0; i < 8; i++) crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1; crc = crclut[(crc ^ byte) & 0x0F] ^ (crc >> 4);
crc = crclut[(crc ^ (byte >> 4)) & 0x0F] ^ (crc >> 4);
} }
return ~crc; return ~crc;
} }
@ -130,4 +135,3 @@ uint64_t mg_millis(void) {
#endif #endif
} }
#endif #endif