From ebfa5f0ba796df4f0dd2351df5d91764dd5b263f Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Sat, 27 Jan 2024 17:06:12 +0000 Subject: [PATCH] Add ek-ra6m4 example --- .../ek-ra6m4-make-baremetal-builtin/Makefile | 56 +++++++ .../ek-ra6m4-make-baremetal-builtin/hal.c | 157 ++++++++++++++++++ .../ek-ra6m4-make-baremetal-builtin/hal.h | 127 ++++++++++++++ .../ek-ra6m4-make-baremetal-builtin/link.ld | 30 ++++ .../ek-ra6m4-make-baremetal-builtin/main.c | 59 +++++++ .../mongoose.c | 1 + .../mongoose.h | 1 + .../mongoose_custom.h | 13 ++ .../ek-ra6m4-make-baremetal-builtin/net.c | 1 + .../ek-ra6m4-make-baremetal-builtin/net.h | 1 + .../packed_fs.c | 1 + 11 files changed, 447 insertions(+) create mode 100644 examples/renesas/ek-ra6m4-make-baremetal-builtin/Makefile create mode 100644 examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.c create mode 100644 examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.h create mode 100644 examples/renesas/ek-ra6m4-make-baremetal-builtin/link.ld create mode 100644 examples/renesas/ek-ra6m4-make-baremetal-builtin/main.c create mode 120000 examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.c create mode 120000 examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.h create mode 100644 examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose_custom.h create mode 120000 examples/renesas/ek-ra6m4-make-baremetal-builtin/net.c create mode 120000 examples/renesas/ek-ra6m4-make-baremetal-builtin/net.h create mode 120000 examples/renesas/ek-ra6m4-make-baremetal-builtin/packed_fs.c diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/Makefile b/examples/renesas/ek-ra6m4-make-baremetal-builtin/Makefile new file mode 100644 index 00000000..bc79a601 --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/Makefile @@ -0,0 +1,56 @@ +CFLAGS = -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion +CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion +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 + +# Example specific build options. See README.md +CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\" + +ifeq ($(OS),Windows_NT) + RM = cmd /C del /Q /F /S +else + RM = rm -rf +endif + +all build example: firmware.bin + +firmware.bin: firmware.elf + arm-none-eabi-objcopy -O binary $< $@ + +firmware.elf: cmsis_core cmsis_mcu $(SOURCES) hal.h link.ld Makefile + arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@ + arm-none-eabi-size $@ + +flash: firmware.bin + rfp-cli -d ra -t jlink -v -p -bin 0x0000000 $< + rfp-cli -d ra -t jlink -rv 0x8000000 256 + +cmsis_core: # ARM CMSIS core headers + git clone -q --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@ +cmsis_mcu: + git clone -q --depth 1 -b v5.1.0 https://github.com/renesas/fsp $@ + + +# 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 +update: firmware.bin + curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$< + +update: CFLAGS += -DUART_DEBUG=LPUART3 + +test: update + curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt + grep 'READY, IP:' /tmp/output.txt # Check for network init + +clean: + $(RM) firmware.* *.su cmsis_core cmsis_mcu mbedtls *.zip diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.c b/examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.c new file mode 100644 index 00000000..5951c18b --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.c @@ -0,0 +1,157 @@ +// Copyright (c) 2024 Cesanta Software Limited +// All rights reserved + +#include +#include +#include // For _fstat() + +#include "hal.h" + +uint32_t SystemCoreClock = SYS_FREQUENCY; +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); + +// 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}; + +void Reset_Handler(void) { + extern long _sbss[], _ebss[], _sdata[], _edata[], _sidata[]; + extern int main(void); + + SCB->VTOR = (uint32_t) tab; + for (long *dst = _sbss; dst < _ebss; dst++) *dst = 0; + for (long *dst = _sdata, *src = _sidata; dst < _edata;) *dst++ = *src++; + + SystemInit(); + main(); + while (1) (void) 0; +} + +void SystemInit(void) { // Called automatically by startup code + 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++; +} + +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)); + } +} + +uint64_t mg_millis(void) { // Let Mongoose use our uptime function + return s_ticks; // Return number of milliseconds since boot +} + +void hal_init(void) { + uart_init(UART_DEBUG, 115200); // Initialise UART + gpio_output(LED1); // Initialise LED + gpio_output(LED2); // Initialise LED + gpio_output(LED3); // Initialise LED + ethernet_init(); // Initialise Ethernet pins +} + +// Newlib syscalls. Implemented are: _sbrk() for malloc, and _write() +int _fstat(int fd, struct stat *st) { + (void) fd, (void) st; + return -1; +} + +extern unsigned char _end[]; // End of data section, start of heap. See link.ld +static unsigned char *s_current_heap_end = _end; + +size_t hal_ram_used(void) { + return (size_t) (s_current_heap_end - _end); +} + +size_t hal_ram_free(void) { + unsigned char endofstack; + return (size_t) (&endofstack - s_current_heap_end); +} + +void *_sbrk(int incr) { + unsigned char *prev_heap; + unsigned char *heap_end = (unsigned char *) ((size_t) &heap_end - 256); + prev_heap = s_current_heap_end; + // Check how much space we got from the heap end to the stack end + if (s_current_heap_end + incr > heap_end) return (void *) -1; + s_current_heap_end += incr; + return prev_heap; +} + +int _open(const char *path) { + (void) path; + return -1; +} + +int _close(int fd) { + (void) fd; + return -1; +} + +int _isatty(int fd) { + (void) fd; + return 1; +} + +int _lseek(int fd, int ptr, int dir) { + (void) fd, (void) ptr, (void) dir; + return 0; +} + +void _exit(int status) { + (void) status; + for (;;) asm volatile("BKPT #0"); +} + +void _kill(int pid, int sig) { + (void) pid, (void) sig; +} + +int _getpid(void) { + return -1; +} + +int _write(int fd, char *ptr, int len) { + (void) fd, (void) ptr, (void) len; + if (fd == 1) uart_write_buf(UART_DEBUG, ptr, (size_t) len); + return -1; +} + +int _read(int fd, char *ptr, int len) { + (void) fd, (void) ptr, (void) len; + return -1; +} + +int _link(const char *a, const char *b) { + (void) a, (void) b; + return -1; +} + +int _unlink(const char *a) { + (void) a; + return -1; +} + +int _stat(const char *path, struct stat *st) { + (void) path, (void) st; + return -1; +} + +int mkdir(const char *path, mode_t mode) { + (void) path, (void) mode; + return -1; +} + +void _init(void) { +} diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.h b/examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.h new file mode 100644 index 00000000..83fda45e --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/hal.h @@ -0,0 +1,127 @@ +// Copyright (c) 2024 Cesanta Software Limited +// All rights reserved +// +// MCU and ek-ra6m4 eval board datasheets: +// https://www.renesas.com/us/en/document/man/ra6m4-group-user-s-manual-hardware +// https://www.renesas.com/us/en/document/man/ek-ra6m5-v1-users-manual + +#pragma once + +#include +#include +#include +#include "bsp_exceptions.h" + +#include "R7FA6M4AF.h" + +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 PIN_NUM(pin) (pin & 255) +#define PIN_PORT(pin) (pin >> 8) + +// No-op HAL API implementation for a device with GPIO and UART +#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 +static inline void clock_init(void) { + SCB->CPACR = (uint32_t) 15U << 20; +} + +// GPIO +#define GPIO(N) ((R_PORT0_Type *) (R_PORT0_BASE + 0x20 * (N))) +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; + } +} + +static inline void gpio_output(uint16_t pin) { + gpio_init(pin, GPIO_MODE_OUTPUT, 0); +} + +static inline void gpio_input(uint16_t pin) { + gpio_init(pin, GPIO_MODE_INPUT, 0); +} + +static inline bool gpio_read(uint16_t pin) { + R_PORT0_Type *gpio = GPIO(PIN_PORT(pin)); + return gpio->PCNTR2 & BIT(PIN_NUM(pin)) ? true : false; +} + +static inline void gpio_write(uint16_t pin, bool val) { + R_PORT0_Type *gpio = GPIO(PIN_PORT(pin)); + gpio->PCNTR3 = BIT(PIN_NUM(pin)) << (val ? 0 : 16U); +} + +static inline void gpio_toggle(uint16_t pin) { + gpio_write(pin, !gpio_read(pin)); +} + +// UART +static inline void uart_init(R_SCI0_Type *uart, unsigned baud) { + gpio_output(UART_TX); + gpio_input(UART_RX); + (void) uart, (void) baud; +} + +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_buf(void *uart, char *buf, size_t len) { + while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++); +} + +// Ethernet +static inline void ethernet_init(void) { +} diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/link.ld b/examples/renesas/ek-ra6m4-make-baremetal-builtin/link.ld new file mode 100644 index 00000000..4eeaed25 --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/link.ld @@ -0,0 +1,30 @@ +ENTRY(Reset_Handler); +MEMORY { + flash(rx) : ORIGIN = 0x00000000, LENGTH = 1024k + sram(rwx) : ORIGIN = 0x20000000, LENGTH = 256k +} +_estack = ORIGIN(sram) + LENGTH(sram); /* End of RAM. stack points here */ + +SECTIONS { + .vectors : { KEEP(*(.isr_vector)) } > flash + .text : { *(.text* .text.*) } > flash + .rodata : { *(.rodata*) } > flash + + .data : { + _sdata = .; + *(.first_data) + *(.ram) + *(.data SORT(.data.*)) + _edata = .; + } > sram AT > flash + _sidata = LOADADDR(.data); + + .bss : { + _sbss = .; + *(.bss SORT(.bss.*) COMMON) + _ebss = .; + } > sram + + . = ALIGN(8); + _end = .; +} diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/main.c b/examples/renesas/ek-ra6m4-make-baremetal-builtin/main.c new file mode 100644 index 00000000..1c1ba8e4 --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/main.c @@ -0,0 +1,59 @@ +// Copyright (c) 2023 Cesanta Software Limited +// All rights reserved + +#include "hal.h" +#include "mongoose.h" +#include "net.h" + +#define BLINK_PERIOD_MS 1000 // LED blinking period in millis + +static void timer_fn(void *arg) { + gpio_toggle(LED2); // Blink LED +#if 0 + 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) { + hal_init(); + + struct mg_mgr mgr; // Initialise + mg_mgr_init(&mgr); // Mongoose event manager + 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(), + // 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_data = &driver_data}; + mg_tcpip_init(&mgr, &mif); + + MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac)); + while (mif.state != MG_TCPIP_STATE_READY) { + mg_mgr_poll(&mgr, 0); + } + + MG_INFO(("Initialising application...")); + web_init(&mgr); +#endif + + MG_INFO(("Starting event loop")); + for (;;) { + mg_mgr_poll(&mgr, 0); + } + + return 0; +} diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.c b/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.c new file mode 120000 index 00000000..5e522bbc --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.c @@ -0,0 +1 @@ +../../../mongoose.c \ No newline at end of file diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.h b/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.h new file mode 120000 index 00000000..ee4ac823 --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose.h @@ -0,0 +1 @@ +../../../mongoose.h \ No newline at end of file diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose_custom.h b/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose_custom.h new file mode 100644 index 00000000..a8f49aee --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/mongoose_custom.h @@ -0,0 +1,13 @@ +#pragma once + +// See https://mongoose.ws/documentation/#build-options +#define MG_ARCH MG_ARCH_NEWLIB +#define MG_OTA MG_OTA_FLASH +#define MG_DEVICE MG_DEVICE_STM32H5 + +#define MG_ENABLE_TCPIP 1 +#define MG_ENABLE_CUSTOM_MILLIS 1 +#define MG_ENABLE_CUSTOM_RANDOM 1 +#define MG_ENABLE_PACKED_FS 1 +#define MG_ENABLE_DRIVER_STM32H 1 +//#define MG_ENABLE_LINES 1 diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/net.c b/examples/renesas/ek-ra6m4-make-baremetal-builtin/net.c new file mode 120000 index 00000000..fe0e6f06 --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/net.c @@ -0,0 +1 @@ +../../device-dashboard/net.c \ No newline at end of file diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/net.h b/examples/renesas/ek-ra6m4-make-baremetal-builtin/net.h new file mode 120000 index 00000000..9de896ef --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/net.h @@ -0,0 +1 @@ +../../device-dashboard/net.h \ No newline at end of file diff --git a/examples/renesas/ek-ra6m4-make-baremetal-builtin/packed_fs.c b/examples/renesas/ek-ra6m4-make-baremetal-builtin/packed_fs.c new file mode 120000 index 00000000..e06bf092 --- /dev/null +++ b/examples/renesas/ek-ra6m4-make-baremetal-builtin/packed_fs.c @@ -0,0 +1 @@ +../../device-dashboard/packed_fs.c \ No newline at end of file