@@ -94,6 +94,161 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c
9494}
9595#endif
9696
97- #if !MICROPY_MIN_USE_STDOUT
98- void _start (void ) {main (0 , NULL );}
97+ #if MICROPY_MIN_USE_CORTEX_CPU
98+
99+ // this is a minimal IRQ and reset framework for any Cortex-M CPU
100+
101+ extern uint32_t _estack , _sidata , _sdata , _edata , _sbss , _ebss ;
102+
103+ void Reset_Handler (void ) __attribute__((naked ));
104+ void Reset_Handler (void ) {
105+ // set stack pointer
106+ asm volatile ("ldr sp, =_estack" );
107+ // copy .data section from flash to RAM
108+ for (uint32_t * src = & _sidata , * dest = & _sdata ; dest < & _edata ;) {
109+ * dest ++ = * src ++ ;
110+ }
111+ // zero out .bss section
112+ for (uint32_t * dest = & _sbss ; dest < & _ebss ;) {
113+ * dest ++ = 0 ;
114+ }
115+ // jump to board initialisation
116+ void _start (void );
117+ _start ();
118+ }
119+
120+ void Default_Handler (void ) {
121+ for (;;) {
122+ }
123+ }
124+
125+ uint32_t isr_vector [] __attribute__((section (".isr_vector" ))) = {
126+ (uint32_t )& _estack ,
127+ (uint32_t )& Reset_Handler ,
128+ (uint32_t )& Default_Handler , // NMI_Handler
129+ (uint32_t )& Default_Handler , // HardFault_Handler
130+ (uint32_t )& Default_Handler , // MemManage_Handler
131+ (uint32_t )& Default_Handler , // BusFault_Handler
132+ (uint32_t )& Default_Handler , // UsageFault_Handler
133+ 0 ,
134+ 0 ,
135+ 0 ,
136+ 0 ,
137+ (uint32_t )& Default_Handler , // SVC_Handler
138+ (uint32_t )& Default_Handler , // DebugMon_Handler
139+ 0 ,
140+ (uint32_t )& Default_Handler , // PendSV_Handler
141+ (uint32_t )& Default_Handler , // SysTick_Handler
142+ };
143+
144+ void _start (void ) {
145+ // when we get here: stack is initialised, bss is clear, data is copied
146+
147+ // SCB->CCR: enable 8-byte stack alignment for IRQ handlers, in accord with EABI
148+ * ((volatile uint32_t * )0xe000ed14 ) |= 1 << 9 ;
149+
150+ // initialise the cpu and peripherals
151+ #if MICROPY_MIN_USE_STM32_MCU
152+ void stm32_init (void );
153+ stm32_init ();
154+ #endif
155+
156+ // now that we have a basic system up and running we can call main
157+ main (0 , NULL );
158+
159+ // we must not return
160+ for (;;) {
161+ }
162+ }
163+
164+ #endif
165+
166+ #if MICROPY_MIN_USE_STM32_MCU
167+
168+ // this is minimal set-up code for an STM32 MCU
169+
170+ typedef struct {
171+ volatile uint32_t CR ;
172+ volatile uint32_t PLLCFGR ;
173+ volatile uint32_t CFGR ;
174+ volatile uint32_t CIR ;
175+ uint32_t _1 [8 ];
176+ volatile uint32_t AHB1ENR ;
177+ volatile uint32_t AHB2ENR ;
178+ volatile uint32_t AHB3ENR ;
179+ uint32_t _2 ;
180+ volatile uint32_t APB1ENR ;
181+ volatile uint32_t APB2ENR ;
182+ } periph_rcc_t ;
183+
184+ typedef struct {
185+ volatile uint32_t MODER ;
186+ volatile uint32_t OTYPER ;
187+ volatile uint32_t OSPEEDR ;
188+ volatile uint32_t PUPDR ;
189+ volatile uint32_t IDR ;
190+ volatile uint32_t ODR ;
191+ volatile uint16_t BSRRL ;
192+ volatile uint16_t BSRRH ;
193+ volatile uint32_t LCKR ;
194+ volatile uint32_t AFR [2 ];
195+ } periph_gpio_t ;
196+
197+ typedef struct {
198+ volatile uint32_t SR ;
199+ volatile uint32_t DR ;
200+ volatile uint32_t BRR ;
201+ volatile uint32_t CR1 ;
202+ } periph_uart_t ;
203+
204+ #define USART1 ((periph_uart_t*) 0x40011000)
205+ #define GPIOA ((periph_gpio_t*) 0x40020000)
206+ #define GPIOB ((periph_gpio_t*) 0x40020400)
207+ #define RCC ((periph_rcc_t*) 0x40023800)
208+
209+ // simple GPIO interface
210+ #define GPIO_MODE_IN (0)
211+ #define GPIO_MODE_OUT (1)
212+ #define GPIO_MODE_ALT (2)
213+ #define GPIO_PULL_NONE (0)
214+ #define GPIO_PULL_UP (0)
215+ #define GPIO_PULL_DOWN (1)
216+ void gpio_init (periph_gpio_t * gpio , int pin , int mode , int pull , int alt ) {
217+ gpio -> MODER = (gpio -> MODER & ~(3 << (2 * pin ))) | (mode << (2 * pin ));
218+ // OTYPER is left as default push-pull
219+ // OSPEEDR is left as default low speed
220+ gpio -> PUPDR = (gpio -> PUPDR & ~(3 << (2 * pin ))) | (pull << (2 * pin ));
221+ gpio -> AFR [pin >> 3 ] = (gpio -> AFR [pin >> 3 ] & ~(15 << (4 * (pin & 7 )))) | (alt << (4 * (pin & 7 )));
222+ }
223+ #define gpio_get (gpio , pin ) ((gpio->IDR >> (pin)) & 1)
224+ #define gpio_set (gpio , pin , value ) do { gpio->ODR = (gpio->ODR & ~(1 << (pin))) | (value << pin); } while (0)
225+ #define gpio_low (gpio , pin ) do { gpio->BSRRH = (1 << (pin)); } while (0)
226+ #define gpio_high (gpio , pin ) do { gpio->BSRRL = (1 << (pin)); } while (0)
227+
228+ void stm32_init (void ) {
229+ // basic MCU config
230+ RCC -> CR |= (uint32_t )0x00000001 ; // set HSION
231+ RCC -> CFGR = 0x00000000 ; // reset all
232+ RCC -> CR &= (uint32_t )0xfef6ffff ; // reset HSEON, CSSON, PLLON
233+ RCC -> PLLCFGR = 0x24003010 ; // reset PLLCFGR
234+ RCC -> CR &= (uint32_t )0xfffbffff ; // reset HSEBYP
235+ RCC -> CIR = 0x00000000 ; // disable IRQs
236+
237+ // leave the clock as-is (internal 16MHz)
238+
239+ // enable GPIO clocks
240+ RCC -> AHB1ENR |= 0x00000003 ; // GPIOAEN, GPIOBEN
241+
242+ // turn on an LED! (on pyboard it's the red one)
243+ gpio_init (GPIOA , 13 , GPIO_MODE_OUT , GPIO_PULL_NONE , 0 );
244+ gpio_high (GPIOA , 13 );
245+
246+ // enable UART1 at 9600 baud (TX=B6, RX=B7)
247+ gpio_init (GPIOB , 6 , GPIO_MODE_ALT , GPIO_PULL_NONE , 7 );
248+ gpio_init (GPIOB , 7 , GPIO_MODE_ALT , GPIO_PULL_NONE , 7 );
249+ RCC -> APB2ENR |= 0x00000010 ; // USART1EN
250+ USART1 -> BRR = (104 << 4 ) | 3 ; // 16MHz/(16*104.1875) = 9598 baud
251+ USART1 -> CR1 = 0x0000200c ; // USART enable, tx enable, rx enable
252+ }
253+
99254#endif
0 commit comments