Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for RA6M4 #2623

Merged
merged 1 commit into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions examples/renesas/ek-ra6m4-make-baremetal-builtin/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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,[email protected]

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/\"
Expand Down Expand Up @@ -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
Expand Down
14 changes: 10 additions & 4 deletions examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand All @@ -33,21 +34,26 @@ 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
}

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
Expand Down
171 changes: 123 additions & 48 deletions examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
}

Expand All @@ -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)
}
18 changes: 7 additions & 11 deletions examples/renesas/ek-ra6m4-make-baremetal-builtin/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -48,7 +45,6 @@ int main(void) {

MG_INFO(("Initialising application..."));
web_init(&mgr);
#endif

MG_INFO(("Starting event loop"));
for (;;) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading
Loading