surenyi
6 months ago
9 changed files with 423 additions and 20 deletions
@ -0,0 +1,90 @@ |
|||
/*
|
|||
* port to ZD32F40X by surenyi (2024/04/26) |
|||
*/ |
|||
|
|||
#include <stdint.h> |
|||
#include "board_config.h" |
|||
|
|||
#define _SCB_BASE (0xE000E010UL) |
|||
#define _SYSTICK_CTRL (*(uint32_t *)(_SCB_BASE + 0x0)) |
|||
#define _SYSTICK_LOAD (*(uint32_t *)(_SCB_BASE + 0x4)) |
|||
#define _SYSTICK_VAL (*(uint32_t *)(_SCB_BASE + 0x8)) |
|||
#define _SYSTICK_CALIB (*(uint32_t *)(_SCB_BASE + 0xC)) |
|||
#define _SYSTICK_PRI (*(uint8_t *)(0xE000ED23UL)) |
|||
|
|||
// Updates the variable SystemCoreClock and must be called
|
|||
// whenever the core clock is changed during program execution.
|
|||
extern void SystemCoreClockUpdate(void); |
|||
|
|||
// Holds the system core clock, which is the system clock
|
|||
// frequency supplied to the SysTick timer and the processor
|
|||
// core clock.
|
|||
extern uint32_t SystemCoreClock; |
|||
|
|||
static uint32_t _SysTick_Config(uint32_t ticks) |
|||
{ |
|||
if ((ticks - 1) > 0xFFFFFF) { |
|||
return 1; |
|||
} |
|||
|
|||
_SYSTICK_LOAD = ticks - 1; |
|||
_SYSTICK_PRI = 0xFF; |
|||
_SYSTICK_VAL = 0; |
|||
_SYSTICK_CTRL = 0x07; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void delay_microseconds(uint32_t us) |
|||
{ |
|||
uint32_t start, now, delta, reload, us_tick; |
|||
|
|||
start = _SYSTICK_VAL; |
|||
reload = _SYSTICK_LOAD; |
|||
us_tick = (SystemCoreClock / 1000000UL) * us; |
|||
|
|||
do { |
|||
now = _SYSTICK_VAL; |
|||
delta = (start > now) ? (start - now) : (reload + start - now); |
|||
} while (delta < us_tick); |
|||
} |
|||
|
|||
/**
|
|||
* This function will initial your board. |
|||
*/ |
|||
extern int main(); |
|||
void entry() |
|||
{ |
|||
/* System Clock Update */ |
|||
SystemCoreClockUpdate(); |
|||
|
|||
/* System Tick Configuration */ |
|||
_SysTick_Config(SystemCoreClock / BOARD_TICK_PER_SECOND); |
|||
|
|||
main(); |
|||
} |
|||
|
|||
volatile uint64_t __current_ticks; |
|||
|
|||
void SysTick_Handler(void) |
|||
{ |
|||
++__current_ticks; |
|||
} |
|||
|
|||
uint64_t millis() |
|||
{ |
|||
return __current_ticks * (SystemCoreClock / BOARD_TICK_PER_SECOND); |
|||
} |
|||
|
|||
/* Default empty handler */ |
|||
static void Dummy_Handler(void) |
|||
{ |
|||
#if defined DEBUG |
|||
__BKPT(3); |
|||
#endif |
|||
for (;;) { |
|||
} |
|||
} |
|||
|
|||
void PendSV_Handler(void) __attribute__((weak, alias("Dummy_Handler"))); |
|||
void HardFault_Handler(void) __attribute__((weak, alias("Dummy_Handler"))); |
@ -0,0 +1,9 @@ |
|||
#pragma once |
|||
|
|||
#define BOARD_HAS_USART1 1 |
|||
#define BOARD_HEAP_SIZE (16384) |
|||
#define BOARD_TICK_PER_SECOND (1000) |
|||
|
|||
#define BOARD_APPLICATION_ENTRY (0x08080000) |
|||
|
|||
#define BOARD_CONSOLE (&serial0) |
@ -0,0 +1,67 @@ |
|||
#include "board_config.h" |
|||
#include <stdio.h> |
|||
#include "stm32f4xx.h" |
|||
#include "bkp_sram.h" |
|||
#include "serial.h" |
|||
|
|||
int go(unsigned long vect) |
|||
{ |
|||
volatile unsigned int *ptr = (volatile unsigned int *)vect; |
|||
register unsigned int stack = ptr[0]; |
|||
register unsigned int addr = ptr[1]; |
|||
|
|||
// printf("stack: %x, entry: %x, [%x, %x]\r\n", stack, addr, (stack & 0x2ffC0000), (stack & 0x1ffe0000));
|
|||
// printf("off: %x\n", (vect - NVIC_VectTab_FLASH));
|
|||
if (((stack & 0x2ffc0000) == 0x20000000) /* SRAM */ || ((stack & 0x1ffe0000) == 0x10000000) /* CCMRAM */) { |
|||
/* disable global irq */ |
|||
__disable_irq(); |
|||
|
|||
NVIC_SetVectorTable(NVIC_VectTab_FLASH, (vect - NVIC_VectTab_FLASH)); |
|||
|
|||
/* set the stack pointer, then run */ |
|||
__asm__ __volatile__("msr msp, %[tos]\n\t" |
|||
"msr psp, %[tos]\n\t" |
|||
"isb sy\n\t" |
|||
"dsb sy\n\t" |
|||
"blx %[app]\n\t" |
|||
: |
|||
: [tos] "r"(stack), [app] "r"(addr)); |
|||
} |
|||
return -1; |
|||
} |
|||
|
|||
void early_boot_sketch() |
|||
{ |
|||
unsigned int magic; |
|||
|
|||
bkp_sram_init(); |
|||
magic = bkp_sram_read(MAGIC_POS); |
|||
if (magic != MAGIC_BOOT) { |
|||
go(BOARD_APPLICATION_ENTRY); |
|||
} |
|||
} |
|||
|
|||
int console_read(void *ptr, int len) |
|||
{ |
|||
return -1; |
|||
} |
|||
|
|||
int console_write(const void *ptr, int len) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
void lowlevel_hw_init() |
|||
{ |
|||
serial_setup(BOARD_CONSOLE, 115200, 8, SERIAL_STOPBITS_1); |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
printf("BootLoader\r\n"); |
|||
|
|||
while (1) |
|||
; |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,225 @@ |
|||
/*
|
|||
* syscall stub to newlib |
|||
*/ |
|||
#include <stdlib.h> |
|||
#include <sys/unistd.h> |
|||
#include <sys/stat.h> |
|||
#include <errno.h> |
|||
#include "stm32f4xx.h" |
|||
#include "config.h" |
|||
#undef errno |
|||
extern int errno; |
|||
|
|||
int * __errno() |
|||
{ |
|||
return &errno; |
|||
} |
|||
|
|||
/*
|
|||
* Environment variables. |
|||
* A pointer to a list of environment variables and their values. For a minimal |
|||
* environment, this empty list is adequate: |
|||
*/ |
|||
|
|||
char *__env[1] = { 0 }; |
|||
char **environ = __env; |
|||
|
|||
__attribute__((weak)) int console_read(void *ptr, int len) |
|||
{ |
|||
errno = EBADF; |
|||
return -1; |
|||
} |
|||
|
|||
static void itm_send(const char *ptr, int n) |
|||
{ |
|||
while (n > 0) { |
|||
ITM_SendChar(*ptr); |
|||
++ptr; |
|||
--n; |
|||
} |
|||
} |
|||
|
|||
__attribute__((weak)) int console_write(const void *ptr, int len) |
|||
{ |
|||
itm_send(ptr, len); |
|||
return len; |
|||
} |
|||
|
|||
/*
|
|||
* Close a file. |
|||
*/ |
|||
int _close(int file) |
|||
{ |
|||
errno = EBADF; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Transfer control to a new process. |
|||
*/ |
|||
int _execve(char *name, char **argv, char **env) |
|||
{ |
|||
errno = ENOMEM; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Exit a program without cleaning up files. |
|||
*/ |
|||
void _exit( int code ) |
|||
{ |
|||
/* Should we force a system reset? */ |
|||
while (1) { |
|||
; |
|||
} |
|||
} |
|||
|
|||
/*
|
|||
* Create a new process. |
|||
*/ |
|||
int _fork(void) |
|||
{ |
|||
errno = EAGAIN; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Status of an open file. |
|||
*/ |
|||
int _fstat(int file, struct stat *st) |
|||
{ |
|||
if ((STDOUT_FILENO == file) || (STDERR_FILENO == file) || (STDIN_FILENO)) { |
|||
st->st_mode = S_IFCHR; |
|||
return 0; |
|||
} |
|||
errno = EBADF; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Process-ID |
|||
*/ |
|||
int _getpid(void) |
|||
{ |
|||
return 1; |
|||
} |
|||
|
|||
/*
|
|||
* Query whether output stream is a terminal. |
|||
*/ |
|||
int _isatty(int file) |
|||
{ |
|||
if ((STDOUT_FILENO == file) || (STDERR_FILENO == file) || (STDIN_FILENO)) { |
|||
return 1; |
|||
} |
|||
errno = EBADF; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Send a signal. |
|||
*/ |
|||
int _kill(int pid, int sig) |
|||
{ |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Establish a new name for an existing file. |
|||
*/ |
|||
int _link(char *old, char *new) |
|||
{ |
|||
errno = EMLINK; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Set position in a file. |
|||
*/ |
|||
int _lseek(int file, int ptr, int dir) |
|||
{ |
|||
if ((STDOUT_FILENO == file) || (STDERR_FILENO == file) || (STDIN_FILENO)) { |
|||
return 0; |
|||
} |
|||
errno = EBADF; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Open a file. |
|||
*/ |
|||
int _open(const char *name, int flags, int mode) |
|||
{ |
|||
errno = ENOSYS; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Read from a file. |
|||
*/ |
|||
int _read(int file, char *ptr, int len) |
|||
{ |
|||
if (STDIN_FILENO == file) |
|||
return console_read(ptr, len); |
|||
errno = EBADF; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Write to a file. libc subroutines will use this system routine for output to |
|||
* all files, including stdout梥o if you need to generate any output, for |
|||
* example to a serial port for debugging, you should make your minimal write |
|||
* capable of doing this. |
|||
*/ |
|||
int _write_r( void * reent, int file, char * ptr, int len ) |
|||
{ |
|||
if ((STDOUT_FILENO == file) || (STDERR_FILENO == file)) { |
|||
return console_write(ptr, len); |
|||
} |
|||
errno = EBADF; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Increase program data space. As malloc and related functions depend on this, |
|||
* it is useful to have a working implementation. The following suffices for a |
|||
* standalone system; it exploits the symbol _end automatically defined by the |
|||
* GNU linker. |
|||
*/ |
|||
static char __heap[BOARD_HEAP_SIZE] __attribute__((section(".heap._sbrk,\"aw\",%nobits@"))); |
|||
|
|||
caddr_t _sbrk(int incr) |
|||
{ |
|||
static char *heap_start = __heap; |
|||
char *prev_heap_end; |
|||
|
|||
prev_heap_end = heap_start; |
|||
if (heap_start + incr > (__heap + BOARD_HEAP_SIZE)) { |
|||
_write_r ((void *)0, 1, "heap and stack collision\r\n", 26); |
|||
return (caddr_t)NULL; |
|||
} |
|||
|
|||
heap_start += incr; |
|||
|
|||
return (caddr_t) prev_heap_end; |
|||
} |
|||
|
|||
/*
|
|||
* Remove a file's directory entry. |
|||
*/ |
|||
int _unlink(char *name) |
|||
{ |
|||
errno = ENOENT; |
|||
return -1; |
|||
} |
|||
|
|||
/*
|
|||
* Wait for a child process. |
|||
*/ |
|||
int _wait(int *status) |
|||
{ |
|||
errno = ECHILD; |
|||
return -1; |
|||
} |
|||
|
@ -0,0 +1,22 @@ |
|||
#include <rtthread.h> |
|||
#include <finsh.h> |
|||
#include <finsh_api.h> |
|||
#include "stm32f4xx_flash.h" |
|||
#include "stm32f4xx.h" |
|||
|
|||
static int flash_option(int argc, char *argv[]) |
|||
{ |
|||
rt_uint8_t option; |
|||
|
|||
if (argc == 1) { |
|||
option = *(volatile rt_uint8_t *)(OPTCR_BYTE0_ADDRESS); |
|||
rt_kprintf("%04x\n", option); |
|||
} else if (argc >= 2) { |
|||
option = strtoul(argv[1], NULL, 16); |
|||
FLASH_Unlock(); |
|||
FLASH_Lock(); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
MSH_CMD_EXPORT(flash_option, flash option); |
@ -1,15 +0,0 @@ |
|||
# gdbscript: script for download elf file |
|||
# gdb --batch -nx -x gdbscript.txt |
|||
|
|||
set confirm off |
|||
target remote localhost:2331 |
|||
set mem inaccessible-by-default off |
|||
monitor flash device = %DEVICE_TYPE% |
|||
monitor flash download = 1 |
|||
monitor endian little |
|||
monitor speed auto |
|||
monitor reset |
|||
monitor sleep 100 |
|||
load %TARGET_FILE% |
|||
monitor go |
|||
quit |
Loading…
Reference in new issue