mirror of
				https://github.com/Klipper3d/klipper.git
				synced 2025-10-31 02:15:52 +01:00 
			
		
		
		
	armcm_boot: Add generic code for early board init on armcm machines
Add basic ARM Cortex-M C init code and build linker scripts to src/generic/ code. This can be used to simplify the various ARM board code. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
		| @@ -209,6 +209,50 @@ const int initial_pins_size PROGMEM = ARRAY_SIZE(initial_pins); | |||||||
| Handlers.append(HandleInitialPins()) | Handlers.append(HandleInitialPins()) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ###################################################################### | ||||||
|  | # ARM IRQ vector table generation | ||||||
|  | ###################################################################### | ||||||
|  |  | ||||||
|  | # Create ARM IRQ vector table from interrupt handler declarations | ||||||
|  | class Handle_arm_irq: | ||||||
|  |     def __init__(self): | ||||||
|  |         self.irqs = {} | ||||||
|  |         self.ctr_dispatch = { 'DECL_ARMCM_IRQ': self.decl_armcm_irq } | ||||||
|  |     def decl_armcm_irq(self, req): | ||||||
|  |         func, num = req.split()[1:] | ||||||
|  |         num = decode_integer(num) | ||||||
|  |         if num in self.irqs and self.irqs[num] != func: | ||||||
|  |             error("Conflicting IRQ definition %d (old %s new %s)" | ||||||
|  |                   % (num, self.irqs[num], func)) | ||||||
|  |         self.irqs[num] = func | ||||||
|  |     def update_data_dictionary(self, data): | ||||||
|  |         pass | ||||||
|  |     def generate_code(self, options): | ||||||
|  |         armcm_offset = 16 | ||||||
|  |         if 1 - armcm_offset not in self.irqs: | ||||||
|  |             # The ResetHandler was not defined - don't build VectorTable | ||||||
|  |             return "" | ||||||
|  |         max_irq = max(self.irqs.keys()) | ||||||
|  |         table = ["    DefaultHandler,\n"] * (max_irq + armcm_offset + 1) | ||||||
|  |         defs = [] | ||||||
|  |         for num, func in self.irqs.items(): | ||||||
|  |             if num < 1 - armcm_offset: | ||||||
|  |                 error("Invalid IRQ %d (%s)" % (num, func)) | ||||||
|  |             defs.append("extern void %s(void);\n" % (func,)) | ||||||
|  |             table[num + armcm_offset] = "    %s,\n" % (func,) | ||||||
|  |         table[0] = "    &_stack_end,\n" | ||||||
|  |         fmt = """ | ||||||
|  | extern void DefaultHandler(void); | ||||||
|  | extern uint32_t _stack_end; | ||||||
|  | %s | ||||||
|  | const void *VectorTable[] __visible __section(".vector_table") = { | ||||||
|  | %s}; | ||||||
|  | """ | ||||||
|  |         return fmt % (''.join(defs), ''.join(table)) | ||||||
|  |  | ||||||
|  | Handlers.append(Handle_arm_irq()) | ||||||
|  |  | ||||||
|  |  | ||||||
| ###################################################################### | ###################################################################### | ||||||
| # Wire protocol commands and responses | # Wire protocol commands and responses | ||||||
| ###################################################################### | ###################################################################### | ||||||
|   | |||||||
							
								
								
									
										73
									
								
								src/generic/armcm_boot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/generic/armcm_boot.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | |||||||
|  | // ARM Cortex-M vector table and initial bootup handling | ||||||
|  | // | ||||||
|  | // Copyright (C) 2019  Kevin O'Connor <kevin@koconnor.net> | ||||||
|  | // | ||||||
|  | // This file may be distributed under the terms of the GNU GPLv3 license. | ||||||
|  |  | ||||||
|  | #include "armcm_boot.h" // DECL_ARMCM_IRQ | ||||||
|  | #include "board/internal.h" // SystemInit | ||||||
|  |  | ||||||
|  | // Symbols created by armcm_boot.lds.S linker script | ||||||
|  | extern uint32_t _data_start, _data_end, _data_flash; | ||||||
|  | extern uint32_t _bss_start, _bss_end, _stack_start; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /**************************************************************** | ||||||
|  |  * Basic interrupt handlers | ||||||
|  |  ****************************************************************/ | ||||||
|  |  | ||||||
|  | // Initial code entry point - invoked by the processor after a reset | ||||||
|  | void | ||||||
|  | ResetHandler(void) | ||||||
|  | { | ||||||
|  |     // Copy global variables from flash to ram | ||||||
|  |     uint32_t count = (&_data_end - &_data_start) * 4; | ||||||
|  |     __builtin_memcpy(&_data_start, &_data_flash, count); | ||||||
|  |  | ||||||
|  |     // Clear the bss segment | ||||||
|  |     __builtin_memset(&_bss_start, 0, (&_bss_end - &_bss_start) * 4); | ||||||
|  |  | ||||||
|  |     barrier(); | ||||||
|  |  | ||||||
|  |     // Initializing the C library isn't needed... | ||||||
|  |     //__libc_init_array(); | ||||||
|  |  | ||||||
|  |     // Initialize the machine | ||||||
|  |     SystemInit(); | ||||||
|  |  | ||||||
|  |     // Run the main code | ||||||
|  |     extern int main(void); | ||||||
|  |     main(); | ||||||
|  |  | ||||||
|  |     // The main() call should not return | ||||||
|  |     for (;;) | ||||||
|  |         ; | ||||||
|  | } | ||||||
|  | DECL_ARMCM_IRQ(ResetHandler, -15); | ||||||
|  |  | ||||||
|  | // Code called for any undefined interrupts | ||||||
|  | void | ||||||
|  | DefaultHandler(void) | ||||||
|  | { | ||||||
|  |     for (;;) | ||||||
|  |         ; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /**************************************************************** | ||||||
|  |  * Dynamic memory range | ||||||
|  |  ****************************************************************/ | ||||||
|  |  | ||||||
|  | // Return the start of memory available for dynamic allocations | ||||||
|  | void * | ||||||
|  | dynmem_start(void) | ||||||
|  | { | ||||||
|  |     return &_bss_end; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Return the end of memory available for dynamic allocations | ||||||
|  | void * | ||||||
|  | dynmem_end(void) | ||||||
|  | { | ||||||
|  |     return &_stack_start; | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								src/generic/armcm_boot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/generic/armcm_boot.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | #ifndef __GENERIC_ARMCM_BOOT_H | ||||||
|  | #define __GENERIC_ARMCM_BOOT_H | ||||||
|  |  | ||||||
|  | #include "ctr.h" // DECL_CTR_INT | ||||||
|  |  | ||||||
|  | // Declare an IRQ handler | ||||||
|  | #define DECL_ARMCM_IRQ(FUNC, NUM)                               \ | ||||||
|  |     DECL_CTR_INT("DECL_ARMCM_IRQ " __stringify(FUNC), (NUM)) | ||||||
|  |  | ||||||
|  | // Statically declare an IRQ handler and run-time enable it | ||||||
|  | #define armcm_enable_irq(FUNC, NUM, PRIORITY) do {      \ | ||||||
|  |         DECL_ARMCM_IRQ(FUNC, (NUM));                    \ | ||||||
|  |         NVIC_SetPriority((NUM), (PRIORITY));            \ | ||||||
|  |         NVIC_EnableIRQ((NUM));                          \ | ||||||
|  |     } while (0) | ||||||
|  |  | ||||||
|  | // Vectors created by scripts/buildcommands.py from DECL_ARMCM_IRQ commands | ||||||
|  | extern const void * const VectorTable[]; | ||||||
|  |  | ||||||
|  | #endif // armcm_boot.h | ||||||
							
								
								
									
										63
									
								
								src/generic/armcm_boot.lds.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/generic/armcm_boot.lds.S
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | // Generic ARM Cortex-M linker script | ||||||
|  | // | ||||||
|  | // Copyright (C) 2019  Kevin O'Connor <kevin@koconnor.net> | ||||||
|  | // | ||||||
|  | // This file may be distributed under the terms of the GNU GPLv3 license. | ||||||
|  |  | ||||||
|  | #include "autoconf.h" // CONFIG_FLASH_START | ||||||
|  |  | ||||||
|  | OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") | ||||||
|  | OUTPUT_ARCH(arm) | ||||||
|  |  | ||||||
|  | MEMORY | ||||||
|  | { | ||||||
|  |   rom (rx) : ORIGIN = CONFIG_FLASH_START , LENGTH = CONFIG_FLASH_SIZE | ||||||
|  |   ram (rwx) : ORIGIN = CONFIG_RAM_START , LENGTH = CONFIG_RAM_SIZE | ||||||
|  | } | ||||||
|  |  | ||||||
|  | SECTIONS | ||||||
|  | { | ||||||
|  |     .text : { | ||||||
|  |         . = ALIGN(4); | ||||||
|  |         KEEP(*(.vector_table)) | ||||||
|  |         *(.text .text.*) | ||||||
|  |         *(.rodata .rodata*) | ||||||
|  |     } > rom | ||||||
|  |  | ||||||
|  |     . = ALIGN(4); | ||||||
|  |     _data_flash = .; | ||||||
|  |  | ||||||
|  |     .data : AT (_data_flash) | ||||||
|  |     { | ||||||
|  |         . = ALIGN(4); | ||||||
|  |         _data_start = .; | ||||||
|  |         *(.ramfunc .ramfunc.*); | ||||||
|  |         *(.data .data.*); | ||||||
|  |         . = ALIGN(4); | ||||||
|  |         _data_end = .; | ||||||
|  |     } > ram | ||||||
|  |  | ||||||
|  |     .bss (NOLOAD) : | ||||||
|  |     { | ||||||
|  |         . = ALIGN(4); | ||||||
|  |         _bss_start = .; | ||||||
|  |         *(.bss .bss.*) | ||||||
|  |         *(COMMON) | ||||||
|  |         . = ALIGN(4); | ||||||
|  |         _bss_end = .; | ||||||
|  |     } > ram | ||||||
|  |  | ||||||
|  |     _stack_start = CONFIG_RAM_START + CONFIG_RAM_SIZE - CONFIG_STACK_SIZE ; | ||||||
|  |     .stack _stack_start (NOLOAD) : | ||||||
|  |     { | ||||||
|  |         . = . + CONFIG_STACK_SIZE; | ||||||
|  |         _stack_end = .; | ||||||
|  |     } > ram | ||||||
|  |  | ||||||
|  |     /DISCARD/ : { | ||||||
|  |         // The .init/.fini sections are used by __libc_init_array(), but | ||||||
|  |         // that isn't needed so no need to include them in the binary. | ||||||
|  |         *(.init) | ||||||
|  |         *(.fini) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -5,6 +5,7 @@ | |||||||
| // This file may be distributed under the terms of the GNU GPLv3 license. | // This file may be distributed under the terms of the GNU GPLv3 license. | ||||||
|  |  | ||||||
| #include "autoconf.h" // CONFIG_CLOCK_FREQ | #include "autoconf.h" // CONFIG_CLOCK_FREQ | ||||||
|  | #include "armcm_boot.h" // DECL_ARMCM_IRQ | ||||||
| #include "board/internal.h" // SysTick | #include "board/internal.h" // SysTick | ||||||
| #include "board/irq.h" // irq_disable | #include "board/irq.h" // irq_disable | ||||||
| #include "board/misc.h" // timer_from_us | #include "board/misc.h" // timer_from_us | ||||||
| @@ -160,6 +161,7 @@ SysTick_Handler(void) | |||||||
|     timer_set_diff(diff); |     timer_set_diff(diff); | ||||||
|     irq_enable(); |     irq_enable(); | ||||||
| } | } | ||||||
|  | DECL_ARMCM_IRQ(SysTick_Handler, SysTick_IRQn); | ||||||
|  |  | ||||||
| // Make sure timer_repeat_until doesn't wrap 32bit comparisons | // Make sure timer_repeat_until doesn't wrap 32bit comparisons | ||||||
| void | void | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user