Skip to content

Commit

Permalink
Added Infineon XMC44/47 examples
Browse files Browse the repository at this point in the history
  • Loading branch information
robert committed Mar 22, 2024
1 parent f58b90f commit 8f2eb1f
Show file tree
Hide file tree
Showing 5 changed files with 509 additions and 27 deletions.
212 changes: 212 additions & 0 deletions mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -16054,3 +16054,215 @@ static bool w5500_up(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver mg_tcpip_driver_w5500 = {w5500_init, w5500_tx, w5500_rx,
w5500_up};
#endif

#ifdef MG_ENABLE_LINES
#line 1 "src/drivers/xmc.c"
#endif


#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC

#ifdef XMC4400_F100x512
#include <XMC4400.h>
#else
#ifdef XMC4700_F144x2048
#include <XMC4700.h>
#endif
#endif

#ifndef ETH0
#define ETH0 ((volatile ETH_GLOBAL_TypeDef*) 0x5000C000UL)
#endif

#define ETH_PKT_SIZE 1536 // Max frame size
#define ETH_DESC_CNT 4 // Descriptors count
#define ETH_DS 4 // Descriptor size (words)

static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
static uint8_t s_txno; // Current TX descriptor
static uint8_t s_rxno; // Current RX descriptor

static struct mg_tcpip_if *s_ifp; // MIP interface
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };

static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk) |
ETH_GMII_ADDRESS_MB_Msk |
((uint32_t)addr << ETH_GMII_ADDRESS_PA_Pos) |
((uint32_t)reg << ETH_GMII_ADDRESS_MR_Pos);
while ((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0) (void) 0;
return (uint16_t)(ETH0->GMII_DATA & ETH_GMII_DATA_MD_Msk);
}

static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
ETH0->GMII_DATA = val;
ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk) |
ETH_GMII_ADDRESS_MB_Msk |
ETH_GMII_ADDRESS_MW_Msk |
((uint32_t)addr << ETH_GMII_ADDRESS_PA_Pos) |
((uint32_t)reg << ETH_GMII_ADDRESS_MR_Pos);
while ((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0) (void) 0;
}

static uint32_t get_clock_rate(struct mg_tcpip_driver_xmc_data *d) {
// assume ETH clock is 60MHz
// then according to 13.2.8.1, we need to set value 3
(void) d;
return 3;
}

static bool mg_tcpip_driver_xmc_init(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_xmc_data *d =
(struct mg_tcpip_driver_xmc_data *) ifp->driver_data;
s_ifp = ifp;

// reset MAC
ETH0->BUS_MODE |= 1;
while (ETH0->BUS_MODE & 1) (void) 0;

// set clock rate
ETH0->GMII_ADDRESS = get_clock_rate(d) << ETH_GMII_ADDRESS_CR_Pos;

// init phy
eth_write_phy(MG_PHY_ADDR, MG_PHYREG_BCR, 0x8000); // reset
uint8_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
while ((bcr & 0x8000) != 0) {
bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
}

// auto-negotiation, 100M, full-duplex
eth_write_phy(MG_PHY_ADDR, MG_PHYREG_BCR, 0x3100);

ETH0->MAC_CONFIGURATION = ETH_MAC_CONFIGURATION_DO_Msk | ETH_MAC_CONFIGURATION_DM_Msk |
ETH_MAC_CONFIGURATION_FES_Msk | ETH_MAC_CONFIGURATION_TC_Msk;

// set the MAC address
ETH0->MAC_ADDRESS0_HIGH = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
ETH0->MAC_ADDRESS0_LOW =
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);

// Configure the receive filter
ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk | ETH_MAC_FRAME_FILTER_HMC_Msk;
// Disable flow control
ETH0->FLOW_CONTROL = 0;
// Enable store and forward mode
ETH0->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk;

// Configure DMA bus mode
ETH0->BUS_MODE = ETH_BUS_MODE_AAL_Msk | ETH_BUS_MODE_USP_Msk |
(32 << ETH_BUS_MODE_RPBL_Pos) | (32 << ETH_BUS_MODE_PBL_Pos);

// init RX descriptors
for (int i = 0; i < ETH_DESC_CNT; i++) {
s_rxdesc[i][0] = MG_BIT(31); // OWN descriptor
//s_rxdesc[i][1] = MG_BIT(24) | ETH_PKT_SIZE; // chained descriptors
s_rxdesc[i][1] = MG_BIT(14) | ETH_PKT_SIZE;
s_rxdesc[i][2] = (uint32_t) s_rxbuf[i];
if (i == ETH_DESC_CNT - 1) {
s_rxdesc[i][3] = (uint32_t) &s_rxdesc[0][0];
} else {
s_rxdesc[i][3] = (uint32_t) &s_rxdesc[i + 1][0];
}
}
ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_rxdesc[0][0];

// init TX descriptors
for (int i = 0; i < ETH_DESC_CNT; i++) {
s_txdesc[i][0] = MG_BIT(30) | MG_BIT(20);
s_txdesc[i][2] = (uint32_t) s_txbuf[i];
if (i == ETH_DESC_CNT - 1) {
s_txdesc[i][3] = (uint32_t) &s_txdesc[0][0];
} else {
s_txdesc[i][3] = (uint32_t) &s_txdesc[i + 1][0];
}
}
ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_txdesc[0][0];

// Clear interrupts
ETH0->STATUS = 0xFFFFFFFF;

// Disable MAC interrupts
ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF;
ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
ETH0->INTERRUPT_MASK = ETH_INTERRUPT_MASK_TSIM_Msk | ETH_INTERRUPT_MASK_PMTIM_Msk;

//Enable interrupts
ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk |
ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk;

// Enable MAC transmission and reception
ETH0->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk | ETH_MAC_CONFIGURATION_RE_Msk;
// Enable DMA transmission and reception
ETH0->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk | ETH_OPERATION_MODE_SR_Msk;

NVIC_EnableIRQ(ETH0_0_IRQn);
return true;
}

static size_t mg_tcpip_driver_xmc_tx(const void *buf, size_t len,
struct mg_tcpip_if *ifp) {
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] & MG_BIT(31))) {
ifp->nerr++;
MG_ERROR(("No free descriptors"));
len = 0; // All descriptors are busy, fail
} else {
memcpy(s_txbuf[s_txno], buf, len);
s_txdesc[s_txno][1] = len;
s_txdesc[s_txno][0] = MG_BIT(29) /* Last frame */ |
MG_BIT(28) /* First frame */ | MG_BIT(30) /* Interrupt on send */ |
MG_BIT(20) /* Chained descriptors */;
s_txdesc[s_txno][0] |= MG_BIT(31); // OWN bit: handle control to DMA
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
}

// Resume processing
ETH0->STATUS = ETH_STATUS_TU_Msk;
ETH0->TRANSMIT_POLL_DEMAND = 0;
return len;
}

static bool mg_tcpip_driver_xmc_up(struct mg_tcpip_if *ifp) {
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
bool up = bsr & MG_BIT(2) ? 1 : 0;
(void) ifp;
return up;
}

void ETH0_IRQHandler(void);
void ETH0_IRQHandler(void) {
uint32_t irq_status = ETH0->STATUS;
if (irq_status & ETH_STATUS_RI_Msk) {
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) == 0) {
size_t len = (s_rxdesc[s_rxno][0] & 0x3fff0000) >> 16;
mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
s_rxdesc[s_rxno][0] = MG_BIT(31); // OWN bit: handle control to DMA
// Resume processing
ETH0->STATUS = ETH_STATUS_RU_Msk | ETH_STATUS_RI_Msk;
ETH0->RECEIVE_POLL_DEMAND = 0;
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
}
}
ETH0->STATUS = ETH_STATUS_RI_Msk;
}

if (irq_status & ETH_STATUS_TI_Msk) {
ETH0->STATUS = ETH_STATUS_TI_Msk;
}

if (irq_status & ETH_STATUS_NIS_Msk) {
ETH0->STATUS = ETH_STATUS_NIS_Msk;
}
}

struct mg_tcpip_driver mg_tcpip_driver_xmc = {
mg_tcpip_driver_xmc_init, mg_tcpip_driver_xmc_tx, NULL,
mg_tcpip_driver_xmc_up};
#endif
81 changes: 54 additions & 27 deletions mongoose.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,30 +254,30 @@ static inline int mg_mkdir(const char *path, mode_t mode) {
#include <pico/stdlib.h>
int mkdir(const char *, mode_t);
#endif


#if MG_ARCH == MG_ARCH_RTTHREAD

#include <rtthread.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

#ifndef MG_IO_SIZE
#define MG_IO_SIZE 1460
#endif

#endif // MG_ARCH == MG_ARCH_RTTHREAD


#if MG_ARCH == MG_ARCH_RTTHREAD

#include <rtthread.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

#ifndef MG_IO_SIZE
#define MG_IO_SIZE 1460
#endif

#endif // MG_ARCH == MG_ARCH_RTTHREAD


#if MG_ARCH == MG_ARCH_ARMCC || MG_ARCH == MG_ARCH_CMSIS_RTOS1 || \
Expand Down Expand Up @@ -2794,6 +2794,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_imxrt;
extern struct mg_tcpip_driver mg_tcpip_driver_same54;
extern struct mg_tcpip_driver mg_tcpip_driver_cmsis;
extern struct mg_tcpip_driver mg_tcpip_driver_ra;
extern struct mg_tcpip_driver mg_tcpip_driver_xmc;

// Drivers that require SPI, can use this SPI abstraction
struct mg_tcpip_spi {
Expand Down Expand Up @@ -3081,10 +3082,36 @@ struct mg_tcpip_driver_tm4c_data {
#endif


#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_W5500) && MG_ENABLE_DRIVER_W5500
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC

#undef MG_ENABLE_TCPIP_DRIVER_INIT
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
struct mg_tcpip_driver_xmc_data {
int mdc_cr;
uint8_t phy_addr;
};

#ifndef MG_TCPIP_PHY_ADDR
#define MG_TCPIP_PHY_ADDR 0
#endif

#ifndef MG_DRIVER_MDC_CR
#define MG_DRIVER_MDC_CR 4
#endif

#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_xmc_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_xmc; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: xmc, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)

#endif

Expand Down
Loading

0 comments on commit 8f2eb1f

Please sign in to comment.