WCH FW build fix. Introduce phy_addr for STM32F driver

This commit is contained in:
Sergey Lyubka 2023-12-27 15:38:41 +00:00
parent 176db1aedb
commit 01b612cff5
13 changed files with 881 additions and 1328 deletions

File diff suppressed because it is too large Load Diff

View File

@ -307,9 +307,9 @@ function Settings({}) {
<//> <//>
<div class="py-2 px-5 flex-1 flex flex-col relative"> <div class="py-2 px-5 flex-1 flex flex-col relative">
<${Setting} title="Enable MQTT forwarding" value=${settings.mqtt_enabled} setfn=${mksetfn('mqtt_enabled')} type="switch" /> <${Setting} title="Enable MQTT forwarding" value=${settings.mqtt_enabled} setfn=${mksetfn('mqtt_enabled')} type="switch" />
<${Setting} title="MQTT Server URL" value=${settings.mqtt_server_url} setfn=${mksetfn('mqtt_server_url')} type="" disabled=${!settings.mqtt_enabled} /> <${Setting} title="MQTT Server URL" value=${settings.mqtt_server_url} setfn=${mksetfn('mqtt_server_url')} />
<${Setting} title="MQTT Topic RX" value=${settings.mqtt_topic_rx} setfn=${mksetfn('mqtt_topic_rx')} type="" disabled=${!settings.mqtt_enabled} /> <${Setting} title="MQTT Topic RX" value=${settings.mqtt_topic_rx} setfn=${mksetfn('mqtt_topic_rx')} />
<${Setting} title="MQTT Topic TX" value=${settings.mqtt_topic_tx} setfn=${mksetfn('mqtt_topic_tx')} type="" disabled=${!settings.mqtt_enabled} /> <${Setting} title="MQTT Topic TX" value=${settings.mqtt_topic_tx} setfn=${mksetfn('mqtt_topic_tx')} />
<div class="mb-1 mt-3 flex place-content-end"><${Button} icon=${Icons.save} onclick=${onsave} title="Save Settings" /><//> <div class="mb-1 mt-3 flex place-content-end"><${Button} icon=${Icons.save} onclick=${onsave} title="Save Settings" /><//>
<//> <//>
<//> <//>

View File

@ -1,16 +1,12 @@
ROOT ?= $(realpath $(PWD)/../../..) ROOT ?= $(realpath $(PWD)/../../..)
PREFIX ?= riscv-none-elf PREFIX ?= riscv-none-elf
#PREFIX ?= docker run --platform linux/amd64 --rm -it -v$(ROOT):$(ROOT) -w $(PWD) mdashnet/riscv riscv64-unknown-elf #PREFIX ?= docker run --platform linux/amd64 --rm -it -v$(ROOT):$(ROOT) -w $(PWD) mdashnet/riscv riscv-none-elf
CFLAGS = -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion
CFLAGS = -W -Wall -Wextra -Wno-error -Wundef -Wshadow -Wdouble-promotion CFLAGS += -Wformat-truncation -Wconversion -Wno-sign-conversion
CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion CFLAGS += -ffunction-sections -fdata-sections -fno-common
CFLAGS += -ffunction-sections -fdata-sections CFLAGS += -DSYSCLK_FREQ_144MHz_HSE -I. -Ivendor -g3 -Os
CFLAGS += -march=rv32imafc -mabi=ilp32f CFLAGS += -march=rv32imafc -mabi=ilp32 $(CFLAGS_EXTRA)
CFLAGS += -DSYSCLK_FREQ_144MHz_HSE -I. -Ivendor -g3 -Os $(CFLAGS_EXTRA) LDFLAGS = -T vendor/link.ld -nostartfiles --specs=nano.specs --specs=nosys.specs -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 SOURCES = main.c mongoose.c net.c packed_fs.c
SOURCES += vendor/system_ch32v30x.c vendor/startup_ch32v30x_D8C.S 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/\" CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\"
@ -25,7 +21,7 @@ all: firmware.bin
firmware.bin: firmware.elf firmware.bin: firmware.elf
$(PREFIX)-objcopy -O binary $< $@ $(PREFIX)-objcopy -O binary $< $@
ls -l firmware.* $(PREFIX)-size --format=berkeley $<
firmware.elf: $(SOURCES) link.ld hal.h mongoose_custom.h Makefile firmware.elf: $(SOURCES) link.ld hal.h mongoose_custom.h Makefile
$(PREFIX)-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@ $(PREFIX)-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@

View File

@ -34,7 +34,7 @@ enum {
}; };
enum { GPIO_OTYPE_PP, GPIO_OTYPE_OD, GPIO_OTYPE_AF_PP, GPIO_AF_OD }; enum { GPIO_OTYPE_PP, GPIO_OTYPE_OD, GPIO_OTYPE_AF_PP, GPIO_AF_OD };
enum { GPIO_ITYPE_ANALOG, GPIO_ITYPE_FLOAT, GPIO_ITYPE_PUPD }; enum { GPIO_ITYPE_ANALOG, GPIO_ITYPE_FLOAT, GPIO_ITYPE_PUPD };
#define GPIO(N) ((GPIO_TypeDef *) (GPIOA_BASE + 0x400 * (N))) #define GPIO(N) ((GPIO_TypeDef *) (size_t) (GPIOA_BASE + 0x400 * (N)))
static GPIO_TypeDef *gpio_bank(uint16_t pin) { static GPIO_TypeDef *gpio_bank(uint16_t pin) {
return GPIO(PINBANK(pin)); return GPIO(PINBANK(pin));
@ -59,7 +59,10 @@ static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t cfg) {
RCC->APB2PCENR |= BIT(0); // Enable AFIO RCC->APB2PCENR |= BIT(0); // Enable AFIO
} }
volatile uint32_t *r = &gpio->CFGLR; volatile uint32_t *r = &gpio->CFGLR;
if (no > 7) r = &gpio->CFGHR, no -= 8; if (no > 7) {
r = &gpio->CFGHR;
no = (uint8_t) (no - 8);
}
uint8_t v = (uint8_t) ((mode & 3U) | ((cfg & 3U) << 2)); uint8_t v = (uint8_t) ((mode & 3U) | ((cfg & 3U) << 2));
CLRSET(*r, 15U << (no * 4), v << (no * 4)); CLRSET(*r, 15U << (no * 4), v << (no * 4));
} }
@ -106,27 +109,13 @@ static inline uint8_t uart_read_byte(USART_TypeDef *uart) {
} }
static inline void ethernet_init(void) { static inline void ethernet_init(void) {
// Set 60MHz ethernet clock RCC->CTLR &= ~BIT(28); // PLL3 off
RCC->CTLR &= ~BIT(28); // PLL3 off CLRSET(RCC->CFGR2, 15U << 4, 1U << 4); // 3.4.12: PREDIV2 = 2
CLRSET(RCC->CFGR2, 15U << 4, 1U << 4); // 3.4.12: PREDIV2 = 2 CLRSET(RCC->CFGR2, 15U << 12, 13U << 12); // 3.4.12: PLL3MUL = 15
CLRSET(RCC->CFGR2, 15U << 12, 13U << 12); // 3.4.12: PLL3MUL = 15 RCC->CTLR |= BIT(28); // PLL3 on
RCC->CTLR |= BIT(28); // PLL3 on EXTEN->EXTEN_CTR |= EXTEN_ETH_10M_EN; // Enable built-in 10M PHY
EXTEN->EXTEN_CTR |= EXTEN_ETH_10M_EN; // Enable built-in 10M PHY
#if 0
// RMII mode
// 27.1.3 : init pins
uint16_t pins[] = {PIN('A', 1), PIN('A', 2), PIN('A', 7),
PIN('B', 11), PIN('B', 12), PIN('B', 13),
PIN('C', 1), PIN('C', 4), PIN('C', 5)};
for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
gpio_init(pins[i], GPIO_MODE_OUTPUT_50M, GPIO_OTYPE_AF_PP);
}
AFIO->PCFR1 |= BIT(23); // Use RMII
#endif
RCC->AHBPCENR |= BIT(14) | BIT(15) | BIT(16); // Enable MAC, TX, RX RCC->AHBPCENR |= BIT(14) | BIT(15) | BIT(16); // Enable MAC, TX, RX
NVIC_EnableIRQ(ETH_IRQn); NVIC_EnableIRQ(ETH_IRQn); // Enable Ethernet interrupt
// NVIC_SetPriority(ETH_IRQn, 0);
} }
// opt: 0: 128/192, 1: 96/224, 2: 64/256, 3: 32/288 // opt: 0: 128/192, 1: 96/224, 2: 64/256, 3: 32/288

View File

@ -1,36 +0,0 @@
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
}

View File

@ -45,7 +45,6 @@ static void timer_fn(void *arg) {
gpio_toggle(LED_PIN); // Blink LED_PIN gpio_toggle(LED_PIN); // Blink LED_PIN
struct mg_tcpip_if *ifp = arg; // And show struct mg_tcpip_if *ifp = arg; // And show
const char *names[] = {"down", "up", "req", "ready"}; // network stats const char *names[] = {"down", "up", "req", "ready"}; // network stats
return;
MG_INFO(("Ethernet: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u", 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, names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
ifp->ndrop, ifp->nerr)); ifp->ndrop, ifp->nerr));
@ -59,30 +58,12 @@ void SysTick_Init(void) {
NVIC_EnableIRQ(SysTicK_IRQn); NVIC_EnableIRQ(SysTicK_IRQn);
} }
static void mg_putchar(char ch, void *param) {
uart_write_byte(param, ch);
}
// https://mongoose.ws/documentation/#2-minute-integration-guide // https://mongoose.ws/documentation/#2-minute-integration-guide
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) { if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data; struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/api/ram")) { mg_http_reply(c, 200, "", "ok %p %p\r\n", hm, fn_data);
// 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);
}
} }
(void) fn_data;
} }
int main(void) { int main(void) {
@ -95,10 +76,8 @@ int main(void) {
struct mg_mgr mgr; // Initialise struct mg_mgr mgr; // Initialise
mg_mgr_init(&mgr); // Mongoose event manager mg_mgr_init(&mgr); // Mongoose event manager
mg_log_set(MG_LL_DEBUG); // Set log level mg_log_set(MG_LL_DEBUG); // Set log level
mg_log_set_fn(mg_putchar, UART_DEBUG);
MG_INFO(("Starting, CPU freq %g MHz", (double) SystemCoreClock / 1000000)); MG_INFO(("Starting, CPU freq %g MHz", (double) SystemCoreClock / 1000000));
// MG_INFO(("RCC_RSTSCKR=%#lx", RCC->RSTSCKR));
extern char _end[], _heap_end[]; extern char _end[], _heap_end[];
MG_INFO(("Heap size: %lu bytes", _heap_end - _end)); MG_INFO(("Heap size: %lu bytes", _heap_end - _end));
@ -106,12 +85,11 @@ int main(void) {
const char *sizes[] = {"128/192", "96/224", "64/256", "32/288"}; const char *sizes[] = {"128/192", "96/224", "64/256", "32/288"};
uint32_t mode = (FLASH->OBR >> 8) & 3U; uint32_t mode = (FLASH->OBR >> 8) & 3U;
MG_INFO(("RAM/FLASH configuration: %s", sizes[mode])); MG_INFO(("RAM/FLASH configuration: %s", sizes[mode]));
if (mode != 3) set_ram_size(3), mg_device_reset(); // if (mode != 3) set_ram_size(3), mg_device_reset();
// Initialise Mongoose network stack // Initialise Mongoose network stack
ethernet_init(); // Initialise ethernet pins ethernet_init(); // Initialise ethernet pins
struct mg_tcpip_driver_stm32f_data struct mg_tcpip_driver_stm32f_data driver_data = {.mdc_cr = 1, .phy_addr = 1};
driver_data = {.mdc_cr = 1};
struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC(), struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC(),
// Uncomment below for static configuration: // Uncomment below for static configuration:
// .ip = mg_htonl(MG_U32(192, 168, 0, 223)), // .ip = mg_htonl(MG_U32(192, 168, 0, 223)),
@ -129,7 +107,7 @@ int main(void) {
MG_INFO(("Initialising application...")); MG_INFO(("Initialising application..."));
mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, NULL); mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, NULL);
web_init(&mgr); //web_init(&mgr);
MG_INFO(("Starting event loop")); MG_INFO(("Starting event loop"));
for (;;) { for (;;) {
@ -139,12 +117,25 @@ int main(void) {
return 0; return 0;
} }
// Newlib syscall for malloc // Newlib syscalls
int _write(int fd, char *buf, int len) {
if (fd == 1) uart_write_buf(USART1, buf, len);
return len;
}
void *_sbrk(ptrdiff_t incr) { void *_sbrk(ptrdiff_t incr) {
extern char _end[], _heap_end[]; extern char _end[], _heap_end[];
static char *curbrk = _end; static char *curbrk = _end;
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end)) return NULL - 1; if ((curbrk + incr < _end) || (curbrk + incr > _heap_end)) {
//MG_INFO(("%p %ld", curbrk, incr)); return NULL - 1;
}
// MG_INFO(("%p %ld", curbrk, incr));
curbrk += incr; curbrk += incr;
return curbrk - incr; return curbrk - incr;
} }
void _init(void) {
}
void _fini(void) {
}

View File

@ -1,17 +1,8 @@
ENTRY( _start ) ENTRY( _start );
__stack_size = 2048; __stack_size = 2048;
PROVIDE( _stack_size = __stack_size ); PROVIDE( _stack_size = __stack_size );
MEMORY { 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_D8C - CH32V307VC-CH32V307WC-CH32V307RC
CH32V30x_D8 - CH32V303VC-CH32V303RC CH32V30x_D8 - CH32V303VC-CH32V303RC
FLASH + RAM supports the following configuration FLASH + RAM supports the following configuration
@ -19,162 +10,129 @@ MEMORY {
FLASH-224K + RAM-96K FLASH-224K + RAM-96K
FLASH-256K + RAM-64K FLASH-256K + RAM-64K
FLASH-288K + RAM-32K FLASH-288K + RAM-32K
*/
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 288K FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 288K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
*/
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 288k
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32k
} }
SECTIONS SECTIONS {
{ .init : {
_sinit = .;
.init : . = ALIGN(4);
{ KEEP(*(SORT_NONE(.init)))
_sinit = .; . = ALIGN(4);
. = ALIGN(4); _einit = .;
KEEP(*(SORT_NONE(.init)))
. = ALIGN(4);
_einit = .;
} >FLASH AT>FLASH
.vector :
{
*(.vector);
. = ALIGN(64);
} >FLASH AT>FLASH } >FLASH AT>FLASH
.text : .vector : {
{ *(.vector);
. = ALIGN(4); . = ALIGN(64);
*(.text) } >FLASH AT>FLASH
*(.text.*)
*(.rodata)
*(.rodata*)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
} >FLASH AT>FLASH
.fini : .text : {
{ . = ALIGN(4);
KEEP(*(SORT_NONE(.fini))) *(.text)
. = ALIGN(4); *(.text.*)
} >FLASH AT>FLASH *(.rodata)
*(.rodata*)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
} >FLASH AT>FLASH
PROVIDE( _etext = . ); .fini : {
PROVIDE( _eitcm = . ); KEEP(*(SORT_NONE(.fini)))
. = ALIGN(4);
} >FLASH AT>FLASH
.preinit_array : PROVIDE( _etext = . );
{ PROVIDE( _eitcm = . );
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 : .preinit_array : {
{ PROVIDE_HIDDEN (__preinit_array_start = .);
. = ALIGN(4); KEEP (*(.preinit_array))
PROVIDE(_data_vma = .); PROVIDE_HIDDEN (__preinit_array_end = .);
} >RAM AT>FLASH } >FLASH AT>FLASH
.dlalign : .init_array : {
{ PROVIDE_HIDDEN (__init_array_start = .);
. = ALIGN(4); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
PROVIDE(_data_lma = .); KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
} >FLASH AT>FLASH PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH AT>FLASH
.data : .fini_array : {
{ PROVIDE_HIDDEN (__fini_array_start = .);
*(.gnu.linkonce.r.*) KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
*(.data .data.*) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
*(.gnu.linkonce.d.*) PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(8); } >FLASH AT>FLASH
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 : .ctors : {
{ KEEP (*crtbegin.o(.ctors))
. = ALIGN(4); KEEP (*crtbegin?.o(.ctors))
PROVIDE( _sbss = .); KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
*(.sbss*) KEEP (*(SORT(.ctors.*)))
*(.gnu.linkonce.sb.*) KEEP (*(.ctors))
*(.bss*) } >FLASH AT>FLASH
*(.gnu.linkonce.b.*)
*(COMMON*)
. = ALIGN(4);
PROVIDE( _ebss = .);
} >RAM AT>FLASH
PROVIDE( _end = _ebss); .dtors : {
PROVIDE( end = . ); KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >FLASH AT>FLASH
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : .dalign : {
{ . = ALIGN(4);
PROVIDE( _heap_end = . ); 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); . = ALIGN(4);
PROVIDE(_susrstack = . ); PROVIDE( _edata = .);
. = . + __stack_size; } >RAM AT>FLASH
PROVIDE( _eusrstack = .);
} >RAM
.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
} }

View File

@ -1,369 +0,0 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : startup_ch32v30x_D8.s
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V303x vector table for eclipse toolchain.
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*******************************************************************************/
.section .init,"ax",@progbits
.global _start
.align 1
_start:
j handle_reset
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00000013
.word 0x00100073
.section .vector,"ax",@progbits
.align 1
_vector_base:
.option norvc;
.word _start
.word 0
.word NMI_Handler /* NMI */
.word HardFault_Handler /* Hard Fault */
.word 0
.word Ecall_M_Mode_Handler /* Ecall M Mode */
.word 0
.word 0
.word Ecall_U_Mode_Handler /* Ecall U Mode */
.word Break_Point_Handler /* Break Point */
.word 0
.word 0
.word SysTick_Handler /* SysTick */
.word 0
.word SW_Handler /* SW */
.word 0
/* External Interrupts */
.word WWDG_IRQHandler /* Window Watchdog */
.word PVD_IRQHandler /* PVD through EXTI Line detect */
.word TAMPER_IRQHandler /* TAMPER */
.word RTC_IRQHandler /* RTC */
.word FLASH_IRQHandler /* Flash */
.word RCC_IRQHandler /* RCC */
.word EXTI0_IRQHandler /* EXTI Line 0 */
.word EXTI1_IRQHandler /* EXTI Line 1 */
.word EXTI2_IRQHandler /* EXTI Line 2 */
.word EXTI3_IRQHandler /* EXTI Line 3 */
.word EXTI4_IRQHandler /* EXTI Line 4 */
.word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */
.word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */
.word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */
.word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */
.word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */
.word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */
.word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */
.word ADC1_2_IRQHandler /* ADC1_2 */
.word USB_HP_CAN1_TX_IRQHandler /* USB HP and CAN1 TX */
.word USB_LP_CAN1_RX0_IRQHandler /* USB LP and CAN1RX0 */
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
.word EXTI9_5_IRQHandler /* EXTI Line 9..5 */
.word TIM1_BRK_IRQHandler /* TIM1 Break */
.word TIM1_UP_IRQHandler /* TIM1 Update */
.word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* EXTI Line 15..10 */
.word RTCAlarm_IRQHandler /* RTC Alarm through EXTI Line */
.word 0
.word TIM8_BRK_IRQHandler /* TIM8 Break */
.word TIM8_UP_IRQHandler /* TIM8 Update */
.word TIM8_TRG_COM_IRQHandler /* TIM8 Trigger and Commutation */
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.word RNG_IRQHandler /* RNG */
.word FSMC_IRQHandler /* FSMC */
.word SDIO_IRQHandler /* SDIO */
.word TIM5_IRQHandler /* TIM5 */
.word SPI3_IRQHandler /* SPI3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word TIM6_IRQHandler /* TIM6 */
.word TIM7_IRQHandler /* TIM7 */
.word DMA2_Channel1_IRQHandler /* DMA2 Channel 1 */
.word DMA2_Channel2_IRQHandler /* DMA2 Channel 2 */
.word DMA2_Channel3_IRQHandler /* DMA2 Channel 3 */
.word DMA2_Channel4_IRQHandler /* DMA2 Channel 4 */
.word DMA2_Channel5_IRQHandler /* DMA2 Channel 5 */
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word OTG_FS_IRQHandler /* OTGFS */
.word 0
.word 0
.word 0
.word UART6_IRQHandler /* UART6 */
.word UART7_IRQHandler /* UART7 */
.word UART8_IRQHandler /* UART8 */
.word TIM9_BRK_IRQHandler /* TIM9 Break */
.word TIM9_UP_IRQHandler /* TIM9 Update */
.word TIM9_TRG_COM_IRQHandler /* TIM9 Trigger and Commutation */
.word TIM9_CC_IRQHandler /* TIM9 Capture Compare */
.word TIM10_BRK_IRQHandler /* TIM10 Break */
.word TIM10_UP_IRQHandler /* TIM10 Update */
.word TIM10_TRG_COM_IRQHandler /* TIM10 Trigger and Commutation */
.word TIM10_CC_IRQHandler /* TIM10 Capture Compare */
.word DMA2_Channel6_IRQHandler /* DMA2 Channel 6 */
.word DMA2_Channel7_IRQHandler /* DMA2 Channel 7 */
.word DMA2_Channel8_IRQHandler /* DMA2 Channel 8 */
.word DMA2_Channel9_IRQHandler /* DMA2 Channel 9 */
.word DMA2_Channel10_IRQHandler /* DMA2 Channel 10 */
.word DMA2_Channel11_IRQHandler /* DMA2 Channel 11 */
.option rvc;
.section .text.vector_handler, "ax", @progbits
.weak NMI_Handler /* NMI */
.weak HardFault_Handler /* Hard Fault */
.weak Ecall_M_Mode_Handler /* Ecall M Mode */
.weak Ecall_U_Mode_Handler /* Ecall U Mode */
.weak Break_Point_Handler /* Break Point */
.weak SysTick_Handler /* SysTick */
.weak SW_Handler /* SW */
.weak WWDG_IRQHandler /* Window Watchdog */
.weak PVD_IRQHandler /* PVD through EXTI Line detect */
.weak TAMPER_IRQHandler /* TAMPER */
.weak RTC_IRQHandler /* RTC */
.weak FLASH_IRQHandler /* Flash */
.weak RCC_IRQHandler /* RCC */
.weak EXTI0_IRQHandler /* EXTI Line 0 */
.weak EXTI1_IRQHandler /* EXTI Line 1 */
.weak EXTI2_IRQHandler /* EXTI Line 2 */
.weak EXTI3_IRQHandler /* EXTI Line 3 */
.weak EXTI4_IRQHandler /* EXTI Line 4 */
.weak DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */
.weak DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */
.weak DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */
.weak DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */
.weak DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */
.weak DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */
.weak DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */
.weak ADC1_2_IRQHandler /* ADC1_2 */
.weak USB_HP_CAN1_TX_IRQHandler /* USB HP and CAN1 TX */
.weak USB_LP_CAN1_RX0_IRQHandler /* USB LP and CAN1RX0 */
.weak CAN1_RX1_IRQHandler /* CAN1 RX1 */
.weak CAN1_SCE_IRQHandler /* CAN1 SCE */
.weak EXTI9_5_IRQHandler /* EXTI Line 9..5 */
.weak TIM1_BRK_IRQHandler /* TIM1 Break */
.weak TIM1_UP_IRQHandler /* TIM1 Update */
.weak TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */
.weak TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.weak TIM2_IRQHandler /* TIM2 */
.weak TIM3_IRQHandler /* TIM3 */
.weak TIM4_IRQHandler /* TIM4 */
.weak I2C1_EV_IRQHandler /* I2C1 Event */
.weak I2C1_ER_IRQHandler /* I2C1 Error */
.weak I2C2_EV_IRQHandler /* I2C2 Event */
.weak I2C2_ER_IRQHandler /* I2C2 Error */
.weak SPI1_IRQHandler /* SPI1 */
.weak SPI2_IRQHandler /* SPI2 */
.weak USART1_IRQHandler /* USART1 */
.weak USART2_IRQHandler /* USART2 */
.weak USART3_IRQHandler /* USART3 */
.weak EXTI15_10_IRQHandler /* EXTI Line 15..10 */
.weak RTCAlarm_IRQHandler /* RTC Alarm through EXTI Line */
.weak TIM8_BRK_IRQHandler /* TIM8 Break */
.weak TIM8_UP_IRQHandler /* TIM8 Update */
.weak TIM8_TRG_COM_IRQHandler /* TIM8 Trigger and Commutation */
.weak TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.weak RNG_IRQHandler /* RNG */
.weak FSMC_IRQHandler /* FSMC */
.weak SDIO_IRQHandler /* SDIO */
.weak TIM5_IRQHandler /* TIM5 */
.weak SPI3_IRQHandler /* SPI3 */
.weak UART4_IRQHandler /* UART4 */
.weak UART5_IRQHandler /* UART5 */
.weak TIM6_IRQHandler /* TIM6 */
.weak TIM7_IRQHandler /* TIM7 */
.weak DMA2_Channel1_IRQHandler /* DMA2 Channel 1 */
.weak DMA2_Channel2_IRQHandler /* DMA2 Channel 2 */
.weak DMA2_Channel3_IRQHandler /* DMA2 Channel 3 */
.weak DMA2_Channel4_IRQHandler /* DMA2 Channel 4 */
.weak DMA2_Channel5_IRQHandler /* DMA2 Channel 5 */
.weak OTG_FS_IRQHandler /* OTGFS */
.weak UART6_IRQHandler /* UART6 */
.weak UART7_IRQHandler /* UART7 */
.weak UART8_IRQHandler /* UART8 */
.weak TIM9_BRK_IRQHandler /* TIM9 Break */
.weak TIM9_UP_IRQHandler /* TIM9 Update */
.weak TIM9_TRG_COM_IRQHandler /* TIM9 Trigger and Commutation */
.weak TIM9_CC_IRQHandler /* TIM9 Capture Compare */
.weak TIM10_BRK_IRQHandler /* TIM10 Break */
.weak TIM10_UP_IRQHandler /* TIM10 Update */
.weak TIM10_TRG_COM_IRQHandler /* TIM10 Trigger and Commutation */
.weak TIM10_CC_IRQHandler /* TIM10 Capture Compare */
.weak DMA2_Channel6_IRQHandler /* DMA2 Channel 6 */
.weak DMA2_Channel7_IRQHandler /* DMA2 Channel 7 */
.weak DMA2_Channel8_IRQHandler /* DMA2 Channel 8 */
.weak DMA2_Channel9_IRQHandler /* DMA2 Channel 9 */
.weak DMA2_Channel10_IRQHandler /* DMA2 Channel 10 */
.weak DMA2_Channel11_IRQHandler /* DMA2 Channel 11 */
NMI_Handler: 1: j 1b
HardFault_Handler: 1: j 1b
Ecall_M_Mode_Handler: 1: j 1b
Ecall_U_Mode_Handler: 1: j 1b
Break_Point_Handler: 1: j 1b
SysTick_Handler: 1: j 1b
SW_Handler: 1: j 1b
WWDG_IRQHandler: 1: j 1b
PVD_IRQHandler: 1: j 1b
TAMPER_IRQHandler: 1: j 1b
RTC_IRQHandler: 1: j 1b
FLASH_IRQHandler: 1: j 1b
RCC_IRQHandler: 1: j 1b
EXTI0_IRQHandler: 1: j 1b
EXTI1_IRQHandler: 1: j 1b
EXTI2_IRQHandler: 1: j 1b
EXTI3_IRQHandler: 1: j 1b
EXTI4_IRQHandler: 1: j 1b
DMA1_Channel1_IRQHandler: 1: j 1b
DMA1_Channel2_IRQHandler: 1: j 1b
DMA1_Channel3_IRQHandler: 1: j 1b
DMA1_Channel4_IRQHandler: 1: j 1b
DMA1_Channel5_IRQHandler: 1: j 1b
DMA1_Channel6_IRQHandler: 1: j 1b
DMA1_Channel7_IRQHandler: 1: j 1b
ADC1_2_IRQHandler: 1: j 1b
USB_HP_CAN1_TX_IRQHandler: 1: j 1b
USB_LP_CAN1_RX0_IRQHandler: 1: j 1b
CAN1_RX1_IRQHandler: 1: j 1b
CAN1_SCE_IRQHandler: 1: j 1b
EXTI9_5_IRQHandler: 1: j 1b
TIM1_BRK_IRQHandler: 1: j 1b
TIM1_UP_IRQHandler: 1: j 1b
TIM1_TRG_COM_IRQHandler: 1: j 1b
TIM1_CC_IRQHandler: 1: j 1b
TIM2_IRQHandler: 1: j 1b
TIM3_IRQHandler: 1: j 1b
TIM4_IRQHandler: 1: j 1b
I2C1_EV_IRQHandler: 1: j 1b
I2C1_ER_IRQHandler: 1: j 1b
I2C2_EV_IRQHandler: 1: j 1b
I2C2_ER_IRQHandler: 1: j 1b
SPI1_IRQHandler: 1: j 1b
SPI2_IRQHandler: 1: j 1b
USART1_IRQHandler: 1: j 1b
USART2_IRQHandler: 1: j 1b
USART3_IRQHandler: 1: j 1b
EXTI15_10_IRQHandler: 1: j 1b
RTCAlarm_IRQHandler: 1: j 1b
TIM8_BRK_IRQHandler: 1: j 1b
TIM8_UP_IRQHandler: 1: j 1b
TIM8_TRG_COM_IRQHandler: 1: j 1b
TIM8_CC_IRQHandler: 1: j 1b
RNG_IRQHandler: 1: j 1b
FSMC_IRQHandler: 1: j 1b
SDIO_IRQHandler: 1: j 1b
TIM5_IRQHandler: 1: j 1b
SPI3_IRQHandler: 1: j 1b
UART4_IRQHandler: 1: j 1b
UART5_IRQHandler: 1: j 1b
TIM6_IRQHandler: 1: j 1b
TIM7_IRQHandler: 1: j 1b
DMA2_Channel1_IRQHandler: 1: j 1b
DMA2_Channel2_IRQHandler: 1: j 1b
DMA2_Channel3_IRQHandler: 1: j 1b
DMA2_Channel4_IRQHandler: 1: j 1b
DMA2_Channel5_IRQHandler: 1: j 1b
OTG_FS_IRQHandler: 1: j 1b
UART6_IRQHandler: 1: j 1b
UART7_IRQHandler: 1: j 1b
UART8_IRQHandler: 1: j 1b
TIM9_BRK_IRQHandler: 1: j 1b
TIM9_UP_IRQHandler: 1: j 1b
TIM9_TRG_COM_IRQHandler: 1: j 1b
TIM9_CC_IRQHandler: 1: j 1b
TIM10_BRK_IRQHandler: 1: j 1b
TIM10_UP_IRQHandler: 1: j 1b
TIM10_TRG_COM_IRQHandler: 1: j 1b
TIM10_CC_IRQHandler: 1: j 1b
DMA2_Channel6_IRQHandler: 1: j 1b
DMA2_Channel7_IRQHandler: 1: j 1b
DMA2_Channel8_IRQHandler: 1: j 1b
DMA2_Channel9_IRQHandler: 1: j 1b
DMA2_Channel10_IRQHandler: 1: j 1b
DMA2_Channel11_IRQHandler: 1: j 1b
.section .text.handle_reset,"ax",@progbits
.weak handle_reset
.align 1
handle_reset:
.option push
.option norelax
la gp, __global_pointer$
.option pop
1:
la sp, _eusrstack
2:
/* Load data section from flash to RAM */
la a0, _data_lma
la a1, _data_vma
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
/* Clear bss section */
la a0, _sbss
la a1, _ebss
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
li t0, 0x1f
csrw 0xbc0, t0
/* Enable nested and hardware stack */
li t0, 0x0b
csrw 0x804, t0
/* Enable floating point and interrupt */
li t0, 0x6088
csrs mstatus, t0
la t0, _vector_base
ori t0, t0, 3
csrw mtvec, t0
jal SystemInit
la t0, main
csrw mepc, t0
mret

View File

@ -6023,7 +6023,9 @@ size_t mg_print_esc(void (*out)(char, void *), void *arg, va_list *ap) {
#if defined(__GNUC__) || defined(__clang__) #if (defined(__GNUC__) && (__GNUC__ > 4) || \
(defined(__GNUC_MINOR__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
defined(__clang__)
#define MG_MEMORY_BARRIER() __sync_synchronize() #define MG_MEMORY_BARRIER() __sync_synchronize()
#elif defined(_MSC_VER) && _MSC_VER >= 1700 #elif defined(_MSC_VER) && _MSC_VER >= 1700
#define MG_MEMORY_BARRIER() MemoryBarrier() #define MG_MEMORY_BARRIER() MemoryBarrier()
@ -14433,7 +14435,8 @@ struct mg_tcpip_driver mg_tcpip_driver_same54 = {
#endif #endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_STM32F) && MG_ENABLE_DRIVER_STM32F #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_STM32F) && \
MG_ENABLE_DRIVER_STM32F
struct stm32f_eth { struct stm32f_eth {
volatile uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR, volatile uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR,
MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR, MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR,
@ -14462,7 +14465,7 @@ static uint8_t s_txno; // Current TX descriptor
static uint8_t s_rxno; // Current RX descriptor static uint8_t s_rxno; // Current RX descriptor
static struct mg_tcpip_if *s_ifp; // MIP interface static struct mg_tcpip_if *s_ifp; // MIP interface
enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1, PHY_CSCR = 31 }; enum { PHY_BCR = 0, PHY_BSR = 1, PHY_ID1 = 2, PHY_ID2 = 3, PHY_CSCR = 31 };
static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) { static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
ETH->MACMIIAR &= (7 << 2); ETH->MACMIIAR &= (7 << 2);
@ -14537,6 +14540,7 @@ static int guess_mdc_cr(void) {
static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) { static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_stm32f_data *d = struct mg_tcpip_driver_stm32f_data *d =
(struct mg_tcpip_driver_stm32f_data *) ifp->driver_data; (struct mg_tcpip_driver_stm32f_data *) ifp->driver_data;
uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
s_ifp = ifp; s_ifp = ifp;
// Init RX descriptors // Init RX descriptors
@ -14569,8 +14573,8 @@ static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause
// ETH->MACFFR = MG_BIT(31); // Receive all // ETH->MACFFR = MG_BIT(31); // Receive all
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(15)); // Reset PHY eth_write_phy(phy_addr, PHY_BCR, MG_BIT(15)); // Reset PHY
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(12)); // Set autonegotiation eth_write_phy(phy_addr, PHY_BCR, MG_BIT(12)); // Set autonegotiation
ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc; // RX descriptors ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc; // RX descriptors
ETH->DMAIER = MG_BIT(6) | MG_BIT(16); // RIE, NISE ETH->DMAIER = MG_BIT(6) | MG_BIT(16); // RIE, NISE
@ -14579,6 +14583,9 @@ static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
ETH->DMAOMR = ETH->DMAOMR =
MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
MG_DEBUG(("PHY ID: %#04hx %#04hx", eth_read_phy(phy_addr, PHY_ID1),
eth_read_phy(phy_addr, PHY_ID2)));
// MAC address filtering // MAC address filtering
ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4]; ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) | ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) |
@ -14588,7 +14595,7 @@ static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
} }
static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len, static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len,
struct mg_tcpip_if *ifp) { struct mg_tcpip_if *ifp) {
if (len > sizeof(s_txbuf[s_txno])) { if (len > sizeof(s_txbuf[s_txno])) {
MG_ERROR(("Frame too big, %ld", (long) len)); MG_ERROR(("Frame too big, %ld", (long) len));
len = 0; // Frame is too big len = 0; // Frame is too big
@ -14611,10 +14618,13 @@ static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len,
} }
static bool mg_tcpip_driver_stm32f_up(struct mg_tcpip_if *ifp) { static bool mg_tcpip_driver_stm32f_up(struct mg_tcpip_if *ifp) {
uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); struct mg_tcpip_driver_stm32f_data *d =
(struct mg_tcpip_driver_stm32f_data *) ifp->driver_data;
uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
uint32_t bsr = eth_read_phy(phy_addr, PHY_BSR);
bool up = bsr & MG_BIT(2) ? 1 : 0; bool up = bsr & MG_BIT(2) ? 1 : 0;
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR); uint32_t scsr = eth_read_phy(phy_addr, PHY_CSCR);
// tmp = reg with flags set to the most likely situation: 100M full-duplex // tmp = reg with flags set to the most likely situation: 100M full-duplex
// if(link is slow or half) set flags otherwise // if(link is slow or half) set flags otherwise
// reg = tmp // reg = tmp
@ -14655,9 +14665,9 @@ void ETH_IRQHandler(void) {
ETH->DMARPDR = 0; // and resume RX ETH->DMARPDR = 0; // and resume RX
} }
struct mg_tcpip_driver mg_tcpip_driver_stm32f = {mg_tcpip_driver_stm32f_init, struct mg_tcpip_driver mg_tcpip_driver_stm32f = {
mg_tcpip_driver_stm32f_tx, NULL, mg_tcpip_driver_stm32f_init, mg_tcpip_driver_stm32f_tx, NULL,
mg_tcpip_driver_stm32f_up}; mg_tcpip_driver_stm32f_up};
#endif #endif
#ifdef MG_ENABLE_LINES #ifdef MG_ENABLE_LINES

View File

@ -2889,6 +2889,8 @@ struct mg_tcpip_driver_stm32f_data {
// 216-310 MHz HCLK/124 5 // 216-310 MHz HCLK/124 5
// 110, 111 Reserved // 110, 111 Reserved
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
uint8_t phy_addr; // PHY address
}; };

View File

@ -1,6 +1,7 @@
#include "net_builtin.h" #include "net_builtin.h"
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_STM32F) && MG_ENABLE_DRIVER_STM32F #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_STM32F) && \
MG_ENABLE_DRIVER_STM32F
struct stm32f_eth { struct stm32f_eth {
volatile uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR, volatile uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR,
MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR, MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR,
@ -29,7 +30,7 @@ static uint8_t s_txno; // Current TX descriptor
static uint8_t s_rxno; // Current RX descriptor static uint8_t s_rxno; // Current RX descriptor
static struct mg_tcpip_if *s_ifp; // MIP interface static struct mg_tcpip_if *s_ifp; // MIP interface
enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1, PHY_CSCR = 31 }; enum { PHY_BCR = 0, PHY_BSR = 1, PHY_ID1 = 2, PHY_ID2 = 3, PHY_CSCR = 31 };
static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) { static uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
ETH->MACMIIAR &= (7 << 2); ETH->MACMIIAR &= (7 << 2);
@ -104,6 +105,7 @@ static int guess_mdc_cr(void) {
static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) { static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_stm32f_data *d = struct mg_tcpip_driver_stm32f_data *d =
(struct mg_tcpip_driver_stm32f_data *) ifp->driver_data; (struct mg_tcpip_driver_stm32f_data *) ifp->driver_data;
uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
s_ifp = ifp; s_ifp = ifp;
// Init RX descriptors // Init RX descriptors
@ -136,8 +138,8 @@ static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause
// ETH->MACFFR = MG_BIT(31); // Receive all // ETH->MACFFR = MG_BIT(31); // Receive all
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(15)); // Reset PHY eth_write_phy(phy_addr, PHY_BCR, MG_BIT(15)); // Reset PHY
eth_write_phy(PHY_ADDR, PHY_BCR, MG_BIT(12)); // Set autonegotiation eth_write_phy(phy_addr, PHY_BCR, MG_BIT(12)); // Set autonegotiation
ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc; // RX descriptors ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc; // RX descriptors
ETH->DMAIER = MG_BIT(6) | MG_BIT(16); // RIE, NISE ETH->DMAIER = MG_BIT(6) | MG_BIT(16); // RIE, NISE
@ -146,6 +148,9 @@ static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
ETH->DMAOMR = ETH->DMAOMR =
MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
MG_DEBUG(("PHY ID: %#04hx %#04hx", eth_read_phy(phy_addr, PHY_ID1),
eth_read_phy(phy_addr, PHY_ID2)));
// MAC address filtering // MAC address filtering
ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4]; ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) | ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) |
@ -155,7 +160,7 @@ static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
} }
static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len, static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len,
struct mg_tcpip_if *ifp) { struct mg_tcpip_if *ifp) {
if (len > sizeof(s_txbuf[s_txno])) { if (len > sizeof(s_txbuf[s_txno])) {
MG_ERROR(("Frame too big, %ld", (long) len)); MG_ERROR(("Frame too big, %ld", (long) len));
len = 0; // Frame is too big len = 0; // Frame is too big
@ -178,10 +183,13 @@ static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len,
} }
static bool mg_tcpip_driver_stm32f_up(struct mg_tcpip_if *ifp) { static bool mg_tcpip_driver_stm32f_up(struct mg_tcpip_if *ifp) {
uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); struct mg_tcpip_driver_stm32f_data *d =
(struct mg_tcpip_driver_stm32f_data *) ifp->driver_data;
uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
uint32_t bsr = eth_read_phy(phy_addr, PHY_BSR);
bool up = bsr & MG_BIT(2) ? 1 : 0; bool up = bsr & MG_BIT(2) ? 1 : 0;
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
uint32_t scsr = eth_read_phy(PHY_ADDR, PHY_CSCR); uint32_t scsr = eth_read_phy(phy_addr, PHY_CSCR);
// tmp = reg with flags set to the most likely situation: 100M full-duplex // tmp = reg with flags set to the most likely situation: 100M full-duplex
// if(link is slow or half) set flags otherwise // if(link is slow or half) set flags otherwise
// reg = tmp // reg = tmp
@ -222,7 +230,7 @@ void ETH_IRQHandler(void) {
ETH->DMARPDR = 0; // and resume RX ETH->DMARPDR = 0; // and resume RX
} }
struct mg_tcpip_driver mg_tcpip_driver_stm32f = {mg_tcpip_driver_stm32f_init, struct mg_tcpip_driver mg_tcpip_driver_stm32f = {
mg_tcpip_driver_stm32f_tx, NULL, mg_tcpip_driver_stm32f_init, mg_tcpip_driver_stm32f_tx, NULL,
mg_tcpip_driver_stm32f_up}; mg_tcpip_driver_stm32f_up};
#endif #endif

View File

@ -13,4 +13,6 @@ struct mg_tcpip_driver_stm32f_data {
// 216-310 MHz HCLK/124 5 // 216-310 MHz HCLK/124 5
// 110, 111 Reserved // 110, 111 Reserved
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
uint8_t phy_addr; // PHY address
}; };

View File

@ -1,7 +1,9 @@
#include "queue.h" #include "queue.h"
#include "util.h" #include "util.h"
#if defined(__GNUC__) || defined(__clang__) #if (defined(__GNUC__) && (__GNUC__ > 4) || \
(defined(__GNUC_MINOR__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
defined(__clang__)
#define MG_MEMORY_BARRIER() __sync_synchronize() #define MG_MEMORY_BARRIER() __sync_synchronize()
#elif defined(_MSC_VER) && _MSC_VER >= 1700 #elif defined(_MSC_VER) && _MSC_VER >= 1700
#define MG_MEMORY_BARRIER() MemoryBarrier() #define MG_MEMORY_BARRIER() MemoryBarrier()