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