-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
447 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// Copyright (c) 2024 Cesanta Software Limited | ||
// All rights reserved | ||
|
||
#include <stdint.h> | ||
#include <string.h> | ||
#include <sys/stat.h> // 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) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
#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) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 = .; | ||
} |
Oops, something went wrong.