mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-03 13:28:44 +00:00
Add support for RA6M4
This commit is contained in:
1 parent
52997c6c51
commit
a027f58744
11 files changed
+765
-85
No files matched your search
@@ -4,14 +4,11 @@ CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
|
||||
CFLAGS += -I. -Icmsis_core/CMSIS/Core/Include
|
||||
CFLAGS += -Icmsis_mcu/ra/fsp/src/bsp/cmsis/Device/RENESAS/Include
|
||||
CFLAGS += -Icmsis_mcu/ra/fsp/src/bsp/mcu/all
|
||||
#CFLAGS += -Icmsis_mcu/ra/fsp/inc
|
||||
#CFLAGS += -Icmsis_mcu/ra/fsp/inc/api
|
||||
CFLAGS += -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard $(CFLAGS_EXTRA)
|
||||
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
|
||||
|
||||
SOURCES = main.c hal.c mongoose.c net.c packed_fs.c
|
||||
#SOURCES += cmsis_mcu/Files/startup_RA.c
|
||||
#SOURCES += cmsis_mcu/Files/system_RA.c
|
||||
# CMSIS startup and system files are deeply tied to the BSP, and we don't use it. See hal.c
|
||||
|
||||
# Example specific build options. See README.md
|
||||
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\"
|
||||
@@ -42,11 +39,11 @@ cmsis_mcu:
|
||||
|
||||
|
||||
# Automated remote test. Requires env variable VCON_API_KEY set. See https://vcon.io/automated-firmware-tests/
|
||||
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/13
|
||||
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/14
|
||||
update: firmware.bin
|
||||
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$<
|
||||
|
||||
update: CFLAGS += -DUART_DEBUG=LPUART3
|
||||
update: CFLAGS += -DUART_DEBUG=R_SCI7
|
||||
|
||||
test: update
|
||||
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt
|
||||
|
||||
@@ -13,11 +13,12 @@ static volatile uint64_t s_ticks; // Milliseconds since boot
|
||||
extern void _estack(void); // Defined in link.ld
|
||||
void Reset_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
extern void EDMAC_IRQHandler(void);
|
||||
|
||||
// 16 ARM and 200 peripheral handlers
|
||||
__attribute__((section(".vectors"))) void (*const tab[16 + 10])(void) = {
|
||||
_estack, Reset_Handler, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, SysTick_Handler};
|
||||
_estack, Reset_Handler, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
SysTick_Handler, EDMAC_IRQHandler};
|
||||
|
||||
void Reset_Handler(void) {
|
||||
extern long _sbss[], _ebss[], _sdata[], _edata[], _sidata[];
|
||||
@@ -33,8 +34,11 @@ void Reset_Handler(void) {
|
||||
}
|
||||
|
||||
void SystemInit(void) { // Called automatically by startup code
|
||||
clock_init(); // Set system clock to SYS_FREQUENCY
|
||||
rng_init(); // Initialise random number generator
|
||||
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
|
||||
__DSB();
|
||||
__ISB();
|
||||
clock_init(); // Set system clock to SYS_FREQUENCY
|
||||
rng_init(); // Initialise random number generator
|
||||
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
|
||||
}
|
||||
|
||||
@@ -42,12 +46,14 @@ void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
|
||||
s_ticks++;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void mg_random(void *buf, size_t len) { // Use on-board RNG
|
||||
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
|
||||
uint32_t r = rng_read();
|
||||
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t mg_millis(void) { // Let Mongoose use our uptime function
|
||||
return s_ticks; // Return number of milliseconds since boot
|
||||
|
||||
@@ -16,30 +16,66 @@
|
||||
|
||||
extern void hal_init(void);
|
||||
|
||||
#define LED1 PIN('E', 15)
|
||||
#define LED2 PIN('E', 4)
|
||||
#define LED3 PIN('E', 0)
|
||||
#define UART_DEBUG R_SCI0
|
||||
#define UART_TX PIN('G', 13)
|
||||
#define UART_RX PIN('G', 12)
|
||||
|
||||
#define BIT(x) (1UL << (x))
|
||||
#define CLRSET(reg, clear, set) ((reg) = ((reg) & ~(clear)) | (set))
|
||||
#define PIN(port, num) ((((port) - 'A') << 8) | (num))
|
||||
#define SETBITS(reg, clear, set) ((reg) = ((reg) & ~(clear)) | (set))
|
||||
#define PIN(port, num) ((((port) - '0') << 8) | (num))
|
||||
#define PIN_NUM(pin) (pin & 255)
|
||||
#define PIN_PORT(pin) (pin >> 8)
|
||||
|
||||
// No-op HAL API implementation for a device with GPIO and UART
|
||||
#define LED1 PIN('4', 15) // blue
|
||||
#define LED2 PIN('4', 4) // green
|
||||
#define LED3 PIN('4', 0) // red
|
||||
#define LED LED2 // Use green LED for blinking
|
||||
|
||||
#define rng_read() 0
|
||||
#define rng_init()
|
||||
#define uart_read_ready(uart) 0
|
||||
#define GENERATE_MAC_ADDRESS() \
|
||||
{ 2, 3, 4, 5, 6, 7 }
|
||||
|
||||
// Clock
|
||||
#define SYS_FREQUENCY 2000000
|
||||
// Board UM: P212 P213 24MHz xtal
|
||||
// - (8.1 Table 8.1) (50.3.1 Table 50.14): PLL 120 ~ 200 MHz; input 8 ~ 24 MHz.
|
||||
// System clock (ICLK) <= 200 MHz; PCLKA <= 100 MHz; PCLKB <= 50 MHz
|
||||
// - (8.2.2): ICLK >= other clocks of interest for us
|
||||
// - (8.7.3): FlashIF Clock (FCLK) (8.1 Table 8.1): 4 MHz to 50 MHz(P/E), up to
|
||||
// 50 MHz (R)
|
||||
// - (8.2.9): MOSCCR Set the PRCR.PRC0 bit to 1 (write enabled) before rewriting
|
||||
// this register.
|
||||
// - (10.2.9) OPCCR : Operating Power Control Register, defaults to high-speed
|
||||
// mode
|
||||
// - (45.2.4) 1 wait state for SRAM (default);
|
||||
#define SYS_FREQUENCY 200000000
|
||||
#define PLL_MUL 49 // x25 ((n+1)/2)
|
||||
#define PLL_DIV 2 // /3 (n+1)
|
||||
#define ICLK_DIV 0 // /1 -> 200MHz (/(2^n))
|
||||
#define FCLK_DIV 2 // /4 -> 50MHz
|
||||
#define PCLKAD_DIV 1 // /2 -> 100MHz
|
||||
#define PCLKBC_DIV 2 // /4 -> 50MHz
|
||||
#define FLASH_MHZ (SYS_FREQUENCY / ((1 << FCLK_DIV) * 1000000))
|
||||
static inline void clock_init(void) {
|
||||
SCB->CPACR = (uint32_t) 15U << 20;
|
||||
R_SYSTEM->PRCR = 0xA501; // enable writing to osc control regs (12.2.1)
|
||||
R_SYSTEM->MOSCWTCR = 9; // (8.2.5, 8.2.4)
|
||||
R_SYSTEM->MOSCCR = 0; // enable main oscillator, default cfg (20~24MHz)
|
||||
while (R_SYSTEM->OSCSF_b.MOSCSF == 0) (void) 0; // wait until it stabilizes
|
||||
R_SYSTEM->PLLCCR =
|
||||
(PLL_MUL << R_SYSTEM_PLLCCR_PLLMUL_Pos) |
|
||||
(PLL_DIV
|
||||
<< R_SYSTEM_PLLCCR_PLIDIV_Pos); // config PLL for MOSC /3 x 25 (8.2.4)
|
||||
R_SYSTEM->PLLCR = 0; // enable PLL
|
||||
R_SYSTEM->SCKDIVCR =
|
||||
(FCLK_DIV << R_SYSTEM_SCKDIVCR_FCK_Pos) |
|
||||
(ICLK_DIV << R_SYSTEM_SCKDIVCR_ICK_Pos) |
|
||||
(PCLKAD_DIV << R_SYSTEM_SCKDIVCR_BCK_Pos) |
|
||||
(PCLKAD_DIV << R_SYSTEM_SCKDIVCR_PCKA_Pos) |
|
||||
(PCLKBC_DIV << R_SYSTEM_SCKDIVCR_PCKB_Pos) |
|
||||
(PCLKBC_DIV << R_SYSTEM_SCKDIVCR_PCKC_Pos) |
|
||||
(PCLKAD_DIV << R_SYSTEM_SCKDIVCR_PCKD_Pos); // set dividers
|
||||
R_FCACHE->FLWT = 3; // flash: 3 wait states (47.4.3)
|
||||
R_FLAD->FCKMHZ = FLASH_MHZ; // flash: read speed optimization (47.4.28)
|
||||
R_FACI_HP->FPCKAR = (0x1E << 8) + FLASH_MHZ; // flash: write (47.4.26)
|
||||
while (R_SYSTEM->OSCSF_b.PLLSF == 0) (void) 0; // PLL stabilization
|
||||
while (R_FLAD->FCKMHZ != FLASH_MHZ) (void) 0; // flash module magic
|
||||
R_SYSTEM->SCKSCR = 5; // select PLL (8.2.3)
|
||||
}
|
||||
|
||||
// GPIO
|
||||
@@ -48,12 +84,22 @@ enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF };
|
||||
|
||||
static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t af) {
|
||||
R_PORT0_Type *gpio = GPIO(PIN_PORT(pin));
|
||||
|
||||
if (mode == GPIO_MODE_OUTPUT) {
|
||||
gpio->PCNTR1 |= BIT(PIN_NUM(pin));
|
||||
} else if (mode == GPIO_MODE_INPUT) {
|
||||
gpio->PCNTR1 &= ~BIT(PIN_NUM(pin));
|
||||
} else {
|
||||
(void) af;
|
||||
} else { // GPIO_MODE_AF
|
||||
// TODO(): only non-analog supported (19.2.5)
|
||||
R_PMISC->PWPR_b.B0WI = 0; // (19.5.1--> (RM says this is PFS...)
|
||||
R_PMISC->PWPR_b.PFSWE = 1;
|
||||
R_PFS->PORT[PIN_PORT(pin)].PIN[PIN_NUM(pin)].PmnPFS_b.PMR = 0;
|
||||
R_PFS->PORT[PIN_PORT(pin)].PIN[PIN_NUM(pin)].PmnPFS_b.PSEL =
|
||||
af & (R_PFS_PORT_PIN_PmnPFS_PSEL_Msk >> R_PFS_PORT_PIN_PmnPFS_PSEL_Pos);
|
||||
R_PFS->PORT[PIN_PORT(pin)].PIN[PIN_NUM(pin)].PmnPFS_b.PMR = 1;
|
||||
R_PFS->PORT[PIN_PORT(pin)].PIN[PIN_NUM(pin)].PmnPFS_b.DSCR = 2; // high
|
||||
R_PMISC->PWPR_b.PFSWE = 0;
|
||||
R_PMISC->PWPR_b.B0WI = 1; // <--19.5.1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,49 +125,78 @@ static inline void gpio_toggle(uint16_t pin) {
|
||||
gpio_write(pin, !gpio_read(pin));
|
||||
}
|
||||
|
||||
#ifndef UART_DEBUG
|
||||
#define UART_DEBUG R_SCI7
|
||||
#endif
|
||||
#define UART_TX PIN('6', 13) // SCI7
|
||||
#define UART_RX PIN('6', 14)
|
||||
|
||||
// UART
|
||||
// (datasheet, after BSP rev.eng.) SCI uses PCLKA in this chip
|
||||
static inline void uart_init(R_SCI0_Type *uart, unsigned baud) {
|
||||
gpio_output(UART_TX);
|
||||
gpio_input(UART_RX);
|
||||
if (uart != R_SCI7) return;
|
||||
R_MSTP->MSTPCRB_b.MSTPB24 = 0; // enable SCI7
|
||||
(void) R_MSTP->MSTPCRB; // (10.10.15)
|
||||
uart->SCR = 0; // (29.3.7 -->) disable SCI
|
||||
uart->FCR_b.FM = 0; // disable FIFO
|
||||
uart->SIMR1 = 0; // disable I2C (default)
|
||||
uart->SPMR = 0; // disable SPI (default)
|
||||
uart->SCMR_b.SMIF = 0; // no smartcard (default)
|
||||
uart->SMR = 0; // async 8N1, use PCLK
|
||||
uart->SCMR_b.CHR1 = 1; // disable 9-bit mode (default)
|
||||
uart->SEMR = 0; // 16x clocking (other SCIs need internal clock setting)
|
||||
uart->SPTR = 3; // no inversions, high on idle
|
||||
uart->BRR = (uint8_t) (SYS_FREQUENCY / (32 * (1 << PCLKAD_DIV) * baud));
|
||||
gpio_init(UART_TX, GPIO_MODE_AF, 5); // (19.6)
|
||||
gpio_init(UART_RX, GPIO_MODE_AF, 5);
|
||||
(void) uart, (void) baud;
|
||||
uart->SCR = R_SCI0_SCR_TE_Msk | R_SCI0_SCR_RE_Msk; // enable Tx, Rx
|
||||
}
|
||||
|
||||
static inline void uart_write_byte(void *uart, uint8_t byte) {
|
||||
uint16_t pin = UART_TX;
|
||||
uint32_t baud = 9600;
|
||||
uint32_t interval = SYS_FREQUENCY / baud; // Time to send 1 bit
|
||||
uint8_t bits[] = {
|
||||
0, // Start bit
|
||||
(byte >> 0) & 1U,
|
||||
(byte >> 1) & 1U,
|
||||
(byte >> 2) & 1U,
|
||||
(byte >> 3) & 1U,
|
||||
(byte >> 4) & 1U,
|
||||
(byte >> 5) & 1U,
|
||||
(byte >> 6) & 1U,
|
||||
(byte >> 7) & 1U,
|
||||
1, // Stop bit
|
||||
};
|
||||
uint32_t t = SysTick->VAL; // Current timer value
|
||||
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
gpio_write(pin, bits[i]);
|
||||
if (t <= interval) {
|
||||
while (SysTick->VAL <= t) (void) 0;
|
||||
t = SysTick->LOAD + 1 - interval;
|
||||
while (SysTick->VAL > t) (void) 0;
|
||||
} else {
|
||||
t -= interval;
|
||||
while (SysTick->VAL > t) (void) 0;
|
||||
}
|
||||
}
|
||||
(void) uart;
|
||||
static inline void uart_write_byte(R_SCI0_Type *uart, uint8_t byte) {
|
||||
uart->TDR = byte;
|
||||
while (uart->SSR_b.TDRE == 0) (void) 0;
|
||||
}
|
||||
|
||||
static inline void uart_write_buf(void *uart, char *buf, size_t len) {
|
||||
static inline void uart_write_buf(R_SCI0_Type *uart, char *buf, size_t len) {
|
||||
while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++);
|
||||
}
|
||||
|
||||
static inline int uart_read_ready(R_SCI0_Type *uart) {
|
||||
return uart->SSR_b.RDRF; // If RDRF bit is set, data is ready
|
||||
}
|
||||
static inline uint8_t uart_read_byte(R_SCI0_Type *uart) {
|
||||
return uart->RDR;
|
||||
}
|
||||
|
||||
// Ethernet
|
||||
// - (13.3.2 Table 13.4) Event table: Event 0x16F, ETHER_EINT0
|
||||
// - (13.1) ICU (13.3.1) Interrupt Vector Table (13.5)
|
||||
// - Choose a IELSRx, that is IRQn=x in NVIC, write event number
|
||||
static inline void ethernet_init(void) {
|
||||
R_MSTP->MSTPCRB_b.MSTPB15 = 0; // enable ETHERC0 and EDMAC0
|
||||
(void) R_MSTP->MSTPCRB; // (10.10.15)
|
||||
// (Board manual: 4.3.3 Table 1, 6.1 Table 20) (RM: 19.6)
|
||||
R_SYSTEM->PRCR = 0xA502; // enable writing to next reg (12.2.1)
|
||||
R_SYSTEM->VBTICTLR = 0; // enable MDC pins (19.5.5) (11.2.6)
|
||||
gpio_init(PIN('4', 1), GPIO_MODE_AF, 0x17); // MDC
|
||||
gpio_init(PIN('4', 2), GPIO_MODE_AF, 0x17); // MDIO
|
||||
gpio_output(PIN('4', 3)); // PHY RST
|
||||
gpio_write(PIN('0', 2), 1); // prevent NAND_TREE
|
||||
gpio_write(PIN('4', 3), 0); // assert RST
|
||||
gpio_init(PIN('4', 5), GPIO_MODE_AF, 0x17); // TX_EN
|
||||
gpio_init(PIN('4', 6), GPIO_MODE_AF, 0x17); // TXD1
|
||||
gpio_init(PIN('7', 0), GPIO_MODE_AF, 0x17); // TXD0
|
||||
gpio_init(PIN('7', 1), GPIO_MODE_AF, 0x17); // REF50CK0
|
||||
gpio_init(PIN('7', 2), GPIO_MODE_AF, 0x17); // RXD0
|
||||
gpio_init(PIN('7', 3), GPIO_MODE_AF, 0x17); // RXD1
|
||||
gpio_init(PIN('7', 4), GPIO_MODE_AF, 0x17); // RX_ER
|
||||
gpio_init(PIN('7', 5), GPIO_MODE_AF, 0x17); // CRS_DV
|
||||
R_PMISC->PFENET_b.PHYMODE0 = 0; // select RMII
|
||||
for (volatile int i = 0; i < 0x2000; i++)
|
||||
(void) 0; // keep PHY RST low for a while
|
||||
gpio_write(PIN('4', 3), 1); // deassert RST
|
||||
gpio_input(PIN('0', 2)); // PHY IRQ, not used
|
||||
NVIC_EnableIRQ(0); // (13.5.1) no CMSIS support
|
||||
R_ICU->IELSR[0] = 0x16f; // (13.2.15)(13.5.4.1)
|
||||
}
|
||||
@@ -8,15 +8,12 @@
|
||||
#define BLINK_PERIOD_MS 1000 // LED blinking period in millis
|
||||
|
||||
static void timer_fn(void *arg) {
|
||||
gpio_toggle(LED2); // Blink LED
|
||||
#if 0
|
||||
gpio_toggle(LED); // Blink LED
|
||||
struct mg_tcpip_if *ifp = arg; // And show
|
||||
const char *names[] = {"down", "up", "req", "ready"}; // network stats
|
||||
MG_INFO(("Ethernet: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
|
||||
names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
|
||||
ifp->ndrop, ifp->nerr));
|
||||
#endif
|
||||
(void) arg;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -27,19 +24,19 @@ int main(void) {
|
||||
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||
|
||||
MG_INFO(("Starting, CPU freq %g MHz", (double) SystemCoreClock / 1000000));
|
||||
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mgr);
|
||||
|
||||
#if 0
|
||||
|
||||
// Initialise Mongoose network stack
|
||||
struct mg_tcpip_driver_stm32h_data driver_data = {.mdc_cr = 4};
|
||||
struct mg_tcpip_if mif = {.mac = GENERATE_MAC_ADDRESS(),
|
||||
struct mg_tcpip_driver_ra_data driver_data = {
|
||||
.clock = SystemCoreClock, .irqno = 0, .phy_addr = 1};
|
||||
struct mg_tcpip_if mif = {// .mac = {...}, generate random mac address
|
||||
// Uncomment below for static configuration:
|
||||
// .ip = mg_htonl(MG_U32(192, 168, 0, 223)),
|
||||
// .mask = mg_htonl(MG_U32(255, 255, 255, 0)),
|
||||
// .gw = mg_htonl(MG_U32(192, 168, 0, 1)),
|
||||
.driver = &mg_tcpip_driver_stm32h,
|
||||
.driver = &mg_tcpip_driver_ra,
|
||||
.driver_data = &driver_data};
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mif);
|
||||
|
||||
MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac));
|
||||
while (mif.state != MG_TCPIP_STATE_READY) {
|
||||
@@ -48,7 +45,6 @@ int main(void) {
|
||||
|
||||
MG_INFO(("Initialising application..."));
|
||||
web_init(&mgr);
|
||||
#endif
|
||||
|
||||
MG_INFO(("Starting event loop"));
|
||||
for (;;) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define MG_ENABLE_TCPIP 1
|
||||
#define MG_ENABLE_CUSTOM_MILLIS 1
|
||||
#define MG_ENABLE_CUSTOM_RANDOM 1
|
||||
#define MG_ENABLE_CUSTOM_RANDOM 0
|
||||
#define MG_ENABLE_PACKED_FS 1
|
||||
#define MG_ENABLE_DRIVER_STM32H 1
|
||||
#define MG_ENABLE_DRIVER_RA 1
|
||||
//#define MG_ENABLE_LINES 1
|
||||
Reference in new issue
Block a user