diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2016-05-27 17:17:44 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2016-05-27 17:17:44 +0900 |
commit | 960921f537adf6424c266664dcf1575c08ef0623 (patch) | |
tree | 799a2bbed8b436542e73035b1b2f2ee4908a1690 /example-fs-bb48 | |
parent | f2a8b01607aca8f41cc5f50b18bea74d65766731 (diff) |
example-fs-bb48: SYS implementation
Diffstat (limited to 'example-fs-bb48')
-rw-r--r-- | example-fs-bb48/ABOUT-SYS | 79 | ||||
-rw-r--r-- | example-fs-bb48/Makefile | 4 | ||||
-rw-r--r-- | example-fs-bb48/command.c | 50 | ||||
-rw-r--r-- | example-fs-bb48/crc32.c | 22 | ||||
-rw-r--r-- | example-fs-bb48/crc32.h | 8 | ||||
-rw-r--r-- | example-fs-bb48/sample.ld | 27 | ||||
-rw-r--r-- | example-fs-bb48/sys.c | 175 | ||||
-rw-r--r-- | example-fs-bb48/sys.h | 38 |
8 files changed, 339 insertions, 64 deletions
diff --git a/example-fs-bb48/ABOUT-SYS b/example-fs-bb48/ABOUT-SYS index d3c79b0..15fb61c 100644 --- a/example-fs-bb48/ABOUT-SYS +++ b/example-fs-bb48/ABOUT-SYS @@ -1,6 +1,10 @@ Consideration about SYS and the first pages of flash ROM ======================================================== +Now, I'm developing something like SYS for Kinetis L MCU, so, I write +this document. + + About SYS on STM32F103 ====================== @@ -15,10 +19,6 @@ STM32F030, as well as STM32F103. But, it wouldn't be useful for STM32F030. In fact, the file example-fsm-55/sys.c has name sys.c but it doesn't include any system routines. -Now, I'm developing something like SYS for Kinetis L MCU, so, I write -this document. - - The original issue was: (1) When it's protected, STM32F103 can't change the first 4KiB of @@ -77,7 +77,7 @@ and here is the list of all. * flash ROM access routines unlock - write word + write halfword erase page brank check write page @@ -114,6 +114,75 @@ For Kinetis L, because it's ROM has the original firmware upgrade support by the vendor (though USB HID), all that we needed for firmware upgrade would be just erasing to factory settings. +And it has no limitation like STM32F103's first 4KiB flash ROM. +All pages can be updated at run time. + +Nevertheless, the first two pages (2KiB) of KL27Z is still difficult +to use. + +So, I decide to introduce something like SYS for Kinetis L. + + +* Layout + +Three pages (3KiB) usage: + + ------------ The first page + End of RAM <-- not used but hardware define this + Address of reset entry + sys_version + sys_board_info (id, name) + sys_vector + + + SYS... + + ------------ The second page + FLASH CONFIG: 16-byte + Reset entry function + CRC-32 routine + CRC-32 table (768-byte of CRC-32 table) + + ------------ The third page + MAGIC 256-byte (256-byte of the last part of CRC-32 table) + ... + vectors (MSP, reset, ...) + ... + + +* data: Board identification + + sys_version + sys_board_id + sys_board_name ; null terminated + +* Board specific routines + + * mcu/board lower level + clock_init + gpio_init + + * led + set_led + +* data: Board independent routines + + * flash ROM access code to be loaded on to RAM + +* system reset routine??? + + nvic_system_reset + + +* data: vectors for routines and data + sys_version + sys_board_id + address of set_led + address of clock_init + address of gpio_init + address of sys_board_name + address of ... + -- diff --git a/example-fs-bb48/Makefile b/example-fs-bb48/Makefile index c806c9c..52782cc 100644 --- a/example-fs-bb48/Makefile +++ b/example-fs-bb48/Makefile @@ -6,7 +6,7 @@ PROJECT = sample CHOPSTX = .. LDSCRIPT= sample.ld -CSRC = sample.c first-pages.c usb_kl27z.c usb-cdc.c adc_kl27z.c command.c +CSRC = sample.c sys.c usb_kl27z.c usb-cdc.c adc_kl27z.c command.c ################################### CROSS = arm-none-eabi- @@ -16,7 +16,7 @@ OBJCOPY = $(CROSS)objcopy MCU = cortex-m0plus CWARN = -Wall -Wextra -Wstrict-prototypes -DEFS = -DFREE_STANDING -DMHZ=48 +DEFS = -DFREE_STANDING -DMHZ=48 -DHAVE_SYS_H OPT = -O3 -Os -g LIBS = diff --git a/example-fs-bb48/command.c b/example-fs-bb48/command.c index b13ca71..08e6b47 100644 --- a/example-fs-bb48/command.c +++ b/example-fs-bb48/command.c @@ -7,6 +7,8 @@ #include "adc.h" static int adc_initialized = 0; #endif +#include "sys.h" +#include "board.h" struct command_table { @@ -33,6 +35,7 @@ static const char *help_string = #ifdef ADC_SUPPORT "adc\r\n" #endif + "sysinfo\r\n" "help\r\n"; static char hexchar (uint8_t x) @@ -197,6 +200,8 @@ cmd_mww (struct tty *tty, const char *line) #ifdef CRC32_SUPPORT #include "crc32.h" +static unsigned int crc_value; + static void cmd_crc32 (struct tty *tty, const char *line) { @@ -204,10 +209,10 @@ cmd_crc32 (struct tty *tty, const char *line) char string[10]; char *s; - crc32_init (); + crc32_init (&crc_value); while (*line) - crc32_u8 (*line++); - v = crc32_value () ^ 0xffffffff; + crc32_u8 (&crc_value, *line++); + v = crc_value ^ 0xffffffff; s = compose_hex (string, v); *s++ = '\r'; @@ -265,6 +270,44 @@ cmd_adc (struct tty *tty, const char *line) #endif static void +cmd_sysinfo (struct tty *tty, const char *line) +{ + char output[73]; + char *s; + int i; + + (void)line; + memcpy (output, "SYS version: ", 13); + s = output + 13; + *s++ = sys_version[2]; + *s++ = sys_version[4]; + *s++ = sys_version[6]; + *s++ = '\r'; + *s++ = '\n'; + tty_send (tty, (uint8_t *)output, s - output); + + memcpy (output, "Board ID: ", 10); + s = output + 10; + s = compose_hex (s, sys_board_id); + *s++ = '\r'; + *s++ = '\n'; + tty_send (tty, (uint8_t *)output, s - output); + + memcpy (output, "Board name: ", 12); + s = output + 12; + for (i = 0; i < (int)sizeof (output) - 2; i ++) + if ((*s = sys_board_name[i]) == 0) + break; + else + s++; + + *s++ = '\r'; + *s++ = '\n'; + tty_send (tty, (uint8_t *)output, s - output); +} + + +static void cmd_help (struct tty *tty, const char *line) { (void)line; @@ -281,6 +324,7 @@ struct command_table command_table[] = { #ifdef ADC_SUPPORT { "adc", cmd_adc }, #endif + { "sysinfo", cmd_sysinfo }, { "help", cmd_help }, }; diff --git a/example-fs-bb48/crc32.c b/example-fs-bb48/crc32.c new file mode 100644 index 0000000..4335295 --- /dev/null +++ b/example-fs-bb48/crc32.c @@ -0,0 +1,22 @@ +const unsigned int *const crc32_table= (const unsigned int *const)0x00000480; + +void +crc32_init (unsigned int *p) +{ + *p = 0xffffffff; +} + +static void +crc32_u8 (unsigned int *p, unsigned char v) +{ + *p = crc32_table[(*p & 0xff) ^ v] ^ (*p >> 8); +} + +void +crc32_u32 (unsigned int *p, unsigned int u) +{ + crc32_u8 (p, u & 0xff); + crc32_u8 (p, (u >> 8)& 0xff); + crc32_u8 (p, (u >> 16)& 0xff); + crc32_u8 (p, (u >> 24)& 0xff); +} diff --git a/example-fs-bb48/crc32.h b/example-fs-bb48/crc32.h index c31ba0f..3c58a26 100644 --- a/example-fs-bb48/crc32.h +++ b/example-fs-bb48/crc32.h @@ -1,5 +1,3 @@ -void crc32_init (void); -void crc32_u8 (unsigned char); -void crc32_u32 (unsigned int); - -unsigned int crc32_value (void); +void crc32_init (unsigned int *); +void crc32_u8 (unsigned int *, unsigned char); +void crc32_u32 (unsigned int *, unsigned int); diff --git a/example-fs-bb48/sample.ld b/example-fs-bb48/sample.ld index 7a3a09f..43c6e4a 100644 --- a/example-fs-bb48/sample.ld +++ b/example-fs-bb48/sample.ld @@ -23,17 +23,28 @@ SECTIONS _text = .; - .f2 : ALIGN(16) SUBALIGN(8) + .text : ALIGN(16) SUBALIGN(8) { KEEP(*(.first_page.first_words)) - KEEP(*(.first_page)) - KEEP(*(.flash_config)) - KEEP(*(.flash_config_page)) - } > flash =0xffffffff - - .text : ALIGN(16) SUBALIGN(16) - { + KEEP(*(.sys.version)) + KEEP(*(.sys.board_info)) + KEEP(*(.sys.vectors)) + build/sys.o(.text) + build/sys.o(.text.*) + build/sys.o(.rodata) + build/sys.o(.rodata.*) . = ALIGN(1024); + KEEP(*(.flash_config)) + KEEP(*(.fixed_function.crc32_init)) + KEEP(*(.fixed_function.crc32_u8)) + KEEP(*(.fixed_function.crc32_u32)) + KEEP(*(.reset.entry)) + /* + * Because of alignment requirement + * of startup.vectors, align to 256. + */ + . = ALIGN(256); + KEEP(*(.crc32_table)) KEEP(*(.startup.vectors)) . = ALIGN(16); *(.text.startup.*) diff --git a/example-fs-bb48/sys.c b/example-fs-bb48/sys.c index a587098..d700ec8 100644 --- a/example-fs-bb48/sys.c +++ b/example-fs-bb48/sys.c @@ -1,5 +1,5 @@ /* - * first-pages.c - First pages for MKL27Z256. + * sys.c - First pages for MKL27Z256. * * Copyright (C) 2016 Flying Stone Technology * Author: NIIBE Yutaka <gniibe@fsij.org> @@ -18,22 +18,37 @@ * data for predefined purposes. */ - #include <stdint.h> +#include <stdlib.h> +#include "board.h" + +#include "mcu/clk_gpio_init-kl.c" -extern uint8_t __main_stack_end__; +static void +set_led (int on) +{ + if (on) + GPIOB->PCOR = (1 << 0); /* PTB0: Clear: Light on */ + else + GPIOB->PSOR = (1 << 0); /* PTB0: Set : Light off */ +} + +#define ADDR_VECTORS (0x00000900) +#define ADDR_SCR_VTOR 0xe000ed08 -static void __attribute__ ((naked,section(".flash_config_page"))) +static void __attribute__ ((naked,section(".reset.entry"))) reset (void) { - uint32_t r3 = 0xe000ed08; + uint32_t r3 = ADDR_SCR_VTOR; asm volatile ("str %2, [%0]\n\t" /* Set SCR->VTOR */ - "ldr %0, [%2, #4]\n\t" /* Jump to the entry */ - "bx %0\n\t" + "ldr %0, [%2]\n\t" /* Stack address */ + "msr MSP, %0\n\t" /* Exception handler stack. */ + "ldr %0, [%2, #4]\n\t" /* The entry address */ + "bx %0\n\t" /* Jump to the entry */ ".align 2\n" : "=r" (r3) - : "0" (r3), "r" (0x00000800) + : "0" (r3), "r" (ADDR_VECTORS) : "memory"); /* Never reach here. */ @@ -42,16 +57,18 @@ reset (void) static uint32_t stack_entry[] __attribute__ ((section(".first_page.first_words"),used)) = { - (uint32_t)(&__main_stack_end__ - 32), + /* Since MSP are soon modified in RESET, we put 0 here. */ + 0, (uint32_t)reset, }; /* - * NOTE: We don't use backdoor comparison key. The area is used by - * CRC32 table. + * Here comes SYS routines and data. */ + static uint32_t flash_config[] __attribute__ ((section(".flash_config"),used)) = { + 0xffffffff, 0xffffffff, /* Comparison Key */ 0xffffffff, /* Protection bytes */ 0xffff3ffe, /* FSEC=0xfe, FOPT=0x3f */ /* FOPT=0x3f: @@ -66,12 +83,96 @@ flash_config[] __attribute__ ((section(".flash_config"),used)) = { /* * CRC32 calculation routines. */ +void __attribute__ ((naked,section(".fixed_function.crc32_init"))) +crc32_init (unsigned int *p) +{ +#ifdef ORIGINAL_IN_C + *p = 0xffffffff; +#else + register unsigned int r3 asm ("r3"); + + asm volatile ("mov %0, #1\n\t" + "neg %0, %0\n\t" + "str %0, [%1]\n\t" + "bx lr\n" + : "=r" (r3) + : "r" (p) + : "memory"); +#endif +} + +#ifdef ORIGINAL_IN_C +const unsigned int *const crc32_table= (const unsigned int *const)0x00000500; +#endif + +void __attribute__ ((naked,section(".fixed_function.crc32_u8"))) +crc32_u8 (unsigned int *p, unsigned char v) +{ +#ifdef ORIGINAL_IN_C + *p = crc32_table[(*p & 0xff) ^ v] ^ (*p >> 8); +#else + register unsigned int r2 asm ("r2"); + register unsigned int r3 asm ("r3"); + + asm volatile ("ldrb %2, [%4]\n\t" + "eor %0, %2\n\t" + "mov %2, #0xa0\n\t" /* (0x0500 >> 3) */ + "lsl %0, %0, #2\n\t" + "lsl %2, %2, #3\n\t" + "add %0, %0, %2\n\t" + "ldr %2, [%4]\n\t" + "ldr %1, [%0]\n\t" + "lsr %2, %2, #8\n\t" + "eor %2, %1\n\t" + "str %2, [%4]\n\t" + "bx lr\n" + : "=r" (v), "=r" (r2), "=r" (r3) + : "0" (v), "r" (p) + : "memory"); +#endif +} + +void __attribute__ ((naked,section(".fixed_function.crc32_u32"))) +crc32_u32 (unsigned int *p, unsigned int u) +{ +#ifdef ORIGINAL_IN_C + crc32_u8 (p, u & 0xff); + crc32_u8 (p, (u >> 8)& 0xff); + crc32_u8 (p, (u >> 16)& 0xff); + crc32_u8 (p, (u >> 24)& 0xff); +#else + register unsigned int r3 asm ("r3"); + register unsigned int r4 asm ("r4"); + register unsigned int r5 asm ("r5"); + + asm volatile ("push {%1, %2, %3, lr}\n\t" + "mov %2, %0\n\t" + "mov %3, %5\n\t" + "uxtb %0, %0\n\t" + "bl crc32_u8\n\t" + "lsr %0, %2, #8\n\t" + "mov %5, %3\n\t" + "uxtb %0, %0\n\t" + "bl crc32_u8\n\t" + "lsr %0, %2, #16\n\t" + "mov %5, %3\n\t" + "uxtb %0, %0\n\t" + "bl crc32_u8\n\t" + "mov %5, %3\n\t" + "lsr %0, %2, #24\n\t" + "bl crc32_u8\n\t" + "pop {%1, %2, %3, pc}\n\t" + : "=r" (u), "=r" (r3), "=r" (r4), "=r" (r5) + : "0" (u), "r" (p) + : "memory"); +#endif +} /* * Table of CRC32, generated by gen_crc_table.py */ -static unsigned int -crc32_table[256] __attribute__ ((section(".first_page"))) = { +const unsigned int +crc32_table[256] __attribute__ ((section(".crc32_table"))) = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, @@ -117,35 +218,27 @@ crc32_table[256] __attribute__ ((section(".first_page"))) = { 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; -static unsigned int crc_reg; -__attribute__ ((section(".flash_config_page"))) -void -crc32_init (void) -{ - crc_reg = 0xffffffff; -} +const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = { + 3*2+2, /* bLength */ + 0x03, /* bDescriptorType = STRING_DESCRIPTOR */ + /* sys version: "3.0" */ + '3', 0, '.', 0, '0', 0, +}; -__attribute__ ((section(".flash_config_page"))) -unsigned int -crc32_value (void) -{ - return crc_reg; -} +static const uint8_t board_name_string[] = BOARD_NAME; -__attribute__ ((section(".flash_config_page"))) -void -crc32_u8 (unsigned char bits_eight) -{ - crc_reg = crc32_table[(crc_reg & 0xff) ^ bits_eight] ^ (crc_reg >> 8); -} +const uint8_t __attribute__((section(".sys.board_info"))) +*const sys_board_name = board_name_string; -__attribute__ ((section(".flash_config_page"))) -void -crc32_u32 (unsigned int u) -{ - crc32_u8 (u & 0xff); - crc32_u8 ((u >> 8)& 0xff); - crc32_u8 ((u >> 16)& 0xff); - crc32_u8 ((u >> 24)& 0xff); -} +const uint32_t __attribute__((section(".sys.board_info"))) +sys_board_id = BOARD_ID; + +typedef void (*handler)(void); + +handler sys_vector[] __attribute__ ((section(".sys.vectors"))) = { + clock_init, + gpio_init, + (handler)set_led, + NULL, +}; diff --git a/example-fs-bb48/sys.h b/example-fs-bb48/sys.h new file mode 100644 index 0000000..c13978c --- /dev/null +++ b/example-fs-bb48/sys.h @@ -0,0 +1,38 @@ +extern const uint8_t sys_version[8]; +extern const uint32_t sys_board_id; +extern const char *const sys_board_name; + +typedef void (*handler)(void); +extern handler sys_vector[16]; + +/* + * Users can override INLINE by 'attribute((used))' to have an + * implementation defined. + */ +#if !defined(INLINE) +#define INLINE __inline__ +#endif + +static INLINE void +clock_init (void) +{ + (*sys_vector[0]) (); +} + +static INLINE void +gpio_init (void) +{ + (*sys_vector[1]) (); +} + +static inline void +set_led (int on) +{ + void (*func) (int) = (void (*)(int))sys_vector[2]; + + return (*func) (on); +} + +void crc32_init (unsigned int *); +void crc32_u8 (unsigned int *, unsigned char); +void crc32_u32 (unsigned int *, unsigned int); |