mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-04 18:29:01 +08:00
Merge pull request #1726 from cesanta/qp
Add MAC addr filtering to stm32 driver. Record free space in q profiler
This commit is contained in:
commit
7e875ba89d
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2022 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
// https://www.st.com/resource/en/reference_manual/dm00124865-stm32f75xxx-and-stm32f74xxx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
|
||||
// https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -97,8 +97,11 @@ static bool mip_driver_stm32_init(uint8_t *mac, void *userdata) {
|
||||
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;
|
||||
// MAC address filtering
|
||||
ETH->MACA0HR = ((uint32_t) mac[5] << 8U) | mac[4];
|
||||
ETH->MACA0LR = (uint32_t) (mac[3] << 24) | ((uint32_t) mac[2] << 16) |
|
||||
((uint32_t) mac[1] << 8) | mac[0];
|
||||
(void) userdata;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -139,9 +142,7 @@ static bool mip_driver_stm32_up(void *userdata) {
|
||||
|
||||
void ETH_IRQHandler(void);
|
||||
void ETH_IRQHandler(void) {
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_mark(QP_IRQTRIGGERED, 0);
|
||||
#endif
|
||||
volatile uint32_t sr = ETH->DMASR;
|
||||
if (sr & BIT(6)) { // Frame received, loop
|
||||
for (uint32_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||
|
62
mip/mip.c
62
mip/mip.c
@ -64,7 +64,8 @@ struct mip_if {
|
||||
uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
|
||||
uint8_t arp_cache[MIP_ARP_CS]; // Each entry is 12 bytes
|
||||
uint16_t eport; // Next ephemeral port
|
||||
int state; // Current state
|
||||
uint16_t dropped; // Number of dropped frames
|
||||
uint8_t state; // Current state
|
||||
#define MIP_STATE_DOWN 0 // Interface is down
|
||||
#define MIP_STATE_UP 1 // Interface is up
|
||||
#define MIP_STATE_READY 2 // Interface is up and has IP
|
||||
@ -202,7 +203,11 @@ static bool q_write(struct queue *q, const void *buf, size_t len) {
|
||||
return success;
|
||||
}
|
||||
|
||||
static size_t q_avail(struct queue *q) {
|
||||
static inline size_t q_space(struct queue *q) {
|
||||
return q->tail > q->head ? q->tail - q->head : q->tail + (q->len - q->head);
|
||||
}
|
||||
|
||||
static inline size_t q_avail(struct queue *q) {
|
||||
size_t n = 0;
|
||||
if (q->tail != q->head) q_copyout(q, (uint8_t *) &n, sizeof(n), q->tail);
|
||||
return n;
|
||||
@ -788,13 +793,9 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) {
|
||||
: ifp->driver->rx(ifp->rx.buf, ifp->rx.len,
|
||||
ifp->driver_data);
|
||||
if (len == 0) break;
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_mark(QP_FRAMEPOPPED, (int) len);
|
||||
#endif
|
||||
qp_mark(QP_FRAMEPOPPED, (int) q_space(&ifp->queue));
|
||||
mip_rx(ifp, ifp->rx.buf, len);
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_mark(QP_FRAMEDONE, (int) len);
|
||||
#endif
|
||||
qp_mark(QP_FRAMEDONE, (int) q_space(&ifp->queue));
|
||||
}
|
||||
|
||||
// Process timeouts
|
||||
@ -825,12 +826,13 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) {
|
||||
// our lock-free queue with preallocated buffer to copy data and return asap
|
||||
static void on_rx(void *buf, size_t len, void *userdata) {
|
||||
struct mip_if *ifp = (struct mip_if *) userdata;
|
||||
#ifndef MIP_QPROFILE
|
||||
if (!q_write(&ifp->queue, buf, len)) MG_ERROR(("dropped %d", (int) len));
|
||||
#else
|
||||
qp_mark(q_write(&ifp->queue, buf, len) ? QP_FRAMEPUSHED : QP_FRAMEDROPPED,
|
||||
(int) len);
|
||||
#endif
|
||||
if (q_write(&ifp->queue, buf, len)) {
|
||||
qp_mark(QP_FRAMEPUSHED, (int) q_space(&ifp->queue));
|
||||
} else {
|
||||
ifp->dropped++;
|
||||
qp_mark(QP_FRAMEDROPPED, ifp->dropped);
|
||||
MG_ERROR(("dropped %d", (int) len));
|
||||
}
|
||||
}
|
||||
|
||||
void mip_init(struct mg_mgr *mgr, struct mip_cfg *ipcfg,
|
||||
@ -958,7 +960,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct qpentry {
|
||||
uint64_t timestamp;
|
||||
uint32_t timestamp;
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
};
|
||||
@ -970,14 +972,11 @@ static struct queue qp;
|
||||
// TODO(scaprile): avoid concurrency issues (2 queues ?)
|
||||
void qp_mark(unsigned int type, int len) {
|
||||
static bool ovf = false;
|
||||
static uint16_t drop_ctr = 0, irq_ctr = 0;
|
||||
struct qpentry e = {
|
||||
.timestamp = mg_millis(), .type = (uint16_t) type, .len = (uint16_t) len};
|
||||
|
||||
if (type == QP_IRQTRIGGERED)
|
||||
e.len = ++irq_ctr; // only incremented on IRQ calls
|
||||
else if (type == QP_FRAMEDROPPED)
|
||||
++drop_ctr; // only incremented on IRQ calls
|
||||
static uint16_t irq_ctr = 0, drop_ctr = 0;
|
||||
struct qpentry e = {.timestamp = (uint32_t) mg_millis(),
|
||||
.type = (uint16_t) type,
|
||||
.len = (uint16_t) len};
|
||||
if (type == QP_IRQTRIGGERED) e.len = ++irq_ctr;
|
||||
if (ovf) {
|
||||
e.type = (uint16_t) QP_QUEUEOVF;
|
||||
e.len = drop_ctr;
|
||||
@ -987,20 +986,15 @@ void qp_mark(unsigned int type, int len) {
|
||||
|
||||
void qp_log(void) {
|
||||
struct qpentry e;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
if (q_read(&qp, &e))
|
||||
MG_INFO(("%llu, %u, %u", e.timestamp, e.type, e.len));
|
||||
else
|
||||
break;
|
||||
const char *titles[] = {"IRQ ", "PUSH", "POP ", "DONE", "DROP", "OVFL"};
|
||||
for (int i = 0; i < 10 && q_read(&qp, &e); i++) {
|
||||
MG_INFO(("%lx %s %u", e.timestamp, titles[e.type], e.len));
|
||||
}
|
||||
}
|
||||
|
||||
void qp_init(void) {
|
||||
unsigned int qlen = 500 * (sizeof(size_t) + sizeof(struct qpentry));
|
||||
|
||||
qp.buf = calloc(1, qlen);
|
||||
qp.len = qlen;
|
||||
// THERE IS NO FREE
|
||||
qp.len = 500 * (sizeof(size_t) + sizeof(struct qpentry));
|
||||
qp.buf = calloc(1, qp.len); // THERE IS NO FREE
|
||||
}
|
||||
#endif // MIP_QPROFILE
|
||||
|
||||
|
15
mip/mip.h
15
mip/mip.h
@ -32,17 +32,18 @@ struct mip_spi {
|
||||
};
|
||||
|
||||
#ifdef MIP_QPROFILE
|
||||
enum { // payload is frame length unless otherwise noted
|
||||
enum {
|
||||
QP_IRQTRIGGERED = 0, // payload is number of interrupts so far
|
||||
QP_FRAMEPUSHED,
|
||||
QP_FRAMEPOPPED,
|
||||
QP_FRAMEDONE,
|
||||
QP_FRAMEDROPPED,
|
||||
QP_QUEUEOVF // profiling queue is full, payload is number of frame drops so
|
||||
// far
|
||||
QP_FRAMEPUSHED, // available space in the frame queue
|
||||
QP_FRAMEPOPPED, // available space in the frame queue
|
||||
QP_FRAMEDONE, // available space in the frame queue
|
||||
QP_FRAMEDROPPED, // number of dropped frames
|
||||
QP_QUEUEOVF // profiling queue is full, payload is number of frame drops
|
||||
};
|
||||
|
||||
void qp_mark(unsigned int type, int len);
|
||||
void qp_log(void); // timestamp, type, payload
|
||||
void qp_init(void);
|
||||
#else
|
||||
#define qp_mark(a, b)
|
||||
#endif
|
||||
|
71
mongoose.c
71
mongoose.c
@ -6079,8 +6079,11 @@ static bool mip_driver_stm32_init(uint8_t *mac, void *userdata) {
|
||||
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;
|
||||
// MAC address filtering
|
||||
ETH->MACA0HR = ((uint32_t) mac[5] << 8U) | mac[4];
|
||||
ETH->MACA0LR = (uint32_t) (mac[3] << 24) | ((uint32_t) mac[2] << 16) |
|
||||
((uint32_t) mac[1] << 8) | mac[0];
|
||||
(void) userdata;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6121,9 +6124,7 @@ static bool mip_driver_stm32_up(void *userdata) {
|
||||
|
||||
void ETH_IRQHandler(void);
|
||||
void ETH_IRQHandler(void) {
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_mark(QP_IRQTRIGGERED, 0);
|
||||
#endif
|
||||
volatile uint32_t sr = ETH->DMASR;
|
||||
if (sr & BIT(6)) { // Frame received, loop
|
||||
for (uint32_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||
@ -6365,7 +6366,8 @@ struct mip_if {
|
||||
uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
|
||||
uint8_t arp_cache[MIP_ARP_CS]; // Each entry is 12 bytes
|
||||
uint16_t eport; // Next ephemeral port
|
||||
int state; // Current state
|
||||
uint16_t dropped; // Number of dropped frames
|
||||
uint8_t state; // Current state
|
||||
#define MIP_STATE_DOWN 0 // Interface is down
|
||||
#define MIP_STATE_UP 1 // Interface is up
|
||||
#define MIP_STATE_READY 2 // Interface is up and has IP
|
||||
@ -6503,7 +6505,11 @@ static bool q_write(struct queue *q, const void *buf, size_t len) {
|
||||
return success;
|
||||
}
|
||||
|
||||
static size_t q_avail(struct queue *q) {
|
||||
static inline size_t q_space(struct queue *q) {
|
||||
return q->tail > q->head ? q->tail - q->head : q->tail + (q->len - q->head);
|
||||
}
|
||||
|
||||
static inline size_t q_avail(struct queue *q) {
|
||||
size_t n = 0;
|
||||
if (q->tail != q->head) q_copyout(q, (uint8_t *) &n, sizeof(n), q->tail);
|
||||
return n;
|
||||
@ -7089,13 +7095,9 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) {
|
||||
: ifp->driver->rx(ifp->rx.buf, ifp->rx.len,
|
||||
ifp->driver_data);
|
||||
if (len == 0) break;
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_mark(QP_FRAMEPOPPED, (int) len);
|
||||
#endif
|
||||
qp_mark(QP_FRAMEPOPPED, (int) q_space(&ifp->queue));
|
||||
mip_rx(ifp, ifp->rx.buf, len);
|
||||
#ifdef MIP_QPROFILE
|
||||
qp_mark(QP_FRAMEDONE, (int) len);
|
||||
#endif
|
||||
qp_mark(QP_FRAMEDONE, (int) q_space(&ifp->queue));
|
||||
}
|
||||
|
||||
// Process timeouts
|
||||
@ -7126,12 +7128,13 @@ static void mip_poll(struct mip_if *ifp, uint64_t uptime_ms) {
|
||||
// our lock-free queue with preallocated buffer to copy data and return asap
|
||||
static void on_rx(void *buf, size_t len, void *userdata) {
|
||||
struct mip_if *ifp = (struct mip_if *) userdata;
|
||||
#ifndef MIP_QPROFILE
|
||||
if (!q_write(&ifp->queue, buf, len)) MG_ERROR(("dropped %d", (int) len));
|
||||
#else
|
||||
qp_mark(q_write(&ifp->queue, buf, len) ? QP_FRAMEPUSHED : QP_FRAMEDROPPED,
|
||||
(int) len);
|
||||
#endif
|
||||
if (q_write(&ifp->queue, buf, len)) {
|
||||
qp_mark(QP_FRAMEPUSHED, (int) q_space(&ifp->queue));
|
||||
} else {
|
||||
ifp->dropped++;
|
||||
qp_mark(QP_FRAMEDROPPED, ifp->dropped);
|
||||
MG_ERROR(("dropped %d", (int) len));
|
||||
}
|
||||
}
|
||||
|
||||
void mip_init(struct mg_mgr *mgr, struct mip_cfg *ipcfg,
|
||||
@ -7259,7 +7262,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct qpentry {
|
||||
uint64_t timestamp;
|
||||
uint32_t timestamp;
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
};
|
||||
@ -7271,14 +7274,11 @@ static struct queue qp;
|
||||
// TODO(scaprile): avoid concurrency issues (2 queues ?)
|
||||
void qp_mark(unsigned int type, int len) {
|
||||
static bool ovf = false;
|
||||
static uint16_t drop_ctr = 0, irq_ctr = 0;
|
||||
struct qpentry e = {
|
||||
.timestamp = mg_millis(), .type = (uint16_t) type, .len = (uint16_t) len};
|
||||
|
||||
if (type == QP_IRQTRIGGERED)
|
||||
e.len = ++irq_ctr; // only incremented on IRQ calls
|
||||
else if (type == QP_FRAMEDROPPED)
|
||||
++drop_ctr; // only incremented on IRQ calls
|
||||
static uint16_t irq_ctr = 0, drop_ctr = 0;
|
||||
struct qpentry e = {.timestamp = (uint32_t) mg_millis(),
|
||||
.type = (uint16_t) type,
|
||||
.len = (uint16_t) len};
|
||||
if (type == QP_IRQTRIGGERED) e.len = ++irq_ctr;
|
||||
if (ovf) {
|
||||
e.type = (uint16_t) QP_QUEUEOVF;
|
||||
e.len = drop_ctr;
|
||||
@ -7288,20 +7288,15 @@ void qp_mark(unsigned int type, int len) {
|
||||
|
||||
void qp_log(void) {
|
||||
struct qpentry e;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
if (q_read(&qp, &e))
|
||||
MG_INFO(("%llu, %u, %u", e.timestamp, e.type, e.len));
|
||||
else
|
||||
break;
|
||||
const char *titles[] = {"IRQ ", "PUSH", "POP ", "DONE", "DROP", "OVFL"};
|
||||
for (int i = 0; i < 10 && q_read(&qp, &e); i++) {
|
||||
MG_INFO(("%lx %s %u", e.timestamp, titles[e.type], e.len));
|
||||
}
|
||||
}
|
||||
|
||||
void qp_init(void) {
|
||||
unsigned int qlen = 500 * (sizeof(size_t) + sizeof(struct qpentry));
|
||||
|
||||
qp.buf = calloc(1, qlen);
|
||||
qp.len = qlen;
|
||||
// THERE IS NO FREE
|
||||
qp.len = 500 * (sizeof(size_t) + sizeof(struct qpentry));
|
||||
qp.buf = calloc(1, qp.len); // THERE IS NO FREE
|
||||
}
|
||||
#endif // MIP_QPROFILE
|
||||
|
||||
|
15
mongoose.h
15
mongoose.h
@ -1456,19 +1456,20 @@ struct mip_spi {
|
||||
};
|
||||
|
||||
#ifdef MIP_QPROFILE
|
||||
enum { // payload is frame length unless otherwise noted
|
||||
enum {
|
||||
QP_IRQTRIGGERED = 0, // payload is number of interrupts so far
|
||||
QP_FRAMEPUSHED,
|
||||
QP_FRAMEPOPPED,
|
||||
QP_FRAMEDONE,
|
||||
QP_FRAMEDROPPED,
|
||||
QP_QUEUEOVF // profiling queue is full, payload is number of frame drops so
|
||||
// far
|
||||
QP_FRAMEPUSHED, // available space in the frame queue
|
||||
QP_FRAMEPOPPED, // available space in the frame queue
|
||||
QP_FRAMEDONE, // available space in the frame queue
|
||||
QP_FRAMEDROPPED, // number of dropped frames
|
||||
QP_QUEUEOVF // profiling queue is full, payload is number of frame drops
|
||||
};
|
||||
|
||||
void qp_mark(unsigned int type, int len);
|
||||
void qp_log(void); // timestamp, type, payload
|
||||
void qp_init(void);
|
||||
#else
|
||||
#define qp_mark(a, b)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
Reference in New Issue
Block a user