mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-28 23:49:44 +08:00
commit
6386cdff50
256
mongoose.c
256
mongoose.c
@ -8879,8 +8879,6 @@ struct mg_tcpip_driver mg_tcpip_driver_imxrt = {mg_tcpip_driver_imxrt_init,
|
||||
|
||||
#include <sam.h>
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1536 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 2 // Descriptor size (words)
|
||||
@ -8895,9 +8893,9 @@ static uint8_t s_rxno; // Current RX descriptor
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 };
|
||||
|
||||
#define PHY_BCR_DUPLEX_MODE_Msk BIT(8)
|
||||
#define PHY_BCR_SPEED_Msk BIT(13)
|
||||
#define PHY_BSR_LINK_STATUS_Msk BIT(2)
|
||||
#define PHY_BCR_DUPLEX_MODE_Msk MG_BIT(8)
|
||||
#define PHY_BCR_SPEED_Msk MG_BIT(13)
|
||||
#define PHY_BSR_LINK_STATUS_Msk MG_BIT(2)
|
||||
|
||||
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
|
||||
@ -8980,16 +8978,16 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
|
||||
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
|
||||
s_txdesc[i][1] = BIT(31); // OWN bit
|
||||
s_txdesc[i][1] = MG_BIT(31); // OWN bit
|
||||
}
|
||||
s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap
|
||||
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); // DMA recv buf 1536
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
||||
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
||||
s_rxdesc[i][1] = 0; // Clear status
|
||||
}
|
||||
s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - wrap
|
||||
s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(1); // Last rx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
|
||||
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
|
||||
@ -9023,13 +9021,13 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // Frame is too big
|
||||
} else if ((s_txdesc[s_txno][1] & BIT(31)) == 0) {
|
||||
} else if ((s_txdesc[s_txno][1] & MG_BIT(31)) == 0) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No free descriptors"));
|
||||
len = 0; // All descriptors are busy, fail
|
||||
} else {
|
||||
uint32_t status = len | BIT(15); // Frame length, last chunk
|
||||
if (s_txno == ETH_DESC_CNT - 1) status |= BIT(30); // wrap
|
||||
uint32_t status = len | MG_BIT(15); // Frame length, last chunk
|
||||
if (s_txno == ETH_DESC_CNT - 1) status |= MG_BIT(30); // wrap
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][1] = status;
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
@ -9064,10 +9062,10 @@ void GMAC_Handler(void) {
|
||||
if (isr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (rsr & GMAC_ISR_RCOMP_Msk) {
|
||||
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||
if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break;
|
||||
size_t len = s_rxdesc[s_rxno][1] & (BIT(13) - 1);
|
||||
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
|
||||
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
|
||||
s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown
|
||||
s_rxdesc[s_rxno][0] &= ~MG_BIT(0); // Disown
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
@ -9077,7 +9075,7 @@ void GMAC_Handler(void) {
|
||||
GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
|
||||
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
|
||||
if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31);
|
||||
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
|
||||
}
|
||||
|
||||
GMAC_REGS->GMAC_RSR = rsr;
|
||||
@ -9111,8 +9109,6 @@ struct stm32_eth {
|
||||
#undef ETH
|
||||
#define ETH ((struct stm32_eth *) (uintptr_t) 0x40028000)
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
@ -9130,17 +9126,17 @@ enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1, PHY_CSCR = 31 };
|
||||
static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
ETH->MACMIIAR &= (7 << 2);
|
||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
|
||||
ETH->MACMIIAR |= BIT(0);
|
||||
while (ETH->MACMIIAR & BIT(0)) (void) 0;
|
||||
ETH->MACMIIAR |= MG_BIT(0);
|
||||
while (ETH->MACMIIAR & MG_BIT(0)) (void) 0;
|
||||
return ETH->MACMIIDR;
|
||||
}
|
||||
|
||||
static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
|
||||
ETH->MACMIIDR = val;
|
||||
ETH->MACMIIAR &= (7 << 2);
|
||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | BIT(1);
|
||||
ETH->MACMIIAR |= BIT(0);
|
||||
while (ETH->MACMIIAR & BIT(0)) (void) 0;
|
||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
|
||||
ETH->MACMIIAR |= MG_BIT(0);
|
||||
while (ETH->MACMIIAR & MG_BIT(0)) (void) 0;
|
||||
}
|
||||
|
||||
static uint32_t get_hclk(void) {
|
||||
@ -9204,8 +9200,8 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// Init RX descriptors
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
||||
s_rxdesc[i][0] = BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][0] = MG_BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
|
||||
s_rxdesc[i][3] =
|
||||
(uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
@ -9218,8 +9214,8 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) {
|
||||
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
}
|
||||
|
||||
ETH->DMABMR |= BIT(0); // Software reset
|
||||
while ((ETH->DMABMR & BIT(0)) != 0) (void) 0; // Wait until done
|
||||
ETH->DMABMR |= MG_BIT(0); // Software reset
|
||||
while ((ETH->DMABMR & MG_BIT(0)) != 0) (void) 0; // Wait until done
|
||||
|
||||
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
|
||||
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
|
||||
@ -9227,17 +9223,17 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// NOTE(cpq): we do not use extended descriptor bit 7, and do not use
|
||||
// hardware checksum. Therefore, descriptor size is 4, not 8
|
||||
// ETH->DMABMR = BIT(13) | BIT(16) | BIT(22) | BIT(23) | BIT(25);
|
||||
ETH->MACIMR = BIT(3) | BIT(9); // Mask timestamp & PMT IT
|
||||
ETH->MACFCR = BIT(7); // Disable zero quarta pause
|
||||
// ETH->MACFFR = BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(12)); // Set autonegotiation
|
||||
// ETH->DMABMR = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) | MG_BIT(25);
|
||||
ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
|
||||
ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause
|
||||
// ETH->MACFFR = MG_BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(12)); // Set autonegotiation
|
||||
ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
|
||||
ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc; // RX descriptors
|
||||
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
|
||||
ETH->DMAIER = MG_BIT(6) | MG_BIT(16); // RIE, NISE
|
||||
ETH->MACCR = MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast
|
||||
ETH->DMAOMR = MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
|
||||
|
||||
// MAC address filtering
|
||||
ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
|
||||
@ -9252,7 +9248,7 @@ static size_t mg_tcpip_driver_stm32_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // Frame is too big
|
||||
} else if ((s_txdesc[s_txno][0] & BIT(31))) {
|
||||
} else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No free descriptors"));
|
||||
// printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long) ETH->DMASR);
|
||||
@ -9260,52 +9256,52 @@ static size_t mg_tcpip_driver_stm32_tx(const void *buf, size_t len,
|
||||
} else {
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][1] = (uint32_t) len; // Set data len
|
||||
s_txdesc[s_txno][0] = BIT(20) | BIT(28) | BIT(29); // Chain,FS,LS
|
||||
s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over
|
||||
s_txdesc[s_txno][0] = MG_BIT(20) | MG_BIT(28) | MG_BIT(29); // Chain,FS,LS
|
||||
s_txdesc[s_txno][0] |= MG_BIT(31); // Set OWN bit - let DMA take over
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
MG_DSB(); // ensure descriptors have been written
|
||||
ETH->DMASR = BIT(2) | BIT(5); // Clear any prior TBUS/TUS
|
||||
ETH->DMASR = MG_BIT(2) | MG_BIT(5); // Clear any prior TBUS/TUS
|
||||
ETH->DMATPDR = 0; // and resume
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool mg_tcpip_driver_stm32_up(struct mg_tcpip_if *ifp) {
|
||||
uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR);
|
||||
bool up = bsr & BIT(2) ? 1 : 0;
|
||||
bool up = bsr & MG_BIT(2) ? 1 : 0;
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
|
||||
uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR);
|
||||
// tmp = reg with flags set to the most likely situation: 100M full-duplex
|
||||
// if(link is slow or half) set flags otherwise
|
||||
// reg = tmp
|
||||
uint32_t maccr = ETH->MACCR | BIT(14) | BIT(11); // 100M, Full-duplex
|
||||
if ((scsr & BIT(3)) == 0) maccr &= ~BIT(14); // 10M
|
||||
if ((scsr & BIT(4)) == 0) maccr &= ~BIT(11); // Half-duplex
|
||||
uint32_t maccr = ETH->MACCR | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex
|
||||
if ((scsr & MG_BIT(3)) == 0) maccr &= ~MG_BIT(14); // 10M
|
||||
if ((scsr & MG_BIT(4)) == 0) maccr &= ~MG_BIT(11); // Half-duplex
|
||||
ETH->MACCR = maccr; // IRQ handler does not fiddle with this register
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & BIT(14) ? 100 : 10,
|
||||
maccr & BIT(11) ? "full" : "half"));
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & MG_BIT(14) ? 100 : 10,
|
||||
maccr & MG_BIT(11) ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
|
||||
void ETH_IRQHandler(void);
|
||||
void ETH_IRQHandler(void) {
|
||||
if (ETH->DMASR & BIT(6)) { // Frame received, loop
|
||||
ETH->DMASR = BIT(16) | BIT(6); // Clear flag
|
||||
if (ETH->DMASR & MG_BIT(6)) { // Frame received, loop
|
||||
ETH->DMASR = MG_BIT(16) | MG_BIT(6); // Clear flag
|
||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if (s_rxdesc[s_rxno][0] & BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (BIT(8) | BIT(9))) == (BIT(8) | BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (BIT(14) - 1));
|
||||
if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) == (MG_BIT(8) | MG_BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1));
|
||||
// printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
|
||||
// ETH->DMASR);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
}
|
||||
s_rxdesc[s_rxno][0] = BIT(31);
|
||||
s_rxdesc[s_rxno][0] = MG_BIT(31);
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
ETH->DMASR = BIT(7); // Clear possible RBUS while processing
|
||||
ETH->DMASR = MG_BIT(7); // Clear possible RBUS while processing
|
||||
ETH->DMARPDR = 0; // and resume RX
|
||||
}
|
||||
|
||||
@ -9355,8 +9351,6 @@ struct stm32h_eth {
|
||||
#define ETH \
|
||||
((struct stm32h_eth *) (uintptr_t) (0x40000000UL + 0x00020000UL + 0x8000UL))
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
@ -9376,8 +9370,8 @@ enum {
|
||||
static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
ETH->MACMDIOAR &= (0xF << 8);
|
||||
ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 3 << 2;
|
||||
ETH->MACMDIOAR |= BIT(0);
|
||||
while (ETH->MACMDIOAR & BIT(0)) (void) 0;
|
||||
ETH->MACMDIOAR |= MG_BIT(0);
|
||||
while (ETH->MACMDIOAR & MG_BIT(0)) (void) 0;
|
||||
return ETH->MACMDIODR;
|
||||
}
|
||||
|
||||
@ -9385,8 +9379,8 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
|
||||
ETH->MACMDIODR = val;
|
||||
ETH->MACMDIOAR &= (0xF << 8);
|
||||
ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 1 << 2;
|
||||
ETH->MACMDIOAR |= BIT(0);
|
||||
while (ETH->MACMDIOAR & BIT(0)) (void) 0;
|
||||
ETH->MACMDIOAR |= MG_BIT(0);
|
||||
while (ETH->MACMDIOAR & MG_BIT(0)) (void) 0;
|
||||
}
|
||||
|
||||
static uint32_t get_hclk(void) {
|
||||
@ -9415,7 +9409,7 @@ static uint32_t get_hclk(void) {
|
||||
unsigned int src = (rcc->PLLCKSELR & (3 << 0)) >> 0;
|
||||
m = ((rcc->PLLCKSELR & (0x3F << 4)) >> 4);
|
||||
n = ((rcc->PLL1DIVR & (0x1FF << 0)) >> 0) + 1 +
|
||||
((rcc->PLLCFGR & BIT(0)) ? 1 : 0); // round-up in fractional mode
|
||||
((rcc->PLLCFGR & MG_BIT(0)) ? 1 : 0); // round-up in fractional mode
|
||||
p = ((rcc->PLL1DIVR & (0x7F << 9)) >> 9) + 1;
|
||||
if (src == 1) {
|
||||
clk = csi;
|
||||
@ -9473,7 +9467,7 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
// Init RX descriptors
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
||||
s_rxdesc[i][0] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
|
||||
s_rxdesc[i][3] = BIT(31) | BIT(30) | BIT(24); // OWN, IOC, BUF1V
|
||||
s_rxdesc[i][3] = MG_BIT(31) | MG_BIT(30) | MG_BIT(24); // OWN, IOC, BUF1V
|
||||
}
|
||||
|
||||
// Init TX descriptors
|
||||
@ -9481,8 +9475,8 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
s_txdesc[i][0] = (uint32_t) (uintptr_t) s_txbuf[i]; // Buf pointer
|
||||
}
|
||||
|
||||
ETH->DMAMR |= BIT(0); // Software reset
|
||||
while ((ETH->DMAMR & BIT(0)) != 0) (void) 0; // Wait until done
|
||||
ETH->DMAMR |= MG_BIT(0); // Software reset
|
||||
while ((ETH->DMAMR & MG_BIT(0)) != 0) (void) 0; // Wait until done
|
||||
|
||||
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
|
||||
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
|
||||
@ -9491,12 +9485,12 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
// NOTE(scaprile): We do not use timing facilities so the DMA engine does not
|
||||
// re-write buffer address
|
||||
ETH->DMAMR = 0 << 16; // use interrupt mode 0 (58.8.1) (reset value)
|
||||
ETH->DMASBMR |= BIT(12); // AAL NOTE(scaprile): is this actually needed
|
||||
ETH->DMASBMR |= MG_BIT(12); // AAL NOTE(scaprile): is this actually needed
|
||||
ETH->MACIER = 0; // Do not enable additional irq sources (reset value)
|
||||
ETH->MACTFCR = BIT(7); // Disable zero-quanta pause
|
||||
// ETH->MACPFR = BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(12)); // Set autonegotiation
|
||||
ETH->MACTFCR = MG_BIT(7); // Disable zero-quanta pause
|
||||
// ETH->MACPFR = MG_BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(12)); // Set autonegotiation
|
||||
ETH->DMACRDLAR =
|
||||
(uint32_t) (uintptr_t) s_rxdesc; // RX descriptors start address
|
||||
ETH->DMACRDRLR = ETH_DESC_CNT - 1; // ring length
|
||||
@ -9509,13 +9503,13 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
ETH->DMACTDTPR =
|
||||
(uint32_t) (uintptr_t) s_txdesc; // first available descriptor address
|
||||
ETH->DMACCR = 0; // DSL = 0 (contiguous descriptor table) (reset value)
|
||||
ETH->DMACIER = BIT(6) | BIT(15); // RIE, NIE
|
||||
ETH->MACCR = BIT(0) | BIT(1) | BIT(13) | BIT(14) |
|
||||
BIT(15); // RE, TE, Duplex, Fast, Reserved
|
||||
ETH->MTLTQOMR |= BIT(1); // TSF
|
||||
ETH->MTLRQOMR |= BIT(5); // RSF
|
||||
ETH->DMACTCR |= BIT(0); // ST
|
||||
ETH->DMACRCR |= BIT(0); // SR
|
||||
ETH->DMACIER = MG_BIT(6) | MG_BIT(15); // RIE, NIE
|
||||
ETH->MACCR = MG_BIT(0) | MG_BIT(1) | MG_BIT(13) | MG_BIT(14) |
|
||||
MG_BIT(15); // RE, TE, Duplex, Fast, Reserved
|
||||
ETH->MTLTQOMR |= MG_BIT(1); // TSF
|
||||
ETH->MTLRQOMR |= MG_BIT(5); // RSF
|
||||
ETH->DMACTCR |= MG_BIT(0); // ST
|
||||
ETH->DMACRCR |= MG_BIT(0); // SR
|
||||
|
||||
// MAC address filtering
|
||||
ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
|
||||
@ -9531,7 +9525,7 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // Frame is too big
|
||||
} else if ((s_txdesc[s_txno][3] & BIT(31))) {
|
||||
} else if ((s_txdesc[s_txno][3] & MG_BIT(31))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No free descriptors: %u %08X %08X %08X", s_txno,
|
||||
s_txdesc[s_txno][3], ETH->DMACSR, ETH->DMACTCR));
|
||||
@ -9540,11 +9534,11 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
|
||||
} else {
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][2] = (uint32_t) len; // Set data len
|
||||
s_txdesc[s_txno][3] = BIT(28) | BIT(29); // FD, LD
|
||||
s_txdesc[s_txno][3] |= BIT(31); // Set OWN bit - let DMA take over
|
||||
s_txdesc[s_txno][3] = MG_BIT(28) | MG_BIT(29); // FD, LD
|
||||
s_txdesc[s_txno][3] |= MG_BIT(31); // Set OWN bit - let DMA take over
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
ETH->DMACSR |= BIT(2) | BIT(1); // Clear any prior TBU, TPS
|
||||
ETH->DMACSR |= MG_BIT(2) | MG_BIT(1); // Clear any prior TBU, TPS
|
||||
ETH->DMACTDTPR = (uint32_t) (uintptr_t) &s_txdesc[s_txno]; // and resume
|
||||
return len;
|
||||
(void) ifp;
|
||||
@ -9552,18 +9546,18 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
|
||||
|
||||
static bool mg_tcpip_driver_stm32h_up(struct mg_tcpip_if *ifp) {
|
||||
uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR);
|
||||
bool up = bsr & BIT(2) ? 1 : 0;
|
||||
bool up = bsr & MG_BIT(2) ? 1 : 0;
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
|
||||
uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR);
|
||||
// tmp = reg with flags set to the most likely situation: 100M full-duplex
|
||||
// if(link is slow or half) set flags otherwise
|
||||
// reg = tmp
|
||||
uint32_t maccr = ETH->MACCR | BIT(14) | BIT(13); // 100M, Full-duplex
|
||||
if ((scsr & BIT(3)) == 0) maccr &= ~BIT(14); // 10M
|
||||
if ((scsr & BIT(4)) == 0) maccr &= ~BIT(13); // Half-duplex
|
||||
uint32_t maccr = ETH->MACCR | MG_BIT(14) | MG_BIT(13); // 100M, Full-duplex
|
||||
if ((scsr & MG_BIT(3)) == 0) maccr &= ~MG_BIT(14); // 10M
|
||||
if ((scsr & MG_BIT(4)) == 0) maccr &= ~MG_BIT(13); // Half-duplex
|
||||
ETH->MACCR = maccr; // IRQ handler does not fiddle with this register
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & BIT(14) ? 100 : 10,
|
||||
maccr & BIT(13) ? "full" : "half"));
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & MG_BIT(14) ? 100 : 10,
|
||||
maccr & MG_BIT(13) ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
@ -9571,23 +9565,23 @@ static bool mg_tcpip_driver_stm32h_up(struct mg_tcpip_if *ifp) {
|
||||
void ETH_IRQHandler(void);
|
||||
static uint32_t s_rxno;
|
||||
void ETH_IRQHandler(void) {
|
||||
if (ETH->DMACSR & BIT(6)) { // Frame received, loop
|
||||
ETH->DMACSR = BIT(15) | BIT(6); // Clear flag
|
||||
if (ETH->DMACSR & MG_BIT(6)) { // Frame received, loop
|
||||
ETH->DMACSR = MG_BIT(15) | MG_BIT(6); // Clear flag
|
||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if (s_rxdesc[s_rxno][3] & BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][3] & (BIT(28) | BIT(29))) ==
|
||||
(BIT(28) | BIT(29))) &&
|
||||
!(s_rxdesc[s_rxno][3] & BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = s_rxdesc[s_rxno][3] & (BIT(15) - 1);
|
||||
if (s_rxdesc[s_rxno][3] & MG_BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][3] & (MG_BIT(28) | MG_BIT(29))) ==
|
||||
(MG_BIT(28) | MG_BIT(29))) &&
|
||||
!(s_rxdesc[s_rxno][3] & MG_BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = s_rxdesc[s_rxno][3] & (MG_BIT(15) - 1);
|
||||
// MG_DEBUG(("%lx %lu %lx %08lx", s_rxno, len, s_rxdesc[s_rxno][3],
|
||||
// ETH->DMACSR));
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
}
|
||||
s_rxdesc[s_rxno][3] = BIT(31) | BIT(30) | BIT(24); // OWN, IOC, BUF1V
|
||||
s_rxdesc[s_rxno][3] = MG_BIT(31) | MG_BIT(30) | MG_BIT(24); // OWN, IOC, BUF1V
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
ETH->DMACSR = BIT(7) | BIT(8); // Clear possible RBU RPS while processing
|
||||
ETH->DMACSR = MG_BIT(7) | MG_BIT(8); // Clear possible RBU RPS while processing
|
||||
ETH->DMACRDTPR =
|
||||
(uint32_t) (uintptr_t) &s_rxdesc[ETH_DESC_CNT - 1]; // and resume RX
|
||||
}
|
||||
@ -9626,8 +9620,6 @@ struct tm4c_emac {
|
||||
#undef EMAC
|
||||
#define EMAC ((struct tm4c_emac *) (uintptr_t) 0x400EC000)
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
@ -9651,17 +9643,17 @@ static inline void tm4cspin(volatile uint32_t count) {
|
||||
static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
|
||||
EMAC->EMACMIIADDR &= (0xf << 2);
|
||||
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
|
||||
EMAC->EMACMIIADDR |= BIT(0);
|
||||
while (EMAC->EMACMIIADDR & BIT(0)) tm4cspin(1);
|
||||
EMAC->EMACMIIADDR |= MG_BIT(0);
|
||||
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
|
||||
return EMAC->EMACMIIDATA;
|
||||
}
|
||||
|
||||
static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
|
||||
EMAC->EMACMIIDATA = val;
|
||||
EMAC->EMACMIIADDR &= (0xf << 2);
|
||||
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | BIT(1);
|
||||
EMAC->EMACMIIADDR |= BIT(0);
|
||||
while (EMAC->EMACMIIADDR & BIT(0)) tm4cspin(1);
|
||||
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
|
||||
EMAC->EMACMIIADDR |= MG_BIT(0);
|
||||
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
|
||||
}
|
||||
|
||||
static uint32_t get_sysclk(void) {
|
||||
@ -9737,8 +9729,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// Init RX descriptors
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
||||
s_rxdesc[i][0] = BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][0] = MG_BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
|
||||
s_rxdesc[i][3] =
|
||||
(uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
@ -9752,8 +9744,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
|
||||
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
}
|
||||
|
||||
EMAC->EMACDMABUSMOD |= BIT(0); // Software reset
|
||||
while ((EMAC->EMACDMABUSMOD & BIT(0)) != 0) tm4cspin(1); // Wait until done
|
||||
EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
|
||||
while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) tm4cspin(1); // Wait until done
|
||||
|
||||
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
|
||||
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
|
||||
@ -9761,19 +9753,19 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// NOTE(cpq): we do not use extended descriptor bit 7, and do not use
|
||||
// hardware checksum. Therefore, descriptor size is 4, not 8
|
||||
// EMAC->EMACDMABUSMOD = BIT(13) | BIT(16) | BIT(22) | BIT(23) | BIT(25);
|
||||
EMAC->EMACIM = BIT(3) | BIT(9); // Mask timestamp & PMT IT
|
||||
EMAC->EMACFLOWCTL = BIT(7); // Disable zero-quanta pause
|
||||
// EMAC->EMACFRAMEFLTR = BIT(31); // Receive all
|
||||
// EMAC->EMACDMABUSMOD = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) | MG_BIT(25);
|
||||
EMAC->EMACIM = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
|
||||
EMAC->EMACFLOWCTL = MG_BIT(7); // Disable zero-quanta pause
|
||||
// EMAC->EMACFRAMEFLTR = MG_BIT(31); // Receive all
|
||||
// EMAC->EMACPC defaults to internal PHY (EPHY) in MMI mode
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, BIT(15)); // Reset internal PHY (EPHY)
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, BIT(12)); // Set autonegotiation
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(15)); // Reset internal PHY (EPHY)
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(12)); // Set autonegotiation
|
||||
EMAC->EMACRXDLADDR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
|
||||
EMAC->EMACTXDLADDR = (uint32_t) (uintptr_t) s_txdesc; // TX descriptors
|
||||
EMAC->EMACDMAIM = BIT(6) | BIT(16); // RIE, NIE
|
||||
EMAC->EMACCFG = BIT(2) | BIT(3) | BIT(11) | BIT(14); // RE, TE, Duplex, Fast
|
||||
EMAC->EMACDMAIM = MG_BIT(6) | MG_BIT(16); // RIE, NIE
|
||||
EMAC->EMACCFG = MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast
|
||||
EMAC->EMACDMAOPMODE =
|
||||
BIT(1) | BIT(13) | BIT(21) | BIT(25); // SR, ST, TSF, RSF
|
||||
MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
|
||||
EMAC->EMACADDR0H = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
|
||||
EMAC->EMACADDR0L = (uint32_t) (ifp->mac[3] << 24) |
|
||||
((uint32_t) ifp->mac[2] << 16) |
|
||||
@ -9789,7 +9781,7 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // fail
|
||||
} else if ((s_txdesc[s_txno][0] & BIT(31))) {
|
||||
} else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No descriptors available"));
|
||||
// printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long)
|
||||
@ -9799,11 +9791,11 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][1] = (uint32_t) len; // Set data len
|
||||
s_txdesc[s_txno][0] =
|
||||
BIT(20) | BIT(28) | BIT(29) | BIT(30); // Chain,FS,LS,IC
|
||||
s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over
|
||||
MG_BIT(20) | MG_BIT(28) | MG_BIT(29) | MG_BIT(30); // Chain,FS,LS,IC
|
||||
s_txdesc[s_txno][0] |= MG_BIT(31); // Set OWN bit - let DMA take over
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
EMAC->EMACDMARIS = BIT(2) | BIT(5); // Clear any prior TU/UNF
|
||||
EMAC->EMACDMARIS = MG_BIT(2) | MG_BIT(5); // Clear any prior TU/UNF
|
||||
EMAC->EMACTXPOLLD = 0; // and resume
|
||||
return len;
|
||||
(void) ifp;
|
||||
@ -9811,18 +9803,18 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
|
||||
|
||||
static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) {
|
||||
uint32_t bmsr = emac_read_phy(EPHY_ADDR, EPHYBMSR);
|
||||
bool up = (bmsr & BIT(2)) ? 1 : 0;
|
||||
bool up = (bmsr & MG_BIT(2)) ? 1 : 0;
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
|
||||
uint32_t sts = emac_read_phy(EPHY_ADDR, EPHYSTS);
|
||||
// tmp = reg with flags set to the most likely situation: 100M full-duplex
|
||||
// if(link is slow or half) set flags otherwise
|
||||
// reg = tmp
|
||||
uint32_t emaccfg = EMAC->EMACCFG | BIT(14) | BIT(11); // 100M, Full-duplex
|
||||
if (sts & BIT(1)) emaccfg &= ~BIT(14); // 10M
|
||||
if ((sts & BIT(2)) == 0) emaccfg &= ~BIT(11); // Half-duplex
|
||||
uint32_t emaccfg = EMAC->EMACCFG | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex
|
||||
if (sts & MG_BIT(1)) emaccfg &= ~MG_BIT(14); // 10M
|
||||
if ((sts & MG_BIT(2)) == 0) emaccfg &= ~MG_BIT(11); // Half-duplex
|
||||
EMAC->EMACCFG = emaccfg; // IRQ handler does not fiddle with this register
|
||||
MG_DEBUG(("Link is %uM %s-duplex", emaccfg & BIT(14) ? 100 : 10,
|
||||
emaccfg & BIT(11) ? "full" : "half"));
|
||||
MG_DEBUG(("Link is %uM %s-duplex", emaccfg & MG_BIT(14) ? 100 : 10,
|
||||
emaccfg & MG_BIT(11) ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
@ -9830,22 +9822,22 @@ static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) {
|
||||
void EMAC0_IRQHandler(void);
|
||||
static uint32_t s_rxno;
|
||||
void EMAC0_IRQHandler(void) {
|
||||
if (EMAC->EMACDMARIS & BIT(6)) { // Frame received, loop
|
||||
EMAC->EMACDMARIS = BIT(16) | BIT(6); // Clear flag
|
||||
if (EMAC->EMACDMARIS & MG_BIT(6)) { // Frame received, loop
|
||||
EMAC->EMACDMARIS = MG_BIT(16) | MG_BIT(6); // Clear flag
|
||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if (s_rxdesc[s_rxno][0] & BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (BIT(8) | BIT(9))) == (BIT(8) | BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (BIT(14) - 1));
|
||||
if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) == (MG_BIT(8) | MG_BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1));
|
||||
// printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
|
||||
// EMAC->EMACDMARIS);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
}
|
||||
s_rxdesc[s_rxno][0] = BIT(31);
|
||||
s_rxdesc[s_rxno][0] = MG_BIT(31);
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
EMAC->EMACDMARIS = BIT(7); // Clear possible RU while processing
|
||||
EMAC->EMACDMARIS = MG_BIT(7); // Clear possible RU while processing
|
||||
EMAC->EMACRXPOLLD = 0; // and resume RX
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
#include <sam.h>
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1536 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 2 // Descriptor size (words)
|
||||
@ -21,9 +19,9 @@ static uint8_t s_rxno; // Current RX descriptor
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 };
|
||||
|
||||
#define PHY_BCR_DUPLEX_MODE_Msk BIT(8)
|
||||
#define PHY_BCR_SPEED_Msk BIT(13)
|
||||
#define PHY_BSR_LINK_STATUS_Msk BIT(2)
|
||||
#define PHY_BCR_DUPLEX_MODE_Msk MG_BIT(8)
|
||||
#define PHY_BCR_SPEED_Msk MG_BIT(13)
|
||||
#define PHY_BSR_LINK_STATUS_Msk MG_BIT(2)
|
||||
|
||||
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
|
||||
@ -106,16 +104,16 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
|
||||
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
|
||||
s_txdesc[i][1] = BIT(31); // OWN bit
|
||||
s_txdesc[i][1] = MG_BIT(31); // OWN bit
|
||||
}
|
||||
s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap
|
||||
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); // DMA recv buf 1536
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
||||
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
||||
s_rxdesc[i][1] = 0; // Clear status
|
||||
}
|
||||
s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - wrap
|
||||
s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(1); // Last rx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
|
||||
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
|
||||
@ -149,13 +147,13 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // Frame is too big
|
||||
} else if ((s_txdesc[s_txno][1] & BIT(31)) == 0) {
|
||||
} else if ((s_txdesc[s_txno][1] & MG_BIT(31)) == 0) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No free descriptors"));
|
||||
len = 0; // All descriptors are busy, fail
|
||||
} else {
|
||||
uint32_t status = len | BIT(15); // Frame length, last chunk
|
||||
if (s_txno == ETH_DESC_CNT - 1) status |= BIT(30); // wrap
|
||||
uint32_t status = len | MG_BIT(15); // Frame length, last chunk
|
||||
if (s_txno == ETH_DESC_CNT - 1) status |= MG_BIT(30); // wrap
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][1] = status;
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
@ -190,10 +188,10 @@ void GMAC_Handler(void) {
|
||||
if (isr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (rsr & GMAC_ISR_RCOMP_Msk) {
|
||||
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||
if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break;
|
||||
size_t len = s_rxdesc[s_rxno][1] & (BIT(13) - 1);
|
||||
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
|
||||
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
|
||||
s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown
|
||||
s_rxdesc[s_rxno][0] &= ~MG_BIT(0); // Disown
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
@ -203,7 +201,7 @@ void GMAC_Handler(void) {
|
||||
GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
|
||||
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
|
||||
if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31);
|
||||
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
|
||||
}
|
||||
|
||||
GMAC_REGS->GMAC_RSR = rsr;
|
||||
|
@ -17,8 +17,6 @@ struct stm32_eth {
|
||||
#undef ETH
|
||||
#define ETH ((struct stm32_eth *) (uintptr_t) 0x40028000)
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
@ -36,17 +34,17 @@ enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1, PHY_CSCR = 31 };
|
||||
static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
ETH->MACMIIAR &= (7 << 2);
|
||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
|
||||
ETH->MACMIIAR |= BIT(0);
|
||||
while (ETH->MACMIIAR & BIT(0)) (void) 0;
|
||||
ETH->MACMIIAR |= MG_BIT(0);
|
||||
while (ETH->MACMIIAR & MG_BIT(0)) (void) 0;
|
||||
return ETH->MACMIIDR;
|
||||
}
|
||||
|
||||
static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
|
||||
ETH->MACMIIDR = val;
|
||||
ETH->MACMIIAR &= (7 << 2);
|
||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | BIT(1);
|
||||
ETH->MACMIIAR |= BIT(0);
|
||||
while (ETH->MACMIIAR & BIT(0)) (void) 0;
|
||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
|
||||
ETH->MACMIIAR |= MG_BIT(0);
|
||||
while (ETH->MACMIIAR & MG_BIT(0)) (void) 0;
|
||||
}
|
||||
|
||||
static uint32_t get_hclk(void) {
|
||||
@ -110,8 +108,8 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// Init RX descriptors
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
||||
s_rxdesc[i][0] = BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][0] = MG_BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
|
||||
s_rxdesc[i][3] =
|
||||
(uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
@ -124,8 +122,8 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) {
|
||||
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
}
|
||||
|
||||
ETH->DMABMR |= BIT(0); // Software reset
|
||||
while ((ETH->DMABMR & BIT(0)) != 0) (void) 0; // Wait until done
|
||||
ETH->DMABMR |= MG_BIT(0); // Software reset
|
||||
while ((ETH->DMABMR & MG_BIT(0)) != 0) (void) 0; // Wait until done
|
||||
|
||||
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
|
||||
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
|
||||
@ -133,17 +131,17 @@ static bool mg_tcpip_driver_stm32_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// NOTE(cpq): we do not use extended descriptor bit 7, and do not use
|
||||
// hardware checksum. Therefore, descriptor size is 4, not 8
|
||||
// ETH->DMABMR = BIT(13) | BIT(16) | BIT(22) | BIT(23) | BIT(25);
|
||||
ETH->MACIMR = BIT(3) | BIT(9); // Mask timestamp & PMT IT
|
||||
ETH->MACFCR = BIT(7); // Disable zero quarta pause
|
||||
// ETH->MACFFR = BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(12)); // Set autonegotiation
|
||||
// ETH->DMABMR = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) | MG_BIT(25);
|
||||
ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
|
||||
ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause
|
||||
// ETH->MACFFR = MG_BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(12)); // Set autonegotiation
|
||||
ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
|
||||
ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc; // RX descriptors
|
||||
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
|
||||
ETH->DMAIER = MG_BIT(6) | MG_BIT(16); // RIE, NISE
|
||||
ETH->MACCR = MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast
|
||||
ETH->DMAOMR = MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
|
||||
|
||||
// MAC address filtering
|
||||
ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
|
||||
@ -158,7 +156,7 @@ static size_t mg_tcpip_driver_stm32_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // Frame is too big
|
||||
} else if ((s_txdesc[s_txno][0] & BIT(31))) {
|
||||
} else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No free descriptors"));
|
||||
// printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long) ETH->DMASR);
|
||||
@ -166,52 +164,52 @@ static size_t mg_tcpip_driver_stm32_tx(const void *buf, size_t len,
|
||||
} else {
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][1] = (uint32_t) len; // Set data len
|
||||
s_txdesc[s_txno][0] = BIT(20) | BIT(28) | BIT(29); // Chain,FS,LS
|
||||
s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over
|
||||
s_txdesc[s_txno][0] = MG_BIT(20) | MG_BIT(28) | MG_BIT(29); // Chain,FS,LS
|
||||
s_txdesc[s_txno][0] |= MG_BIT(31); // Set OWN bit - let DMA take over
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
MG_DSB(); // ensure descriptors have been written
|
||||
ETH->DMASR = BIT(2) | BIT(5); // Clear any prior TBUS/TUS
|
||||
ETH->DMASR = MG_BIT(2) | MG_BIT(5); // Clear any prior TBUS/TUS
|
||||
ETH->DMATPDR = 0; // and resume
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool mg_tcpip_driver_stm32_up(struct mg_tcpip_if *ifp) {
|
||||
uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR);
|
||||
bool up = bsr & BIT(2) ? 1 : 0;
|
||||
bool up = bsr & MG_BIT(2) ? 1 : 0;
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
|
||||
uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR);
|
||||
// tmp = reg with flags set to the most likely situation: 100M full-duplex
|
||||
// if(link is slow or half) set flags otherwise
|
||||
// reg = tmp
|
||||
uint32_t maccr = ETH->MACCR | BIT(14) | BIT(11); // 100M, Full-duplex
|
||||
if ((scsr & BIT(3)) == 0) maccr &= ~BIT(14); // 10M
|
||||
if ((scsr & BIT(4)) == 0) maccr &= ~BIT(11); // Half-duplex
|
||||
uint32_t maccr = ETH->MACCR | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex
|
||||
if ((scsr & MG_BIT(3)) == 0) maccr &= ~MG_BIT(14); // 10M
|
||||
if ((scsr & MG_BIT(4)) == 0) maccr &= ~MG_BIT(11); // Half-duplex
|
||||
ETH->MACCR = maccr; // IRQ handler does not fiddle with this register
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & BIT(14) ? 100 : 10,
|
||||
maccr & BIT(11) ? "full" : "half"));
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & MG_BIT(14) ? 100 : 10,
|
||||
maccr & MG_BIT(11) ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
|
||||
void ETH_IRQHandler(void);
|
||||
void ETH_IRQHandler(void) {
|
||||
if (ETH->DMASR & BIT(6)) { // Frame received, loop
|
||||
ETH->DMASR = BIT(16) | BIT(6); // Clear flag
|
||||
if (ETH->DMASR & MG_BIT(6)) { // Frame received, loop
|
||||
ETH->DMASR = MG_BIT(16) | MG_BIT(6); // Clear flag
|
||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if (s_rxdesc[s_rxno][0] & BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (BIT(8) | BIT(9))) == (BIT(8) | BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (BIT(14) - 1));
|
||||
if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) == (MG_BIT(8) | MG_BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1));
|
||||
// printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
|
||||
// ETH->DMASR);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
}
|
||||
s_rxdesc[s_rxno][0] = BIT(31);
|
||||
s_rxdesc[s_rxno][0] = MG_BIT(31);
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
ETH->DMASR = BIT(7); // Clear possible RBUS while processing
|
||||
ETH->DMASR = MG_BIT(7); // Clear possible RBUS while processing
|
||||
ETH->DMARPDR = 0; // and resume RX
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,6 @@ struct stm32h_eth {
|
||||
#define ETH \
|
||||
((struct stm32h_eth *) (uintptr_t) (0x40000000UL + 0x00020000UL + 0x8000UL))
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
@ -57,8 +55,8 @@ enum {
|
||||
static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
ETH->MACMDIOAR &= (0xF << 8);
|
||||
ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 3 << 2;
|
||||
ETH->MACMDIOAR |= BIT(0);
|
||||
while (ETH->MACMDIOAR & BIT(0)) (void) 0;
|
||||
ETH->MACMDIOAR |= MG_BIT(0);
|
||||
while (ETH->MACMDIOAR & MG_BIT(0)) (void) 0;
|
||||
return ETH->MACMDIODR;
|
||||
}
|
||||
|
||||
@ -66,8 +64,8 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
|
||||
ETH->MACMDIODR = val;
|
||||
ETH->MACMDIOAR &= (0xF << 8);
|
||||
ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 1 << 2;
|
||||
ETH->MACMDIOAR |= BIT(0);
|
||||
while (ETH->MACMDIOAR & BIT(0)) (void) 0;
|
||||
ETH->MACMDIOAR |= MG_BIT(0);
|
||||
while (ETH->MACMDIOAR & MG_BIT(0)) (void) 0;
|
||||
}
|
||||
|
||||
static uint32_t get_hclk(void) {
|
||||
@ -96,7 +94,7 @@ static uint32_t get_hclk(void) {
|
||||
unsigned int src = (rcc->PLLCKSELR & (3 << 0)) >> 0;
|
||||
m = ((rcc->PLLCKSELR & (0x3F << 4)) >> 4);
|
||||
n = ((rcc->PLL1DIVR & (0x1FF << 0)) >> 0) + 1 +
|
||||
((rcc->PLLCFGR & BIT(0)) ? 1 : 0); // round-up in fractional mode
|
||||
((rcc->PLLCFGR & MG_BIT(0)) ? 1 : 0); // round-up in fractional mode
|
||||
p = ((rcc->PLL1DIVR & (0x7F << 9)) >> 9) + 1;
|
||||
if (src == 1) {
|
||||
clk = csi;
|
||||
@ -154,7 +152,7 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
// Init RX descriptors
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
||||
s_rxdesc[i][0] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
|
||||
s_rxdesc[i][3] = BIT(31) | BIT(30) | BIT(24); // OWN, IOC, BUF1V
|
||||
s_rxdesc[i][3] = MG_BIT(31) | MG_BIT(30) | MG_BIT(24); // OWN, IOC, BUF1V
|
||||
}
|
||||
|
||||
// Init TX descriptors
|
||||
@ -162,8 +160,8 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
s_txdesc[i][0] = (uint32_t) (uintptr_t) s_txbuf[i]; // Buf pointer
|
||||
}
|
||||
|
||||
ETH->DMAMR |= BIT(0); // Software reset
|
||||
while ((ETH->DMAMR & BIT(0)) != 0) (void) 0; // Wait until done
|
||||
ETH->DMAMR |= MG_BIT(0); // Software reset
|
||||
while ((ETH->DMAMR & MG_BIT(0)) != 0) (void) 0; // Wait until done
|
||||
|
||||
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
|
||||
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
|
||||
@ -172,12 +170,12 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
// NOTE(scaprile): We do not use timing facilities so the DMA engine does not
|
||||
// re-write buffer address
|
||||
ETH->DMAMR = 0 << 16; // use interrupt mode 0 (58.8.1) (reset value)
|
||||
ETH->DMASBMR |= BIT(12); // AAL NOTE(scaprile): is this actually needed
|
||||
ETH->DMASBMR |= MG_BIT(12); // AAL NOTE(scaprile): is this actually needed
|
||||
ETH->MACIER = 0; // Do not enable additional irq sources (reset value)
|
||||
ETH->MACTFCR = BIT(7); // Disable zero-quanta pause
|
||||
// ETH->MACPFR = BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(12)); // Set autonegotiation
|
||||
ETH->MACTFCR = MG_BIT(7); // Disable zero-quanta pause
|
||||
// ETH->MACPFR = MG_BIT(31); // Receive all
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(15)); // Reset PHY
|
||||
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(12)); // Set autonegotiation
|
||||
ETH->DMACRDLAR =
|
||||
(uint32_t) (uintptr_t) s_rxdesc; // RX descriptors start address
|
||||
ETH->DMACRDRLR = ETH_DESC_CNT - 1; // ring length
|
||||
@ -190,13 +188,13 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
|
||||
ETH->DMACTDTPR =
|
||||
(uint32_t) (uintptr_t) s_txdesc; // first available descriptor address
|
||||
ETH->DMACCR = 0; // DSL = 0 (contiguous descriptor table) (reset value)
|
||||
ETH->DMACIER = BIT(6) | BIT(15); // RIE, NIE
|
||||
ETH->MACCR = BIT(0) | BIT(1) | BIT(13) | BIT(14) |
|
||||
BIT(15); // RE, TE, Duplex, Fast, Reserved
|
||||
ETH->MTLTQOMR |= BIT(1); // TSF
|
||||
ETH->MTLRQOMR |= BIT(5); // RSF
|
||||
ETH->DMACTCR |= BIT(0); // ST
|
||||
ETH->DMACRCR |= BIT(0); // SR
|
||||
ETH->DMACIER = MG_BIT(6) | MG_BIT(15); // RIE, NIE
|
||||
ETH->MACCR = MG_BIT(0) | MG_BIT(1) | MG_BIT(13) | MG_BIT(14) |
|
||||
MG_BIT(15); // RE, TE, Duplex, Fast, Reserved
|
||||
ETH->MTLTQOMR |= MG_BIT(1); // TSF
|
||||
ETH->MTLRQOMR |= MG_BIT(5); // RSF
|
||||
ETH->DMACTCR |= MG_BIT(0); // ST
|
||||
ETH->DMACRCR |= MG_BIT(0); // SR
|
||||
|
||||
// MAC address filtering
|
||||
ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
|
||||
@ -212,7 +210,7 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // Frame is too big
|
||||
} else if ((s_txdesc[s_txno][3] & BIT(31))) {
|
||||
} else if ((s_txdesc[s_txno][3] & MG_BIT(31))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No free descriptors: %u %08X %08X %08X", s_txno,
|
||||
s_txdesc[s_txno][3], ETH->DMACSR, ETH->DMACTCR));
|
||||
@ -221,11 +219,11 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
|
||||
} else {
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][2] = (uint32_t) len; // Set data len
|
||||
s_txdesc[s_txno][3] = BIT(28) | BIT(29); // FD, LD
|
||||
s_txdesc[s_txno][3] |= BIT(31); // Set OWN bit - let DMA take over
|
||||
s_txdesc[s_txno][3] = MG_BIT(28) | MG_BIT(29); // FD, LD
|
||||
s_txdesc[s_txno][3] |= MG_BIT(31); // Set OWN bit - let DMA take over
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
ETH->DMACSR |= BIT(2) | BIT(1); // Clear any prior TBU, TPS
|
||||
ETH->DMACSR |= MG_BIT(2) | MG_BIT(1); // Clear any prior TBU, TPS
|
||||
ETH->DMACTDTPR = (uint32_t) (uintptr_t) &s_txdesc[s_txno]; // and resume
|
||||
return len;
|
||||
(void) ifp;
|
||||
@ -233,18 +231,18 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
|
||||
|
||||
static bool mg_tcpip_driver_stm32h_up(struct mg_tcpip_if *ifp) {
|
||||
uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR);
|
||||
bool up = bsr & BIT(2) ? 1 : 0;
|
||||
bool up = bsr & MG_BIT(2) ? 1 : 0;
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
|
||||
uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR);
|
||||
// tmp = reg with flags set to the most likely situation: 100M full-duplex
|
||||
// if(link is slow or half) set flags otherwise
|
||||
// reg = tmp
|
||||
uint32_t maccr = ETH->MACCR | BIT(14) | BIT(13); // 100M, Full-duplex
|
||||
if ((scsr & BIT(3)) == 0) maccr &= ~BIT(14); // 10M
|
||||
if ((scsr & BIT(4)) == 0) maccr &= ~BIT(13); // Half-duplex
|
||||
uint32_t maccr = ETH->MACCR | MG_BIT(14) | MG_BIT(13); // 100M, Full-duplex
|
||||
if ((scsr & MG_BIT(3)) == 0) maccr &= ~MG_BIT(14); // 10M
|
||||
if ((scsr & MG_BIT(4)) == 0) maccr &= ~MG_BIT(13); // Half-duplex
|
||||
ETH->MACCR = maccr; // IRQ handler does not fiddle with this register
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & BIT(14) ? 100 : 10,
|
||||
maccr & BIT(13) ? "full" : "half"));
|
||||
MG_DEBUG(("Link is %uM %s-duplex", maccr & MG_BIT(14) ? 100 : 10,
|
||||
maccr & MG_BIT(13) ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
@ -252,23 +250,23 @@ static bool mg_tcpip_driver_stm32h_up(struct mg_tcpip_if *ifp) {
|
||||
void ETH_IRQHandler(void);
|
||||
static uint32_t s_rxno;
|
||||
void ETH_IRQHandler(void) {
|
||||
if (ETH->DMACSR & BIT(6)) { // Frame received, loop
|
||||
ETH->DMACSR = BIT(15) | BIT(6); // Clear flag
|
||||
if (ETH->DMACSR & MG_BIT(6)) { // Frame received, loop
|
||||
ETH->DMACSR = MG_BIT(15) | MG_BIT(6); // Clear flag
|
||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if (s_rxdesc[s_rxno][3] & BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][3] & (BIT(28) | BIT(29))) ==
|
||||
(BIT(28) | BIT(29))) &&
|
||||
!(s_rxdesc[s_rxno][3] & BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = s_rxdesc[s_rxno][3] & (BIT(15) - 1);
|
||||
if (s_rxdesc[s_rxno][3] & MG_BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][3] & (MG_BIT(28) | MG_BIT(29))) ==
|
||||
(MG_BIT(28) | MG_BIT(29))) &&
|
||||
!(s_rxdesc[s_rxno][3] & MG_BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = s_rxdesc[s_rxno][3] & (MG_BIT(15) - 1);
|
||||
// MG_DEBUG(("%lx %lu %lx %08lx", s_rxno, len, s_rxdesc[s_rxno][3],
|
||||
// ETH->DMACSR));
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
}
|
||||
s_rxdesc[s_rxno][3] = BIT(31) | BIT(30) | BIT(24); // OWN, IOC, BUF1V
|
||||
s_rxdesc[s_rxno][3] = MG_BIT(31) | MG_BIT(30) | MG_BIT(24); // OWN, IOC, BUF1V
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
ETH->DMACSR = BIT(7) | BIT(8); // Clear possible RBU RPS while processing
|
||||
ETH->DMACSR = MG_BIT(7) | MG_BIT(8); // Clear possible RBU RPS while processing
|
||||
ETH->DMACRDTPR =
|
||||
(uint32_t) (uintptr_t) &s_rxdesc[ETH_DESC_CNT - 1]; // and resume RX
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ struct tm4c_emac {
|
||||
#undef EMAC
|
||||
#define EMAC ((struct tm4c_emac *) (uintptr_t) 0x400EC000)
|
||||
|
||||
#undef BIT
|
||||
#define BIT(x) ((uint32_t) 1 << (x))
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
@ -49,17 +47,17 @@ static inline void tm4cspin(volatile uint32_t count) {
|
||||
static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
|
||||
EMAC->EMACMIIADDR &= (0xf << 2);
|
||||
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
|
||||
EMAC->EMACMIIADDR |= BIT(0);
|
||||
while (EMAC->EMACMIIADDR & BIT(0)) tm4cspin(1);
|
||||
EMAC->EMACMIIADDR |= MG_BIT(0);
|
||||
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
|
||||
return EMAC->EMACMIIDATA;
|
||||
}
|
||||
|
||||
static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
|
||||
EMAC->EMACMIIDATA = val;
|
||||
EMAC->EMACMIIADDR &= (0xf << 2);
|
||||
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | BIT(1);
|
||||
EMAC->EMACMIIADDR |= BIT(0);
|
||||
while (EMAC->EMACMIIADDR & BIT(0)) tm4cspin(1);
|
||||
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
|
||||
EMAC->EMACMIIADDR |= MG_BIT(0);
|
||||
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
|
||||
}
|
||||
|
||||
static uint32_t get_sysclk(void) {
|
||||
@ -135,8 +133,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// Init RX descriptors
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
||||
s_rxdesc[i][0] = BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][0] = MG_BIT(31); // Own
|
||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained
|
||||
s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
|
||||
s_rxdesc[i][3] =
|
||||
(uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
@ -150,8 +148,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
|
||||
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
||||
}
|
||||
|
||||
EMAC->EMACDMABUSMOD |= BIT(0); // Software reset
|
||||
while ((EMAC->EMACDMABUSMOD & BIT(0)) != 0) tm4cspin(1); // Wait until done
|
||||
EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
|
||||
while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) tm4cspin(1); // Wait until done
|
||||
|
||||
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
|
||||
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
|
||||
@ -159,19 +157,19 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
|
||||
|
||||
// NOTE(cpq): we do not use extended descriptor bit 7, and do not use
|
||||
// hardware checksum. Therefore, descriptor size is 4, not 8
|
||||
// EMAC->EMACDMABUSMOD = BIT(13) | BIT(16) | BIT(22) | BIT(23) | BIT(25);
|
||||
EMAC->EMACIM = BIT(3) | BIT(9); // Mask timestamp & PMT IT
|
||||
EMAC->EMACFLOWCTL = BIT(7); // Disable zero-quanta pause
|
||||
// EMAC->EMACFRAMEFLTR = BIT(31); // Receive all
|
||||
// EMAC->EMACDMABUSMOD = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) | MG_BIT(25);
|
||||
EMAC->EMACIM = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
|
||||
EMAC->EMACFLOWCTL = MG_BIT(7); // Disable zero-quanta pause
|
||||
// EMAC->EMACFRAMEFLTR = MG_BIT(31); // Receive all
|
||||
// EMAC->EMACPC defaults to internal PHY (EPHY) in MMI mode
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, BIT(15)); // Reset internal PHY (EPHY)
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, BIT(12)); // Set autonegotiation
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(15)); // Reset internal PHY (EPHY)
|
||||
emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(12)); // Set autonegotiation
|
||||
EMAC->EMACRXDLADDR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
|
||||
EMAC->EMACTXDLADDR = (uint32_t) (uintptr_t) s_txdesc; // TX descriptors
|
||||
EMAC->EMACDMAIM = BIT(6) | BIT(16); // RIE, NIE
|
||||
EMAC->EMACCFG = BIT(2) | BIT(3) | BIT(11) | BIT(14); // RE, TE, Duplex, Fast
|
||||
EMAC->EMACDMAIM = MG_BIT(6) | MG_BIT(16); // RIE, NIE
|
||||
EMAC->EMACCFG = MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast
|
||||
EMAC->EMACDMAOPMODE =
|
||||
BIT(1) | BIT(13) | BIT(21) | BIT(25); // SR, ST, TSF, RSF
|
||||
MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
|
||||
EMAC->EMACADDR0H = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
|
||||
EMAC->EMACADDR0L = (uint32_t) (ifp->mac[3] << 24) |
|
||||
((uint32_t) ifp->mac[2] << 16) |
|
||||
@ -187,7 +185,7 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // fail
|
||||
} else if ((s_txdesc[s_txno][0] & BIT(31))) {
|
||||
} else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No descriptors available"));
|
||||
// printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long)
|
||||
@ -197,11 +195,11 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
s_txdesc[s_txno][1] = (uint32_t) len; // Set data len
|
||||
s_txdesc[s_txno][0] =
|
||||
BIT(20) | BIT(28) | BIT(29) | BIT(30); // Chain,FS,LS,IC
|
||||
s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over
|
||||
MG_BIT(20) | MG_BIT(28) | MG_BIT(29) | MG_BIT(30); // Chain,FS,LS,IC
|
||||
s_txdesc[s_txno][0] |= MG_BIT(31); // Set OWN bit - let DMA take over
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
EMAC->EMACDMARIS = BIT(2) | BIT(5); // Clear any prior TU/UNF
|
||||
EMAC->EMACDMARIS = MG_BIT(2) | MG_BIT(5); // Clear any prior TU/UNF
|
||||
EMAC->EMACTXPOLLD = 0; // and resume
|
||||
return len;
|
||||
(void) ifp;
|
||||
@ -209,18 +207,18 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
|
||||
|
||||
static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) {
|
||||
uint32_t bmsr = emac_read_phy(EPHY_ADDR, EPHYBMSR);
|
||||
bool up = (bmsr & BIT(2)) ? 1 : 0;
|
||||
bool up = (bmsr & MG_BIT(2)) ? 1 : 0;
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
|
||||
uint32_t sts = emac_read_phy(EPHY_ADDR, EPHYSTS);
|
||||
// tmp = reg with flags set to the most likely situation: 100M full-duplex
|
||||
// if(link is slow or half) set flags otherwise
|
||||
// reg = tmp
|
||||
uint32_t emaccfg = EMAC->EMACCFG | BIT(14) | BIT(11); // 100M, Full-duplex
|
||||
if (sts & BIT(1)) emaccfg &= ~BIT(14); // 10M
|
||||
if ((sts & BIT(2)) == 0) emaccfg &= ~BIT(11); // Half-duplex
|
||||
uint32_t emaccfg = EMAC->EMACCFG | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex
|
||||
if (sts & MG_BIT(1)) emaccfg &= ~MG_BIT(14); // 10M
|
||||
if ((sts & MG_BIT(2)) == 0) emaccfg &= ~MG_BIT(11); // Half-duplex
|
||||
EMAC->EMACCFG = emaccfg; // IRQ handler does not fiddle with this register
|
||||
MG_DEBUG(("Link is %uM %s-duplex", emaccfg & BIT(14) ? 100 : 10,
|
||||
emaccfg & BIT(11) ? "full" : "half"));
|
||||
MG_DEBUG(("Link is %uM %s-duplex", emaccfg & MG_BIT(14) ? 100 : 10,
|
||||
emaccfg & MG_BIT(11) ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
@ -228,22 +226,22 @@ static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) {
|
||||
void EMAC0_IRQHandler(void);
|
||||
static uint32_t s_rxno;
|
||||
void EMAC0_IRQHandler(void) {
|
||||
if (EMAC->EMACDMARIS & BIT(6)) { // Frame received, loop
|
||||
EMAC->EMACDMARIS = BIT(16) | BIT(6); // Clear flag
|
||||
if (EMAC->EMACDMARIS & MG_BIT(6)) { // Frame received, loop
|
||||
EMAC->EMACDMARIS = MG_BIT(16) | MG_BIT(6); // Clear flag
|
||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if (s_rxdesc[s_rxno][0] & BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (BIT(8) | BIT(9))) == (BIT(8) | BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (BIT(14) - 1));
|
||||
if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done
|
||||
if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) == (MG_BIT(8) | MG_BIT(9))) &&
|
||||
!(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames
|
||||
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1));
|
||||
// printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
|
||||
// EMAC->EMACDMARIS);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
}
|
||||
s_rxdesc[s_rxno][0] = BIT(31);
|
||||
s_rxdesc[s_rxno][0] = MG_BIT(31);
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
EMAC->EMACDMARIS = BIT(7); // Clear possible RU while processing
|
||||
EMAC->EMACDMARIS = MG_BIT(7); // Clear possible RU while processing
|
||||
EMAC->EMACRXPOLLD = 0; // and resume RX
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user