Use V307 flash

This commit is contained in:
cpq committed 2023-11-30 23:51:34 +00:00
1 parent c74534cf5e
commit 85d3e7f375
17 files changed
+1518 -1064

No files matched your search

@@ -1,13 +1,18 @@
ROOT ?= $(realpath $(PWD)/../../..)
PREFIX ?= riscv-none-elf
#PREFIX ?= docker run --platform linux/amd64 --rm -it -v$(ROOT):$(ROOT) -w $(PWD) mdashnet/riscv riscv64-unknown-elf
CFLAGS = -W -Wall -Wextra -Wno-error -Wundef -Wshadow -Wdouble-promotion
CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -march=rv32imafc -mabi=ilp32f
CFLAGS += -DSYSCLK_FREQ_144MHz_HSE -I. -Ivendor -g3 -Os $(CFLAGS_EXTRA)
LDFLAGS = -T vendor/link.ld -nostartfiles --specs=nano.specs
LDFLAGS += -lc -lgcc -Wl,--gc-sections
LDFLAGS = -T link.ld -nostartfiles --specs=nano.specs
LDFLAGS += -lc -lgcc -Wl,--gc-sections #-Wl,-Map=$@.map
SOURCES = main.c mongoose.c net.c packed_fs.c vendor/system_ch32v30x.c vendor/startup_ch32v30x_D8C.S
SOURCES = main.c mongoose.c net.c packed_fs.c
SOURCES += vendor/system_ch32v30x.c vendor/startup_ch32v30x_D8C.S
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\"
ifeq ($(OS),Windows_NT)
@@ -19,14 +24,15 @@ endif
all: firmware.bin
firmware.bin: firmware.elf
riscv64-unknown-elf-objcopy -O binary $< $@
$(PREFIX)-objcopy -O binary $< $@
ls -l firmware.*
firmware.elf: $(SOURCES) hal.h Makefile
riscv64-unknown-elf-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
firmware.elf: $(SOURCES) link.ld hal.h mongoose_custom.h Makefile
$(PREFIX)-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
flash: firmware.bin
wchisp flash $<
# @echo; echo "IMPORTANT: configure device to 96k RAM / 224k Flash"
clean:
$(RM) firmware.* *.su
@@ -3,6 +3,8 @@
#pragma once
#define UART_DEBUG USART1
#include <ch32v30x.h>
#include <stdbool.h>
@@ -58,7 +60,7 @@ static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t cfg) {
}
volatile uint32_t *r = &gpio->CFGLR;
if (no > 7) r = &gpio->CFGHR, no -= 8;
uint8_t v = (mode & 3U) | ((cfg & 3U) << 2);
uint8_t v = (uint8_t) ((mode & 3U) | ((cfg & 3U) << 2));
CLRSET(*r, 15U << (no * 4), v << (no * 4));
}
static inline void gpio_input(uint16_t pin) {
@@ -127,6 +129,23 @@ static inline void ethernet_init(void) {
// NVIC_SetPriority(ETH_IRQn, 0);
}
// opt: 0: 128/192, 1: 96/224, 2: 64/256, 3: 32/288
static inline void set_ram_size(uint8_t opt) {
// Unlock flash option byte, RM 32.6.1
FLASH->KEYR = 0x45670123;
FLASH->KEYR = 0xcdef89ab;
FLASH->OBKEYR = 0x45670123;
FLASH->OBKEYR = 0xcdef89ab;
FLASH->CTLR |= 1U << 4; // Enable options byte programming
unsigned val = *(uint16_t *) 0x1ffff802;
val &= ~(3U << 6);
val |= ((opt & 3U)) << 6;
FLASH->CTLR |= FLASH_CTLR_PG; // Set programming bit
*(uint16_t *) 0x1ffff802 = (uint16_t) val; // Write half-word
spin(9999);
FLASH->CTLR &= ~(1U << 4);
}
static inline void rng_init(void) {
RNG->CR |= RNG_CR_RNGEN;
}
@@ -0,0 +1,36 @@
ENTRY(_start);
MEMORY {
flash(rx) : ORIGIN = 0x00000000, LENGTH = 288k
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 32k
}
_estack = ORIGIN(sram) + LENGTH(sram);
SECTIONS {
.init : { _sinit = .; . = ALIGN(4); KEEP(*(SORT_NONE(.init))) . = ALIGN(4); _einit = . ; } > flash
.vector : { KEEP(*(.vector)) } > flash
.text : { *(.text .text.* .rodata .rodata.*) } > flash
.dalign : { . = ALIGN(4); PROVIDE(_data_vma = . ); } > sram AT > flash
.dlalign : { . = ALIGN(4); PROVIDE(_data_lma = . ); } > flash AT > flash
.data : {
_sdata = .;
*(.data .data.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.* .gnu.linkonce.s.*) /* for weak symbol linking */
_edata = .;
} > sram AT > flash
.bss : { _sbss = .; *(.bss .bss.* COMMON) _ebss = .; } > sram
. = ALIGN(8);
_end = .;
__stack_size = 2048;
.stack ORIGIN(sram) + LENGTH(sram) - __stack_size : {
PROVIDE( _heap_end = . );
. = ALIGN(4);
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = . );
} > sram
}
@@ -8,7 +8,6 @@
#define LED1_PIN PIN('A', 15) // On-board red LED
#define LED2_PIN PIN('B', 4) // On-board blue LED
#define LED_PIN LED2_PIN
#define UART_DEBUG USART1
#define BLINK_PERIOD_MS 1000 // LED_PIN blinking period in millis
@@ -29,10 +28,24 @@ void mg_random(void *buf, size_t len) { // Use on-board RNG
}
}
// This flash space resides at after the 0-wait 320k area
static char *s_flash_space = (char *) (0x8000000 + 320 * 1024);
bool web_load_settings(void *buf, size_t len) {
if (*(uint32_t *) s_flash_space != SETTINGS_MAGIC) return false;
memcpy(buf, s_flash_space, len);
return true;
}
bool web_save_settings(void *buf, size_t len) {
return mg_flash_write(s_flash_space, buf, len);
}
static void timer_fn(void *arg) {
gpio_toggle(LED_PIN); // Blink LED_PIN
struct mg_tcpip_if *ifp = arg; // And show
const char *names[] = {"down", "up", "req", "ready"}; // network stats
return;
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));
@@ -53,21 +66,20 @@ static void mg_putchar(char ch, void *param) {
// https://mongoose.ws/documentation/#2-minute-integration-guide
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
// The MG_EV_HTTP_MSG event means HTTP request. `hm` holds parsed request,
// see https://mongoose.ws/documentation/#struct-mg_http_message
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
// If the requested URI is "/api/hi", send a simple JSON response back
if (mg_http_match_uri(hm, "/api/hi")) {
// Use mg_http_reply() API function to generate JSON response. It adds a
// Content-Length header automatically. In the response, we show
// the requested URI and HTTP body:
mg_http_reply(c, 200, "", "{%m:%m,%m:%m}\n", // See mg_snprintf doc
MG_ESC("uri"), mg_print_esc, hm->uri.len, hm->uri.ptr,
MG_ESC("body"), mg_print_esc, hm->body.len, hm->body.ptr);
if (mg_http_match_uri(hm, "/api/ram")) {
// This endpoint allows to read RAM:
// curl IP:8000/api/ram -d '{"addr":"0x20", "len": 32}'
char *s = mg_json_get_str(hm->body, "$.addr");
void *buf = (void *) (uintptr_t) (s ? strtoul(s, NULL, 0) : 0);
size_t len = mg_json_get_long(hm->body, "$.len", 4);
mg_hexdump(buf, len);
mg_http_reply(c, 200, "", "{%m:%m}\n", MG_ESC("data"), mg_print_hex, len,
buf);
free(s);
} else {
// For all other URIs, serve static content
mg_http_reply(c, 200, "", "hi tick %llu\n", s_ticks); // See mg_snprintf doc
mg_http_reply(c, 200, "", "hi tick %llu\n", s_ticks);
}
}
(void) fn_data;
@@ -85,10 +97,19 @@ int main(void) {
mg_log_set(MG_LL_DEBUG); // Set log level
mg_log_set_fn(mg_putchar, UART_DEBUG);
ethernet_init(); // Initialise ethernet pins
MG_INFO(("Starting, CPU freq %g MHz", (double) SystemCoreClock / 1000000));
// MG_INFO(("RCC_RSTSCKR=%#lx", RCC->RSTSCKR));
extern char _end[], _heap_end[];
MG_INFO(("Heap size: %lu bytes", _heap_end - _end));
// Print chip RAM/Flash configuration, and set to 64/256
const char *sizes[] = {"128/192", "96/224", "64/256", "32/288"};
uint32_t mode = (FLASH->OBR >> 8) & 3U;
MG_INFO(("RAM/FLASH configuration: %s", sizes[mode]));
if (mode != 3) set_ram_size(3), mg_device_reset();
// Initialise Mongoose network stack
ethernet_init(); // Initialise ethernet pins
struct mg_tcpip_driver_stm32_data driver_data = {.mdc_cr = 1};
struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC(),
// Uncomment below for static configuration:
@@ -117,17 +138,12 @@ int main(void) {
return 0;
}
// Newlib syscalls overrides. IO retargeting, and malloc
int _write(int fd, char *ptr, int len) {
if (fd == 1 || fd == 2) uart_write_buf(UART_DEBUG, ptr, (size_t) len);
return len;
}
// Newlib syscall for malloc
void *_sbrk(ptrdiff_t incr) {
extern char _end[];
extern char _heap_end[];
extern char _end[], _heap_end[];
static char *curbrk = _end;
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end)) return NULL - 1;
//MG_INFO(("%p %ld", curbrk, incr));
curbrk += incr;
return curbrk - incr;
}
@@ -2,6 +2,8 @@
// See https://mongoose.ws/documentation/#build-options
#define MG_ARCH MG_ARCH_NEWLIB
#define MG_OTA MG_OTA_FLASH
#define MG_DEVICE MG_DEVICE_CH32V307
#define MG_ENABLE_TCPIP 1
#define MG_ENABLE_CUSTOM_MILLIS 1
+180 -1
View File
@@ -1 +1,180 @@
ENTRY( _start )␍␍__stack_size = 2048;␍␍PROVIDE( _stack_size = __stack_size );␍␍␍MEMORY␍{␍/* CH32V30x_D8C - CH32V305RB-CH32V305FB␍ CH32V30x_D8 - CH32V303CB-CH32V303RB␍*/␍/*␍ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K␍ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K␍*/␍ ␍/* CH32V30x_D8C - CH32V307VC-CH32V307WC-CH32V307RC␍ CH32V30x_D8 - CH32V303VC-CH32V303RC␍ FLASH + RAM supports the following configuration␍ FLASH-192K + RAM-128K␍ FLASH-224K + RAM-96K␍ FLASH-256K + RAM-64K ␍ FLASH-288K + RAM-32K ␍*/␍ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 288K␍ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K␍}␍␍␍SECTIONS␍{␍␍ .init :␍ {␍ _sinit = .;␍ . = ALIGN(4);␍ KEEP(*(SORT_NONE(.init)))␍ . = ALIGN(4);␍ _einit = .;␍ } >FLASH AT>FLASH␍␍ .vector :␍ {␍ *(.vector);␍ . = ALIGN(64);␍ } >FLASH AT>FLASH␍␍ .text :␍ {␍ . = ALIGN(4);␍ *(.text)␍ *(.text.*)␍ *(.rodata)␍ *(.rodata*)␍ *(.gnu.linkonce.t.*)␍ . = ALIGN(4);␍ } >FLASH AT>FLASH ␍␍ .fini :␍ {␍ KEEP(*(SORT_NONE(.fini)))␍ . = ALIGN(4);␍ } >FLASH AT>FLASH␍␍ PROVIDE( _etext = . );␍ PROVIDE( _eitcm = . ); ␍␍ .preinit_array :␍ {␍ PROVIDE_HIDDEN (__preinit_array_start = .);␍ KEEP (*(.preinit_array))␍ PROVIDE_HIDDEN (__preinit_array_end = .);␍ } >FLASH AT>FLASH ␍ ␍ .init_array :␍ {␍ PROVIDE_HIDDEN (__init_array_start = .);␍ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))␍ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))␍ PROVIDE_HIDDEN (__init_array_end = .);␍ } >FLASH AT>FLASH ␍ ␍ .fini_array :␍ {␍ PROVIDE_HIDDEN (__fini_array_start = .);␍ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))␍ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))␍ PROVIDE_HIDDEN (__fini_array_end = .);␍ } >FLASH AT>FLASH ␍ ␍ .ctors :␍ {␍ /* gcc uses crtbegin.o to find the start of␍ the constructors, so we make sure it is␍ first. Because this is a wildcard, it␍ doesn't matter if the user does not␍ actually link against crtbegin.o; the␍ linker won't look for a file to match a␍ wildcard. The wildcard also means that it␍ doesn't matter which directory crtbegin.o␍ is in. */␍ KEEP (*crtbegin.o(.ctors))␍ KEEP (*crtbegin?.o(.ctors))␍ /* We don't want to include the .ctor section from␍ the crtend.o file until after the sorted ctors.␍ The .ctor section from the crtend file contains the␍ end of ctors marker and it must be last */␍ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))␍ KEEP (*(SORT(.ctors.*)))␍ KEEP (*(.ctors))␍ } >FLASH AT>FLASH ␍ ␍ .dtors :␍ {␍ KEEP (*crtbegin.o(.dtors))␍ KEEP (*crtbegin?.o(.dtors))␍ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))␍ KEEP (*(SORT(.dtors.*)))␍ KEEP (*(.dtors))␍ } >FLASH AT>FLASH ␍␍ .dalign :␍ {␍ . = ALIGN(4);␍ PROVIDE(_data_vma = .);␍ } >RAM AT>FLASH ␍␍ .dlalign :␍ {␍ . = ALIGN(4); ␍ PROVIDE(_data_lma = .);␍ } >FLASH AT>FLASH␍␍ .data :␍ {␍ *(.gnu.linkonce.r.*)␍ *(.data .data.*)␍ *(.gnu.linkonce.d.*)␍ . = ALIGN(8);␍ PROVIDE( __global_pointer$ = . + 0x800 );␍ *(.sdata .sdata.*)␍ *(.sdata2.*)␍ *(.gnu.linkonce.s.*)␍ . = ALIGN(8);␍ *(.srodata.cst16)␍ *(.srodata.cst8)␍ *(.srodata.cst4)␍ *(.srodata.cst2)␍ *(.srodata .srodata.*)␍ . = ALIGN(4);␍ PROVIDE( _edata = .);␍ } >RAM AT>FLASH␍␍ .bss :␍ {␍ . = ALIGN(4);␍ PROVIDE( _sbss = .);␍ *(.sbss*)␍ *(.gnu.linkonce.sb.*)␍ *(.bss*)␍ *(.gnu.linkonce.b.*) ␍ *(COMMON*)␍ . = ALIGN(4);␍ PROVIDE( _ebss = .);␍ } >RAM AT>FLASH␍␍ PROVIDE( _end = _ebss);␍ PROVIDE( end = . );␍␍ .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :␍ {␍ PROVIDE( _heap_end = . ); ␍ . = ALIGN(4);␍ PROVIDE(_susrstack = . );␍ . = . + __stack_size;␍ PROVIDE( _eusrstack = .);␍ } >RAM ␍␍}␍␍␍␍
ENTRY( _start )
__stack_size = 2048;
PROVIDE( _stack_size = __stack_size );
MEMORY {
/* CH32V30x_D8C - CH32V305RB-CH32V305FB
CH32V30x_D8 - CH32V303CB-CH32V303RB
*/
/*
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
*/
/* CH32V30x_D8C - CH32V307VC-CH32V307WC-CH32V307RC
CH32V30x_D8 - CH32V303VC-CH32V303RC
FLASH + RAM supports the following configuration
FLASH-192K + RAM-128K
FLASH-224K + RAM-96K
FLASH-256K + RAM-64K
FLASH-288K + RAM-32K
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 288K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
*/
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 288k
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32k
}
SECTIONS
{
.init :
{
_sinit = .;
. = ALIGN(4);
KEEP(*(SORT_NONE(.init)))
. = ALIGN(4);
_einit = .;
} >FLASH AT>FLASH
.vector :
{
*(.vector);
. = ALIGN(64);
} >FLASH AT>FLASH
.text :
{
. = ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata*)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
} >FLASH AT>FLASH
.fini :
{
KEEP(*(SORT_NONE(.fini)))
. = ALIGN(4);
} >FLASH AT>FLASH
PROVIDE( _etext = . );
PROVIDE( _eitcm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH AT>FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH AT>FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH AT>FLASH
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >FLASH AT>FLASH
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >FLASH AT>FLASH
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
} >RAM AT>FLASH
.dlalign :
{
. = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
.data :
{
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4);
PROVIDE( _edata = .);
} >RAM AT>FLASH
.bss :
{
. = ALIGN(4);
PROVIDE( _sbss = .);
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss*)
*(.gnu.linkonce.b.*)
*(COMMON*)
. = ALIGN(4);
PROVIDE( _ebss = .);
} >RAM AT>FLASH
PROVIDE( _end = _ebss);
PROVIDE( end = . );
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
{
PROVIDE( _heap_end = . );
. = ALIGN(4);
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
} >RAM
}