├── start_kernel.h ├── mpu.h ├── usart.h ├── start_kernel.c ├── stm32f429.lds ├── stm32h743.lds ├── stm32h7_regs.h ├── usart-f7.c ├── usart-f4.c ├── gpio.h ├── stm32f4_regs.h ├── mpu.c ├── gpio.c ├── qspi.h ├── Makefile ├── qspi.c ├── stm32f429i-disco.c ├── stm32429i-eval.c ├── stm32746g-eval.c ├── stm32f469i-disco.c └── stm32h743i-eval.c /start_kernel.h: -------------------------------------------------------------------------------- 1 | #ifndef _START_KERNEL_H 2 | #define _START_KERNEL_H 3 | 4 | void start_kernel(void); 5 | 6 | #endif /* _START_KERNEL_H */ 7 | -------------------------------------------------------------------------------- /mpu.h: -------------------------------------------------------------------------------- 1 | #ifndef _MPU_H 2 | #define _MPU_H 3 | 4 | #include 5 | 6 | void mpu_config(uint32_t sdram_base); 7 | 8 | #endif /* _MPU_H */ 9 | -------------------------------------------------------------------------------- /usart.h: -------------------------------------------------------------------------------- 1 | #ifndef _USART_H 2 | #define _USART_H 3 | 4 | void usart_setup(void *base, uint32_t clk_freq); 5 | void usart_putch(void *base, char ch); 6 | 7 | #endif /* _USART_H */ 8 | -------------------------------------------------------------------------------- /start_kernel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void start_kernel(void) 5 | { 6 | void (*kernel)(uint32_t reserved, uint32_t mach, uint32_t dt) = (void (*)(uint32_t, uint32_t, uint32_t))(KERNEL_ADDR | 1); 7 | 8 | kernel(0, ~0UL, DTB_ADDR); 9 | } 10 | -------------------------------------------------------------------------------- /stm32f429.lds: -------------------------------------------------------------------------------- 1 | ENTRY(reset) 2 | MEMORY 3 | { 4 | FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 0x00200000 5 | SRAM1 (RWX) : ORIGIN = 0x20000000, LENGTH = 176 * 1024 /*0x00040000*/ 6 | STACK (RW) : ORIGIN = 0x20000000 + 176 * 1024 - 1, LENGTH = 0 7 | } 8 | SECTIONS 9 | { 10 | . = ORIGIN(FLASH); 11 | 12 | .text : 13 | { 14 | KEEP(*(.vector_table)) 15 | *(.text) 16 | *(.rodata) 17 | *(.rodata.*) 18 | /*. = ALIGN(4);*/ 19 | _end_text = .; 20 | } >FLASH 21 | 22 | .data : 23 | { 24 | _start_data = .; 25 | *(.data) 26 | _end_data = .; 27 | } >SRAM1 AT >FLASH 28 | 29 | .bss : 30 | { 31 | _start_bss = .; 32 | *(.bss) 33 | _end_bss = .; 34 | } >SRAM1 35 | 36 | .stack : 37 | { 38 | _stack_top = .; 39 | } >STACK 40 | } 41 | -------------------------------------------------------------------------------- /stm32h743.lds: -------------------------------------------------------------------------------- 1 | ENTRY(reset) 2 | MEMORY 3 | { 4 | FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 0x00200000 5 | SRAM1 (RWX) : ORIGIN = 0x24000000, LENGTH = 176 * 1024 /*0x00040000*/ 6 | STACK (RW) : ORIGIN = 0x24000000 + 176 * 1024 - 1, LENGTH = 0 7 | } 8 | SECTIONS 9 | { 10 | . = ORIGIN(FLASH); 11 | 12 | .text : 13 | { 14 | KEEP(*(.vector_table)) 15 | *(.text) 16 | *(.rodata) 17 | *(.rodata.*) 18 | /*. = ALIGN(4);*/ 19 | _end_text = .; 20 | } >FLASH 21 | 22 | .data : 23 | { 24 | _start_data = .; 25 | *(.data) 26 | _end_data = .; 27 | } >SRAM1 AT >FLASH 28 | 29 | .bss : 30 | { 31 | _start_bss = .; 32 | *(.bss) 33 | _end_bss = .; 34 | } >SRAM1 35 | 36 | .stack : 37 | { 38 | _stack_top = .; 39 | } >STACK 40 | } 41 | -------------------------------------------------------------------------------- /stm32h7_regs.h: -------------------------------------------------------------------------------- 1 | #ifndef _STM32H7_REGS_H 2 | #define _STM32H7_REGS_H 3 | 4 | /* RCC */ 5 | #define RCC_BASE_REG 0x58024400 6 | 7 | #define RCC_CR_HSION 1 8 | #define RCC_CR_HSEON 1<<16 9 | #define RCC_CR_HSERDY 1<<17 10 | #define RCC_CR_HSEBYP 1<<18 11 | #define RCC_CR_PLL1ON 1<<24 12 | #define RCC_CR_PLL1RDY 1<<25 13 | #define RCC_D1AHB1ENR_FMCEN 1<<12 14 | 15 | /* PWR */ 16 | #define PWR_BASE 0x58024800 17 | /* FLASH */ 18 | #define FLASH_BASE 0x52002000 19 | #define FLASH_FACR_REG FLASH_BASE 20 | /* FMC */ 21 | #define FMC_BASE 0x52004000 22 | #define FMC_BCR1_REG FMC_BASE 23 | 24 | /* Other base */ 25 | #define USART1_BASE 0x40011000 26 | #define GPIOA_BASE 0x58020000UL 27 | #define SDRAM_BASE 0xd0000000UL 28 | #define QUADSPI_BASE 0x52005000 29 | 30 | #endif /* _STM32H7_REGS_H */ 31 | -------------------------------------------------------------------------------- /usart-f7.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define USART_CR1_UE (1 << 0) 4 | #define USART_CR1_RE (1 << 2) 5 | #define USART_CR1_TE (1 << 3) 6 | 7 | #define USART_ISR_TXE (1 << 7) 8 | 9 | void usart_setup(void *base, uint32_t clk_freq) 10 | { 11 | volatile uint32_t *USART_BRR = base + 0x0c; 12 | volatile uint32_t *USART_CR1 = base + 0x00; 13 | volatile uint32_t *USART_CR2 = base + 0x04; 14 | volatile uint32_t *USART_CR3 = base + 0x08; 15 | 16 | *USART_CR1 = USART_CR1_TE | USART_CR1_RE; 17 | *USART_CR2 = 0; 18 | *USART_CR3 = 0; 19 | 20 | *USART_BRR = clk_freq / 115200; 21 | 22 | *USART_CR1 |= USART_CR1_UE; 23 | } 24 | 25 | void usart_putch(void *base, char ch) 26 | { 27 | volatile uint32_t *USART_ISR = base + 0x1c; 28 | volatile uint32_t *USART_TDR = base + 0x28; 29 | 30 | while (!(*USART_ISR & USART_ISR_TXE)) { 31 | } 32 | *USART_TDR = ch; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /usart-f4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define USART_SR_TXE (1 << 7) 4 | 5 | #define USART_CR1_RE (1 << 2) 6 | #define USART_CR1_TE (1 << 3) 7 | #define USART_CR1_UE (1 << 13) 8 | 9 | void usart_setup(void *base, uint32_t clk_freq) 10 | { 11 | volatile uint32_t *USART_BRR = base + 0x08; 12 | volatile uint32_t *USART_CR1 = base + 0x0C; 13 | volatile uint32_t *USART_CR2 = base + 0x10; 14 | volatile uint32_t *USART_CR3 = base + 0x14; 15 | uint32_t int_div, frac_div, val; 16 | 17 | *USART_CR1 = USART_CR1_TE | USART_CR1_RE; 18 | *USART_CR2 = 0; 19 | *USART_CR3 = 0; 20 | 21 | int_div = (25 * clk_freq) / (4 * 115200); 22 | val = (int_div / 100) << 4; 23 | frac_div = int_div - 100 * (val >> 4); 24 | val |= ((frac_div * 16 + 50) / 100) & 0xf; 25 | *USART_BRR = val; 26 | 27 | *USART_CR1 |= USART_CR1_UE; 28 | } 29 | 30 | void usart_putch(void *base, char ch) 31 | { 32 | volatile uint32_t *USART_SR = base + 0x00; 33 | volatile uint32_t *USART_DR = base + 0x04; 34 | 35 | while (!(*USART_SR & USART_SR_TXE)) { 36 | } 37 | *USART_DR = ch; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef _GPIO_H 2 | #define _GPIO_H 3 | 4 | #define GPIOx_MODER_MODERy_INPUT 0x0UL 5 | #define GPIOx_MODER_MODERy_GPOUTPUT 0x1UL 6 | #define GPIOx_MODER_MODERy_ALTFUNC 0x2UL 7 | #define GPIOx_MODER_MODERy_ANALOG 0x3UL 8 | #define GPIOx_MODER_MODERy_MASK 0x3UL 9 | 10 | #define GPIOx_OSPEEDR_OSPEEDRy_FAST 0x2UL 11 | #define GPIOx_OSPEEDR_OSPEEDRy_HIGH 0x3UL 12 | #define GPIOx_OSPEEDR_OSPEEDRy_MASK 0x3UL 13 | 14 | #define GPIOx_PUPDR_NOPULL 0x0UL 15 | #define GPIOx_PUPDR_PULLUP 0x1UL 16 | #define GPIOx_PUPDR_PULLDOWN 0x2UL 17 | #define GPIOx_PUPDR_PUPDRy_MASK 0x3UL 18 | 19 | #define GPIOx_AFRy_MASK 0xfUL 20 | 21 | void gpio_set(void *base, char bank, uint8_t port, uint8_t otype, uint8_t mode, 22 | uint8_t ospeed, uint8_t pupd); 23 | void gpio_set_alt(void *base, char bank, uint8_t port, uint8_t otype, uint8_t ospeed, 24 | uint8_t pupd, uint8_t altfunc); 25 | void gpio_set_fmc(void *base, char bank, uint8_t port); 26 | void gpio_set_qspi(void *base, char bank, uint8_t port, uint8_t altfunc, uint8_t pupd); 27 | void gpio_set_usart(void *base, char bank, uint8_t port, uint8_t altfunc); 28 | 29 | #endif /* _GPIO_H */ 30 | -------------------------------------------------------------------------------- /stm32f4_regs.h: -------------------------------------------------------------------------------- 1 | #ifndef _STM32F4_REGS_H 2 | #define _STM32F4_REGS_H 3 | 4 | #define RCC_BASE 0x40023800 5 | 6 | #define RCC_CR_HSEON (1 << 16) 7 | #define RCC_CR_HSERDY (1 << 17) 8 | #define RCC_CR_PLLON (1 << 24) 9 | #define RCC_CR_PLLRDY (1 << 25) 10 | #define RCC_CR_SAION (1 << 28) 11 | #define RCC_CR_SAIRDY (1 << 29) 12 | 13 | #define RCC_PLLCFGR_PLLSRC_HSE (1 << 22) 14 | 15 | #define RCC_CFGR_SW_PLL (0x2 << 0) 16 | #define RCC_CFGR_SW_MASK (0x3 << 0) 17 | #define RCC_CFGR_SWS_PLL (0x2 << 2) 18 | #define RCC_CFGR_SWS_MASK (0x3 << 2) 19 | #define RCC_CFGR_HPRE_MASK (0xf << 4) 20 | #define RCC_CFGR_PPRE1_MASK (0x7 << 10) 21 | #define RCC_CFGR_PPRE2_MASK (0x7 << 13) 22 | 23 | #define RCC_DCKCFGR_48SRC_SAI (1 << 27) 24 | #define RCC_DCKCFGR_SDIO48 (1 << 28) 25 | 26 | #define RCC_AHB1ENR_GPIOGEN (1 << 6) 27 | 28 | #define RCC_AHB1LPENR_OTGHSULPILPEN (1 << 30) 29 | 30 | #define RCC_AHB3ENR_FMC (1 << 0) 31 | 32 | 33 | #define RCC_APB2ENR_USART1EN (1 << 4) 34 | #define RCC_APB2ENR_SYSCFGEN (1 << 14) 35 | 36 | #define FLASH_BASE 0x40023C00 37 | 38 | #define FLASH_ACR_PRFTEN (1 << 8) 39 | #define FLASH_ACR_ICEN (1 << 9) 40 | 41 | #define FLASH_CR_PSIZE_X32 0x2 42 | #define FLASH_CR_PSIZE_MASK 0x3 43 | #define FLASH_CR_EOPIE (1 << 24) 44 | #define FLASH_CR_ERRIE (1 << 25) 45 | #define FLASH_CR_LOCK (1UL << 31) 46 | 47 | #define USART3_BASE 0x40004800 48 | #define USART1_BASE 0x40011000 49 | #define GPIOA_BASE 0x40020000 50 | 51 | #define FMC_BASE 0xA0000000 52 | #define QUADSPI_BASE 0xA0001000 53 | 54 | #define FMC_SDSR_BUSY (1 << 5) 55 | 56 | #define SYSCFG_BASE 0x40013800 57 | #define SYSCFG_MEMRMP_SWP_FMC 0x1 58 | 59 | 60 | #endif /* _STM32F4_REGS_H */ 61 | -------------------------------------------------------------------------------- /mpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MPU_BASE 0xe000ed90 4 | 5 | #define MPU_CTLR_ENABLE (1 << 0) 6 | #define MPU_CTLR_PRIVDEFENA (1 << 2) 7 | 8 | #define MPU_RBAR_ADDR_MASK 0xffffffe0 9 | 10 | #define MPU_RASR_AP_SHIFT 24 11 | #define MPU_RASR_AP_RWRW (0x3 << MPU_RASR_AP_SHIFT) 12 | 13 | #define MPU_RASR_TEX_SHIFT 19 14 | #define MPU_RASR_S_SHIFT 18 15 | #define MPU_RASR_C_SHIFT 17 16 | #define MPU_RASR_B_SHIFT 16 17 | #define MPU_RASR_SIZE_SHIFT 1 18 | 19 | #define MPU_RASR_REG_ENABLE 0x1 20 | 21 | #define MPU_RASR_SIZE_256M (28 << MPU_RASR_SIZE_SHIFT) 22 | #define MPU_RASR_SIZE_32M (24 << MPU_RASR_SIZE_SHIFT) 23 | #define MPU_RASR_SIZE_1M (19 << MPU_RASR_SIZE_SHIFT) 24 | 25 | 26 | #define MPU_RASR_PERM_ATTRS(TEX, C, B, S) \ 27 | ((TEX << MPU_RASR_TEX_SHIFT) |\ 28 | (C << MPU_RASR_C_SHIFT) | \ 29 | (B << MPU_RASR_B_SHIFT) | \ 30 | (S << MPU_RASR_S_SHIFT)) 31 | 32 | #define MPU_RASR_INT_FLASH_ATTR MPU_RASR_PERM_ATTRS(0, 1, 0, 0) 33 | #define MPU_RASR_INT_RAM_ATTR MPU_RASR_PERM_ATTRS(0, 1, 0, 1) 34 | #define MPU_RASR_EXT_RAM_ATTR MPU_RASR_PERM_ATTRS(0, 1, 1, 0) 35 | #define MPU_RASR_PERIPH_ATTR MPU_RASR_PERM_ATTRS(0, 0, 1, 1) 36 | #define MPU_RASR_PRIV_PERIPH_ATTR MPU_RASR_PERM_ATTRS(0, 0, 0, 0) 37 | 38 | void mpu_config(uint32_t sdram_base) 39 | { 40 | volatile uint32_t *MPU_CTRL = (void *)(MPU_BASE + 0x04); 41 | volatile uint32_t *MPU_RNR = (void *)(MPU_BASE + 0x08); 42 | volatile uint32_t *MPU_RBAR = (void *)(MPU_BASE + 0x0c); 43 | volatile uint32_t *MPU_RASR = (void *)(MPU_BASE + 0x10); 44 | 45 | /* Configure external SDRAM */ 46 | *MPU_RNR = 0x0; 47 | *MPU_RBAR = sdram_base; 48 | *MPU_RASR = MPU_RASR_AP_RWRW | 49 | MPU_RASR_EXT_RAM_ATTR | 50 | MPU_RASR_SIZE_256M | 51 | MPU_RASR_REG_ENABLE; 52 | 53 | *MPU_RNR = 0x2; 54 | *MPU_RBAR = 0x90000000; 55 | *MPU_RASR = MPU_RASR_AP_RWRW | 56 | MPU_RASR_EXT_RAM_ATTR| 57 | MPU_RASR_SIZE_32M | 58 | MPU_RASR_REG_ENABLE; 59 | 60 | *MPU_CTRL = MPU_CTLR_ENABLE | MPU_CTLR_PRIVDEFENA; 61 | 62 | asm volatile ("dsb"); 63 | asm volatile ("isb"); 64 | } 65 | -------------------------------------------------------------------------------- /gpio.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "gpio.h" 4 | 5 | void gpio_set(void *base, char bank, uint8_t port, 6 | uint8_t otype, uint8_t mode, uint8_t ospeed, uint8_t pupd) 7 | { 8 | volatile uint32_t *GPIOx_base = (base + (bank - 'A') * 0x400); 9 | volatile uint32_t *GPIOx_MODER = (void *)GPIOx_base + 0x00; 10 | volatile uint32_t *GPIOx_OTYPER = (void *)GPIOx_base + 0x04; 11 | volatile uint32_t *GPIOx_OSPEEDR = (void *)GPIOx_base + 0x08; 12 | volatile uint32_t *GPIOx_PUPDR = (void *)GPIOx_base + 0x0C; 13 | int i; 14 | 15 | i = port; 16 | *GPIOx_OTYPER &= ~(1UL << i); 17 | *GPIOx_OTYPER |= (uint32_t)otype << i; 18 | 19 | i <<= 1; 20 | *GPIOx_MODER &= ~(GPIOx_MODER_MODERy_MASK << i); 21 | *GPIOx_MODER |= (uint32_t)mode << i; 22 | *GPIOx_OSPEEDR &= ~(GPIOx_OSPEEDR_OSPEEDRy_MASK << i); 23 | *GPIOx_OSPEEDR |= (uint32_t)ospeed << i; 24 | *GPIOx_PUPDR &= ~(GPIOx_PUPDR_PUPDRy_MASK << i); 25 | *GPIOx_PUPDR |= (uint32_t)pupd << i; 26 | } 27 | 28 | void gpio_set_alt(void *base, char bank, uint8_t port, 29 | uint8_t otype, uint8_t ospeed, uint8_t pupd, uint8_t altfunc) 30 | { 31 | volatile uint32_t *GPIOx_base = (base + (bank - 'A') * 0x400); 32 | volatile uint32_t *GPIOx_AFRL = (void *)GPIOx_base + 0x20; 33 | volatile uint32_t *GPIOx_AFRH = (void *)GPIOx_base + 0x24; 34 | volatile uint32_t *GPIOx_AFR; 35 | int i; 36 | 37 | if (port >= 8) { 38 | GPIOx_AFR = GPIOx_AFRH; 39 | i = (port - 8) * 4; 40 | } else { 41 | GPIOx_AFR = GPIOx_AFRL; 42 | i = port * 4; 43 | } 44 | *GPIOx_AFR &= ~(GPIOx_AFRy_MASK << i); 45 | *GPIOx_AFR |= (uint32_t)altfunc << i; 46 | 47 | gpio_set(base, bank, port, otype, GPIOx_MODER_MODERy_ALTFUNC, ospeed, pupd); 48 | } 49 | 50 | void gpio_set_fmc(void *base, char bank, uint8_t port) 51 | { 52 | gpio_set_alt(base, bank, port, 0, GPIOx_OSPEEDR_OSPEEDRy_HIGH, 0, 0xC); 53 | } 54 | 55 | void gpio_set_qspi(void *base, char bank, uint8_t port, uint8_t pupd, uint8_t altfunc) 56 | { 57 | gpio_set_alt(base, bank, port, 0, GPIOx_OSPEEDR_OSPEEDRy_HIGH, pupd, altfunc); 58 | } 59 | 60 | void gpio_set_usart(void *base, char bank, uint8_t port, uint8_t altfunc) 61 | { 62 | gpio_set_alt(base, bank, port, 0, GPIOx_OSPEEDR_OSPEEDRy_FAST, 1, altfunc); 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /qspi.h: -------------------------------------------------------------------------------- 1 | #ifndef _QSPI_H 2 | #define _QSPI_H 3 | 4 | #include 5 | 6 | /* QUADSPI_CR */ 7 | #define QUADSPI_CR_EN (1 << 0) 8 | #define QUADSPI_CR_TCEN (1 << 3) 9 | #define QUADSPI_CR_SSHIFT (1 << 4) 10 | #define QUADSPI_CR_DFM (1 << 6) 11 | #define QUADSPI_CR_FSEL (1 << 7) 12 | #define QUADSPI_CR_FTHRES(x) ((x) << 8) 13 | #define QUADSPI_CR_TOIE (1 << 20) 14 | #define QUADSPI_CR_AMPS (1 << 22) 15 | #define QUADSPI_CR_PRESCALER(x) ((x) << 24) 16 | 17 | #define QUADSPI_CR_PRESCALER_MASK QUADSPI_CR_PRESCALER(0xff) 18 | 19 | /* QUADSPI_DCR */ 20 | #define QUADSPI_DCR_CSHT(x) ((x) << 8) 21 | #define QUADSPI_DCR_FSIZE(x) ((x) << 16) 22 | 23 | #define QUADSPI_DCR_CSHT_MASK QUADSPI_DCR_CSHT(0x7) 24 | #define QUADSPI_DCR_FSIZE_MASK QUADSPI_DCR_FSIZE(0x1f) 25 | #define QUADSPI_DCR_FSIZE_64MB QUADSPI_DCR_FSIZE(25) 26 | #define QUADSPI_DCR_FSIZE_128MB QUADSPI_DCR_FSIZE(26) 27 | 28 | /* QUADSPI_SR */ 29 | #define QUADSPI_SR_TCF (1 << 1) 30 | #define QUADSPI_SR_FTF (1 << 2) 31 | #define QUADSPI_SR_SMF (1 << 3) 32 | #define QUADSPI_SR_BUSY (1 << 5) 33 | 34 | /* QUADSPI_FCR */ 35 | #define QUADSPI_FCR_CTCF (1 << 1) 36 | #define QUADSPI_FCR_CSMF (1 << 3) 37 | 38 | /* QUADSPI_CCR */ 39 | #define QUADSPI_CCR_IDMODE(x) ((x) << 8) 40 | #define QUADSPI_CCR_ADMODE(x) ((x) << 10) 41 | #define QUADSPI_CCR_ADSIZE(x) ((x) << 12) 42 | #define QUADSPI_CCR_DCYC(x) ((x) << 18) 43 | #define QUADSPI_CCR_DMODE(x) ((x) << 24) 44 | #define QUADSPI_CCR_FMODE(x) ((x) << 26) 45 | 46 | #define QUADSPI_CCR_IDMOD_1_LINE QUADSPI_CCR_IDMODE(1) 47 | #define QUADSPI_CCR_ADMOD_1_LINE QUADSPI_CCR_ADMODE(1) 48 | #define QUADSPI_CCR_ADSIZE_24BITS QUADSPI_CCR_ADSIZE(2) 49 | #define QUADSPI_CCR_ADSIZE_32BITS QUADSPI_CCR_ADSIZE(3) 50 | #define QUADSPI_CCR_DMODE_1_LINE QUADSPI_CCR_DMODE(1) 51 | #define QUADSPI_CCR_DMODE_4_LINES QUADSPI_CCR_DMODE(3) 52 | #define QUADSPI_CCR_FMODE_IND_WR QUADSPI_CCR_FMODE(0) 53 | #define QUADSPI_CCR_FMODE_IND_RD QUADSPI_CCR_FMODE(1) 54 | #define QUADSPI_CCR_FMODE_AUTO_POLL QUADSPI_CCR_FMODE(2) 55 | #define QUADSPI_CCR_FMODE_MEMMAP QUADSPI_CCR_FMODE(3) 56 | 57 | /* QSPI Comands */ 58 | #define READ_STATUS_REG_CMD 0x05 59 | #define WRITE_ENABLE_CMD 0x06 60 | #define RESET_ENABLE_CMD 0x66 61 | #define QUAD_OUTPUT_FAST_READ_CMD 0x6b 62 | #define WRITE_VOL_CFG_REG_CMD 0x81 63 | #define READ_VOL_CFG_REG_CMD 0x85 64 | #define RESET_MEMORY_CMD 0x99 65 | #define ENTER_4_BYTE_ADDR_MODE_CMD 0xb7 66 | 67 | 68 | /* N25Q512A Registers*/ 69 | 70 | /* N25Q512A_SR */ 71 | #define N25Q512A_SR_WIP (1 << 0) 72 | #define N25Q512A_SR_WREN (1 << 1) 73 | 74 | struct qspi_params { 75 | uint32_t address_size; 76 | uint32_t fifo_threshold; 77 | uint32_t prescaler; 78 | uint32_t sshift; 79 | uint32_t fsel; 80 | uint32_t dfm; 81 | uint32_t dummy_cycle; 82 | uint32_t fsize; 83 | }; 84 | 85 | void quadspi_init(struct qspi_params *params, void *base); 86 | 87 | #endif /* _QSPI_H */ 88 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | 3 | CC = $(CROSS_COMPILE)gcc 4 | LD = $(CROSS_COMPILE)ld 5 | OBJCOPY = $(CROSS_COMPILE)objcopy 6 | OBJDUMP = $(CROSS_COMPILE)objdump 7 | SIZE = $(CROSS_COMPILE)size 8 | GDB = $(CROSS_COMPILE)gdb 9 | OPENOCD = openocd 10 | KERNEL_ADDR?=0x08008000 11 | DTB_ADDR?=0x08004000 12 | 13 | CFLAGS := -mthumb -mcpu=cortex-m4 14 | CFLAGS += -ffunction-sections -fdata-sections 15 | CFLAGS += -Os -std=gnu99 -Wall 16 | LINKERFLAGS := -nostartfiles --gc-sections 17 | 18 | obj-y += gpio.o mpu.o qspi.o start_kernel.o 19 | obj-f4 += $(obj-y) usart-f4.o 20 | obj-f7 += $(obj-y) usart-f7.o 21 | 22 | all: stm32f429i-disco stm32429i-eval stm32f469i-disco stm32746g-eval stm32h743i-eval 23 | 24 | %.o: %.c 25 | $(CC) -c $(CFLAGS) -DKERNEL_ADDR=$(KERNEL_ADDR) -DDTB_ADDR=$(DTB_ADDR) $< -o $@ 26 | 27 | stm32f429i-disco: stm32f429i-disco.o $(obj-f4) 28 | $(LD) -T stm32f429.lds $(LINKERFLAGS) -o stm32f429i-disco.elf stm32f429i-disco.o $(obj-f4) 29 | $(OBJCOPY) -Obinary stm32f429i-disco.elf stm32f429i-disco.bin 30 | $(SIZE) stm32f429i-disco.elf 31 | 32 | stm32429i-eval: stm32429i-eval.o $(obj-f4) 33 | $(LD) -T stm32f429.lds $(LINKERFLAGS) -o stm32429i-eval.elf stm32429i-eval.o $(obj-f4) 34 | $(OBJCOPY) -Obinary stm32429i-eval.elf stm32429i-eval.bin 35 | $(SIZE) stm32429i-eval.elf 36 | 37 | stm32f469i-disco: stm32f469i-disco.o $(obj-f4) 38 | $(LD) -T stm32f429.lds $(LINKERFLAGS) -o stm32f469i-disco.elf stm32f469i-disco.o $(obj-f4) 39 | $(OBJCOPY) -Obinary stm32f469i-disco.elf stm32f469i-disco.bin 40 | $(SIZE) stm32f469i-disco.elf 41 | 42 | stm32746g-eval: stm32746g-eval.o $(obj-f7) 43 | $(LD) -T stm32f429.lds $(LINKERFLAGS) -o stm32746g-eval.elf stm32746g-eval.o $(obj-f7) 44 | $(OBJCOPY) -Obinary stm32746g-eval.elf stm32746g-eval.bin 45 | $(SIZE) stm32746g-eval.elf 46 | 47 | stm32h743i-eval: stm32h743i-eval.o $(obj-f7) 48 | $(LD) -T stm32h743.lds $(LINKERFLAGS) -o stm32h743i-eval.elf stm32h743i-eval.o $(obj-f7) 49 | $(OBJCOPY) -Obinary stm32h743i-eval.elf stm32h743i-eval.bin 50 | $(SIZE) stm32h743i-eval.elf 51 | 52 | clean: 53 | @rm -f *.o *.elf *.bin *.lst 54 | 55 | flash_stm32f429i-disco: stm32f429i-disco 56 | $(OPENOCD) -f board/stm32f429discovery.cfg \ 57 | -c "init" \ 58 | -c "reset init" \ 59 | -c "flash probe 0" \ 60 | -c "flash info 0" \ 61 | -c "flash write_image erase stm32f429i-disco.bin 0x08000000" \ 62 | -c "reset run" \ 63 | -c "shutdown" 64 | 65 | flash_stm32429i-eval: stm32429i-eval 66 | $(OPENOCD) -f board/stm32429i_eval_stlink.cfg \ 67 | -c "init" \ 68 | -c "reset init" \ 69 | -c "flash probe 0" \ 70 | -c "flash info 0" \ 71 | -c "flash write_image erase stm32429i-eval.bin 0x08000000" \ 72 | -c "reset run" \ 73 | -c "shutdown" 74 | 75 | flash_stm32f469i-disco: stm32f469i-disco 76 | $(OPENOCD) -f board/stm32f469discovery.cfg \ 77 | -c "init" \ 78 | -c "reset init" \ 79 | -c "flash probe 0" \ 80 | -c "flash info 0" \ 81 | -c "flash write_image erase stm32f469i-disco.bin 0x08000000" \ 82 | -c "reset run" \ 83 | -c "shutdown" 84 | 85 | flash_stm32746g-eval: stm32746g-eval 86 | $(OPENOCD) -f interface/stlink-v2-1.cfg -f board/stm327x6g_eval.cfg \ 87 | -c "init" \ 88 | -c "reset init" \ 89 | -c "flash probe 0" \ 90 | -c "flash info 0" \ 91 | -c "flash write_image erase stm32746g-eval.bin 0x08000000" \ 92 | -c "reset run" \ 93 | -c "shutdown" 94 | 95 | flash_stm32h743i-eval: stm32h743i-eval 96 | $(OPENOCD) -f interface/stlink-v2-1.cfg -f board/stm32h7xx_eval.cfg \ 97 | -c "init" \ 98 | -c "reset init"\ 99 | -c "flash probe 0" \ 100 | -c "flash info 0" \ 101 | -c "flash write_image erase stm32h743i-eval.bin 0x08000000" \ 102 | -c "reset run" \ 103 | -c "shutdown" 104 | 105 | debug_stm32f429i-disco: stm32f429i-disco 106 | $(GDB) stm32f429i-disco.elf -ex "target remote :3333" -ex "monitor reset halt" 107 | 108 | debug_stm32429i-eval: stm32429i-eval 109 | $(GDB) stm32429i-eval.elf -ex "target remote :3333" -ex "monitor reset halt" 110 | 111 | debug_stm32f469i-disco: stm32f469i-disco 112 | $(GDB) stm32f469i-disco.elf -ex "target remote :3333" -ex "monitor reset halt" 113 | 114 | debug_stm32746g-eval: stm32746g-eval 115 | $(GDB) stm32746g-eval.elf -ex "target remote :3333" -ex "monitor reset halt" 116 | 117 | debug_stm32h743i-eval: stm32h743i-eval 118 | $(GDB) stm32h743i-eval.elf -ex "target remote :3333" -ex "monitor reset halt" 119 | -------------------------------------------------------------------------------- /qspi.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qspi.h" 4 | 5 | void quadspi_busy_wait(void *base) 6 | { 7 | volatile uint32_t *QUADSPI_SR = base + 0x08; 8 | 9 | while (*QUADSPI_SR & QUADSPI_SR_BUSY); 10 | } 11 | 12 | void quadspi_wait_flag(void *base, uint32_t flag) 13 | { 14 | volatile uint32_t *QUADSPI_SR = base + 0x08; 15 | volatile uint32_t *QUADSPI_FCR = base + 0x0c; 16 | 17 | while (!(*QUADSPI_SR & flag)); 18 | *QUADSPI_FCR = flag; 19 | } 20 | 21 | void quadspi_write_enable(void *base) 22 | { 23 | volatile uint32_t *QUADSPI_CR = base + 0x00; 24 | volatile uint32_t *QUADSPI_DLR = base + 0x10; 25 | volatile uint32_t *QUADSPI_CCR = base + 0x14; 26 | volatile uint32_t *QUADSPI_PSMKR = base + 0x24; 27 | volatile uint32_t *QUADSPI_PSMAR = base + 0x28; 28 | volatile uint32_t *QUADSPI_PIR = base + 0x2c; 29 | 30 | quadspi_busy_wait(base); 31 | 32 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_IND_WR | QUADSPI_CCR_IDMOD_1_LINE | 33 | WRITE_ENABLE_CMD; 34 | 35 | quadspi_wait_flag(base, QUADSPI_SR_TCF); 36 | 37 | quadspi_busy_wait(base); 38 | 39 | *QUADSPI_PSMAR = N25Q512A_SR_WREN; 40 | *QUADSPI_PSMKR = N25Q512A_SR_WREN; 41 | *QUADSPI_PIR = 0x10; 42 | 43 | *QUADSPI_CR |= QUADSPI_CR_AMPS; 44 | *QUADSPI_DLR = 0; 45 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_AUTO_POLL | QUADSPI_CCR_DMODE_1_LINE | 46 | QUADSPI_CCR_IDMOD_1_LINE | READ_STATUS_REG_CMD; 47 | 48 | quadspi_wait_flag(base, QUADSPI_SR_SMF); 49 | } 50 | 51 | void quadspi_init(struct qspi_params *params, void *base) 52 | { 53 | volatile uint32_t *QUADSPI_CR = base + 0x00; 54 | volatile uint32_t *QUADSPI_DCR = base + 0x04; 55 | volatile uint32_t *QUADSPI_SR = base + 0x08; 56 | volatile uint32_t *QUADSPI_DLR = base + 0x10; 57 | volatile uint32_t *QUADSPI_CCR = base + 0x14; 58 | volatile uint32_t *QUADSPI_AR = base + 0x18; 59 | volatile uint32_t *QUADSPI_DR = base + 0x20; 60 | volatile uint32_t *QUADSPI_PSMKR = base + 0x24; 61 | volatile uint32_t *QUADSPI_PSMAR = base + 0x28; 62 | volatile uint32_t *QUADSPI_PIR = base + 0x2c; 63 | uint32_t reg; 64 | 65 | *QUADSPI_CR = params->fifo_threshold; 66 | 67 | quadspi_busy_wait(base); 68 | 69 | *QUADSPI_CR |= QUADSPI_CR_PRESCALER(params->prescaler) | params->sshift | 70 | params->dfm | params->fsel; 71 | *QUADSPI_DCR = params->fsize | QUADSPI_DCR_CSHT(1); 72 | 73 | *QUADSPI_CR |= QUADSPI_CR_EN; 74 | 75 | /* Reset memory */ 76 | quadspi_busy_wait(base); 77 | 78 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_IND_WR | QUADSPI_CCR_IDMOD_1_LINE | 79 | RESET_ENABLE_CMD; 80 | 81 | quadspi_wait_flag(base, QUADSPI_SR_TCF); 82 | 83 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_IND_WR | QUADSPI_CCR_IDMOD_1_LINE | 84 | RESET_MEMORY_CMD; 85 | 86 | quadspi_wait_flag(base, QUADSPI_SR_TCF); 87 | 88 | quadspi_busy_wait(base); 89 | 90 | *QUADSPI_PSMAR = 0; 91 | *QUADSPI_PSMKR = N25Q512A_SR_WIP; 92 | *QUADSPI_PIR = 0x10; 93 | 94 | *QUADSPI_CR |= QUADSPI_CR_AMPS; 95 | *QUADSPI_DLR = 0; 96 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_AUTO_POLL | QUADSPI_CCR_DMODE_1_LINE | 97 | QUADSPI_CCR_IDMOD_1_LINE | READ_STATUS_REG_CMD; 98 | 99 | quadspi_wait_flag(base, QUADSPI_SR_SMF); 100 | 101 | /* Enter 4-bytes address mode */ 102 | quadspi_write_enable(base); 103 | 104 | quadspi_busy_wait(base); 105 | 106 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_IND_WR | QUADSPI_CCR_IDMOD_1_LINE | 107 | ENTER_4_BYTE_ADDR_MODE_CMD; 108 | 109 | quadspi_wait_flag(base, QUADSPI_SR_TCF); 110 | 111 | quadspi_busy_wait(base); 112 | 113 | *QUADSPI_PSMAR = 0; 114 | *QUADSPI_PSMKR = N25Q512A_SR_WIP; 115 | *QUADSPI_PIR = 0x10; 116 | 117 | *QUADSPI_CR |= QUADSPI_CR_AMPS; 118 | *QUADSPI_DLR = 0; 119 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_AUTO_POLL | QUADSPI_CCR_DMODE_1_LINE | 120 | QUADSPI_CCR_IDMOD_1_LINE | READ_STATUS_REG_CMD; 121 | 122 | quadspi_wait_flag(base, QUADSPI_SR_SMF); 123 | 124 | /* Configure dummy cycles on memory side */ 125 | 126 | quadspi_busy_wait(base); 127 | 128 | *QUADSPI_DLR = 0; 129 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_IND_WR | QUADSPI_CCR_DMODE_1_LINE | 130 | QUADSPI_CCR_IDMOD_1_LINE | READ_VOL_CFG_REG_CMD; 131 | 132 | *QUADSPI_CCR |= QUADSPI_CCR_FMODE_IND_RD; 133 | 134 | *QUADSPI_AR = *QUADSPI_AR; //Needed? 135 | 136 | while (!(*QUADSPI_SR & (QUADSPI_SR_FTF | QUADSPI_SR_TCF))); 137 | 138 | reg = *QUADSPI_DR; 139 | 140 | quadspi_wait_flag(base, QUADSPI_SR_TCF); 141 | 142 | reg = (reg & ~0xf0) | (params->dummy_cycle << 4); 143 | 144 | quadspi_write_enable(base); 145 | 146 | quadspi_busy_wait(base); 147 | 148 | *QUADSPI_DLR = 0; 149 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_IND_WR | QUADSPI_CCR_DMODE_1_LINE | 150 | QUADSPI_CCR_IDMOD_1_LINE | WRITE_VOL_CFG_REG_CMD; 151 | 152 | while (!(*QUADSPI_SR & QUADSPI_SR_FTF)); 153 | 154 | *QUADSPI_DR = reg; 155 | 156 | quadspi_wait_flag(base, QUADSPI_SR_TCF); 157 | 158 | quadspi_busy_wait(base); 159 | 160 | *QUADSPI_CCR = QUADSPI_CCR_FMODE_MEMMAP | QUADSPI_CCR_DMODE_4_LINES | 161 | QUADSPI_CCR_DCYC(params->dummy_cycle) | params->address_size | 162 | QUADSPI_CCR_ADMOD_1_LINE | QUADSPI_CCR_IDMOD_1_LINE | 163 | QUAD_OUTPUT_FAST_READ_CMD; 164 | 165 | quadspi_busy_wait(base); 166 | } 167 | 168 | -------------------------------------------------------------------------------- /stm32f429i-disco.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "stm32f4_regs.h" 5 | #include "usart.h" 6 | #include "gpio.h" 7 | #include "start_kernel.h" 8 | 9 | #define CONFIG_HSE_HZ 8000000 10 | #define CONFIG_PLL_M 8 11 | #define CONFIG_PLL_N 336 12 | #define CONFIG_PLL_P 2 13 | #define CONFIG_PLL_Q 7 14 | #define PLLCLK_HZ (((CONFIG_HSE_HZ / CONFIG_PLL_M) * CONFIG_PLL_N) / CONFIG_PLL_P) 15 | #if PLLCLK_HZ == 168000000 16 | #define FLASH_LATENCY 5 17 | #else 18 | #error PLL clock does not match 168 MHz 19 | #endif 20 | 21 | static void *usart_base = (void *)USART1_BASE; 22 | static void *gpio_base = (void *)GPIOA_BASE; 23 | 24 | static void clock_setup(void) 25 | { 26 | volatile uint32_t *RCC_CR = (void *)(RCC_BASE + 0x00); 27 | volatile uint32_t *RCC_PLLCFGR = (void *)(RCC_BASE + 0x04); 28 | volatile uint32_t *RCC_CFGR = (void *)(RCC_BASE + 0x08); 29 | volatile uint32_t *FLASH_ACR = (void *)(FLASH_BASE + 0x00); 30 | volatile uint32_t *RCC_AHB1ENR = (void *)(RCC_BASE + 0x30); 31 | volatile uint32_t *RCC_AHB2ENR = (void *)(RCC_BASE + 0x34); 32 | volatile uint32_t *RCC_AHB3ENR = (void *)(RCC_BASE + 0x38); 33 | volatile uint32_t *RCC_APB1ENR = (void *)(RCC_BASE + 0x40); 34 | volatile uint32_t *RCC_APB2ENR = (void *)(RCC_BASE + 0x44); 35 | volatile uint32_t *RCC_AHB1LPENR= (void *)(RCC_BASE + 0x50); 36 | uint32_t val; 37 | 38 | *RCC_CR |= RCC_CR_HSEON; 39 | while (!(*RCC_CR & RCC_CR_HSERDY)) { 40 | } 41 | 42 | val = *RCC_CFGR; 43 | val &= ~RCC_CFGR_HPRE_MASK; 44 | //val |= 0 << 4; // not divided 45 | val &= ~RCC_CFGR_PPRE1_MASK; 46 | val |= 0x5 << 10; // divided by 4 47 | val &= ~RCC_CFGR_PPRE2_MASK; 48 | val |= 0x4 << 13; // divided by 2 49 | *RCC_CFGR = val; 50 | 51 | val = 0; 52 | val |= RCC_PLLCFGR_PLLSRC_HSE; 53 | val |= CONFIG_PLL_M; 54 | val |= CONFIG_PLL_N << 6; 55 | val |= ((CONFIG_PLL_P >> 1) - 1) << 16; 56 | val |= CONFIG_PLL_Q << 24; 57 | *RCC_PLLCFGR = val; 58 | 59 | *RCC_CR |= RCC_CR_PLLON; 60 | while (!(*RCC_CR & RCC_CR_PLLRDY)); 61 | 62 | *FLASH_ACR = FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | FLASH_LATENCY; 63 | 64 | *RCC_CFGR &= ~RCC_CFGR_SW_MASK; 65 | *RCC_CFGR |= RCC_CFGR_SW_PLL; 66 | while ((*RCC_CFGR & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL) { 67 | } 68 | 69 | /* Enable all clocks, unused ones will be gated at end of kernel boot */ 70 | *RCC_AHB1ENR |= 0x7ef417ff; 71 | *RCC_AHB2ENR |= 0xf1; 72 | *RCC_AHB3ENR |= 0x1; 73 | *RCC_APB1ENR |= 0xf6fec9ff; 74 | *RCC_APB2ENR |= 0x4777f33; 75 | 76 | /* Clear bit OTGHSULPILPEN in register AHB1LPENR when OTG HS in FS mode with internal PHY */ 77 | /* https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FPower%20consumption%20without%20low%20power&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=469 */ 78 | *RCC_AHB1LPENR &= ~RCC_AHB1LPENR_OTGHSULPILPEN; 79 | } 80 | 81 | 82 | 83 | static void fmc_wait_busy(void) 84 | { 85 | volatile uint32_t *FMC_SDSR = (void *)(FMC_BASE + 0x158); 86 | 87 | while ((*FMC_SDSR & FMC_SDSR_BUSY)) { 88 | } 89 | } 90 | 91 | int main(void) 92 | { 93 | volatile uint32_t *FLASH_KEYR = (void *)(FLASH_BASE + 0x04); 94 | volatile uint32_t *FLASH_CR = (void *)(FLASH_BASE + 0x10); 95 | volatile uint32_t *FMC_SDCR1 = (void *)(FMC_BASE + 0x140); 96 | volatile uint32_t *FMC_SDCR2 = (void *)(FMC_BASE + 0x144); 97 | volatile uint32_t *FMC_SDTR1 = (void *)(FMC_BASE + 0x148); 98 | volatile uint32_t *FMC_SDTR2 = (void *)(FMC_BASE + 0x14C); 99 | volatile uint32_t *FMC_SDCMR = (void *)(FMC_BASE + 0x150); 100 | volatile uint32_t *FMC_SDRTR = (void *)(FMC_BASE + 0x154); 101 | volatile uint32_t *SYSCFG_MEMRMP = (void *)(SYSCFG_BASE + 0x00); 102 | int i; 103 | 104 | if (*FLASH_CR & FLASH_CR_LOCK) { 105 | *FLASH_KEYR = 0x45670123; 106 | *FLASH_KEYR = 0xCDEF89AB; 107 | } 108 | *FLASH_CR &= ~(FLASH_CR_ERRIE | FLASH_CR_EOPIE | FLASH_CR_PSIZE_MASK); 109 | *FLASH_CR |= FLASH_CR_PSIZE_X32; 110 | *FLASH_CR |= FLASH_CR_LOCK; 111 | 112 | clock_setup(); 113 | 114 | gpio_set_fmc(gpio_base, 'B', 5); 115 | gpio_set_fmc(gpio_base, 'B', 6); 116 | gpio_set_fmc(gpio_base, 'C', 0); 117 | gpio_set_fmc(gpio_base, 'D', 0); 118 | gpio_set_fmc(gpio_base, 'D', 1); 119 | gpio_set_fmc(gpio_base, 'D', 8); 120 | gpio_set_fmc(gpio_base, 'D', 9); 121 | gpio_set_fmc(gpio_base, 'D', 10); 122 | gpio_set_fmc(gpio_base, 'D', 14); 123 | gpio_set_fmc(gpio_base, 'D', 15); 124 | gpio_set_fmc(gpio_base, 'E', 0); 125 | gpio_set_fmc(gpio_base, 'E', 1); 126 | gpio_set_fmc(gpio_base, 'E', 7); 127 | gpio_set_fmc(gpio_base, 'E', 8); 128 | gpio_set_fmc(gpio_base, 'E', 9); 129 | gpio_set_fmc(gpio_base, 'E', 10); 130 | gpio_set_fmc(gpio_base, 'E', 11); 131 | gpio_set_fmc(gpio_base, 'E', 12); 132 | gpio_set_fmc(gpio_base, 'E', 13); 133 | gpio_set_fmc(gpio_base, 'E', 14); 134 | gpio_set_fmc(gpio_base, 'E', 15); 135 | gpio_set_fmc(gpio_base, 'F', 0); 136 | gpio_set_fmc(gpio_base, 'F', 1); 137 | gpio_set_fmc(gpio_base, 'F', 2); 138 | gpio_set_fmc(gpio_base, 'F', 3); 139 | gpio_set_fmc(gpio_base, 'F', 4); 140 | gpio_set_fmc(gpio_base, 'F', 5); 141 | gpio_set_fmc(gpio_base, 'F', 11); 142 | gpio_set_fmc(gpio_base, 'F', 12); 143 | gpio_set_fmc(gpio_base, 'F', 13); 144 | gpio_set_fmc(gpio_base, 'F', 14); 145 | gpio_set_fmc(gpio_base, 'F', 15); 146 | gpio_set_fmc(gpio_base, 'G', 0); 147 | gpio_set_fmc(gpio_base, 'G', 1); 148 | gpio_set_fmc(gpio_base, 'G', 4); 149 | gpio_set_fmc(gpio_base, 'G', 5); 150 | gpio_set_fmc(gpio_base, 'G', 8); 151 | gpio_set_fmc(gpio_base, 'G', 15); 152 | *FMC_SDCR1 = 0x00001800; 153 | *FMC_SDCR2 = 0x000019D4; 154 | *FMC_SDTR1 = 0x00106000; 155 | *FMC_SDTR2 = 0x00010361; 156 | 157 | fmc_wait_busy(); 158 | *FMC_SDCMR = 0x00000009; // clock 159 | for (i = 0; i < 50000000; i++) { // 10 ms 160 | asm volatile ("nop"); 161 | } 162 | fmc_wait_busy(); 163 | *FMC_SDCMR = 0x0000000A; // PALL 164 | fmc_wait_busy(); 165 | *FMC_SDCMR = 0x000000EB; // auto-refresh 166 | fmc_wait_busy(); 167 | *FMC_SDCMR = 0x0004600C; // external memory mode 168 | *FMC_SDRTR = 1386 << 1; // refresh rate 169 | fmc_wait_busy(); 170 | 171 | *SYSCFG_MEMRMP = SYSCFG_MEMRMP_SWP_FMC << 10; 172 | 173 | gpio_set_usart(gpio_base, 'A', 9, 7); 174 | gpio_set_usart(gpio_base, 'A', 10, 7); 175 | 176 | usart_setup(usart_base, PLLCLK_HZ/2); 177 | usart_putch(usart_base, '.'); 178 | 179 | start_kernel(); 180 | 181 | return 0; 182 | } 183 | 184 | static void noop(void) 185 | { 186 | usart_putch(usart_base, 'E'); 187 | while (1) { 188 | } 189 | } 190 | 191 | extern unsigned int _end_text; 192 | extern unsigned int _start_data; 193 | extern unsigned int _end_data; 194 | extern unsigned int _start_bss; 195 | extern unsigned int _end_bss; 196 | 197 | void reset(void) 198 | { 199 | unsigned int *src, *dst; 200 | 201 | asm volatile ("cpsid i"); 202 | 203 | src = &_end_text; 204 | dst = &_start_data; 205 | while (dst < &_end_data) { 206 | *dst++ = *src++; 207 | } 208 | 209 | dst = &_start_bss; 210 | while (dst < &_end_bss) { 211 | *dst++ = 0; 212 | } 213 | 214 | main(); 215 | } 216 | 217 | extern unsigned long _stack_top; 218 | 219 | __attribute__((section(".vector_table"))) 220 | void (*vector_table[16 + 91])(void) = { 221 | (void (*))&_stack_top, 222 | reset, 223 | noop, 224 | noop, 225 | noop, 226 | noop, 227 | noop, 228 | NULL, 229 | NULL, 230 | NULL, 231 | NULL, 232 | noop, 233 | noop, 234 | NULL, 235 | noop, 236 | noop, 237 | noop, 238 | noop, 239 | noop, 240 | noop, 241 | noop, 242 | noop, 243 | noop, 244 | noop, 245 | noop, 246 | noop, 247 | noop, 248 | noop, 249 | noop, 250 | noop, 251 | noop, 252 | noop, 253 | noop, 254 | noop, 255 | noop, 256 | noop, 257 | noop, 258 | noop, 259 | noop, 260 | noop, 261 | noop, 262 | noop, 263 | noop, 264 | noop, 265 | noop, 266 | noop, 267 | noop, 268 | noop, 269 | noop, 270 | noop, 271 | noop, 272 | noop, 273 | noop, 274 | noop, 275 | noop, 276 | noop, 277 | noop, 278 | noop, 279 | noop, 280 | noop, 281 | noop, 282 | noop, 283 | noop, 284 | noop, 285 | noop, 286 | noop, 287 | noop, 288 | noop, 289 | noop, 290 | noop, 291 | noop, 292 | noop, 293 | noop, 294 | noop, 295 | noop, 296 | noop, 297 | noop, 298 | noop, 299 | noop, 300 | noop, 301 | noop, 302 | noop, 303 | noop, 304 | noop, 305 | noop, 306 | noop, 307 | noop, 308 | noop, 309 | noop, 310 | noop, 311 | noop, 312 | noop, 313 | noop, 314 | noop, 315 | noop, 316 | noop, 317 | noop, 318 | noop, 319 | noop, 320 | noop, 321 | noop, 322 | noop, 323 | noop, 324 | noop, 325 | noop, 326 | noop, 327 | noop, 328 | }; 329 | -------------------------------------------------------------------------------- /stm32429i-eval.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "stm32f4_regs.h" 5 | #include "usart.h" 6 | #include "gpio.h" 7 | #include "mpu.h" 8 | #include "start_kernel.h" 9 | 10 | #define CONFIG_HSE_HZ 25000000 11 | #define CONFIG_PLL_M 25 12 | #define CONFIG_PLL_N 360 13 | #define CONFIG_PLL_P 2 14 | #define CONFIG_PLL_Q 7 15 | #define PLLCLK_HZ (((CONFIG_HSE_HZ / CONFIG_PLL_M) * CONFIG_PLL_N) / CONFIG_PLL_P) 16 | #if PLLCLK_HZ == 180000000 17 | #define FLASH_LATENCY 5 18 | #else 19 | #error PLL clock does not match 180 MHz 20 | #endif 21 | 22 | static void *usart_base = (void *)USART1_BASE; 23 | static void *gpio_base = (void *)GPIOA_BASE; 24 | 25 | static void clock_setup(void) 26 | { 27 | volatile uint32_t *RCC_CR = (void *)(RCC_BASE + 0x00); 28 | volatile uint32_t *RCC_PLLCFGR = (void *)(RCC_BASE + 0x04); 29 | volatile uint32_t *RCC_CFGR = (void *)(RCC_BASE + 0x08); 30 | volatile uint32_t *FLASH_ACR = (void *)(FLASH_BASE + 0x00); 31 | volatile uint32_t *RCC_AHB1ENR = (void *)(RCC_BASE + 0x30); 32 | volatile uint32_t *RCC_AHB2ENR = (void *)(RCC_BASE + 0x34); 33 | volatile uint32_t *RCC_AHB3ENR = (void *)(RCC_BASE + 0x38); 34 | volatile uint32_t *RCC_APB1ENR = (void *)(RCC_BASE + 0x40); 35 | volatile uint32_t *RCC_APB2ENR = (void *)(RCC_BASE + 0x44); 36 | uint32_t val; 37 | 38 | *RCC_CR |= RCC_CR_HSEON; 39 | while (!(*RCC_CR & RCC_CR_HSERDY)); 40 | 41 | val = *RCC_CFGR; 42 | val &= ~RCC_CFGR_HPRE_MASK; 43 | //val |= 0 << 4; // not divided 44 | val &= ~RCC_CFGR_PPRE1_MASK; 45 | val |= 0x5 << 10; // divided by 4 46 | val &= ~RCC_CFGR_PPRE2_MASK; 47 | val |= 0x4 << 13; // divided by 2 48 | *RCC_CFGR = val; 49 | 50 | val = 0; 51 | val |= RCC_PLLCFGR_PLLSRC_HSE; 52 | val |= CONFIG_PLL_M; 53 | val |= CONFIG_PLL_N << 6; 54 | val |= ((CONFIG_PLL_P >> 1) - 1) << 16; 55 | val |= CONFIG_PLL_Q << 24; 56 | *RCC_PLLCFGR = val; 57 | 58 | *RCC_CR |= RCC_CR_PLLON; 59 | while (*RCC_CR & RCC_CR_PLLRDY) { 60 | } 61 | 62 | *FLASH_ACR = FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | FLASH_LATENCY; 63 | 64 | *RCC_CFGR &= ~RCC_CFGR_SW_MASK; 65 | *RCC_CFGR |= RCC_CFGR_SW_PLL; 66 | while ((*RCC_CFGR & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL) { 67 | } 68 | 69 | /* Enable all clocks, unused ones will be gated at end of kernel boot */ 70 | *RCC_AHB1ENR |= 0x7ef417ff; 71 | *RCC_AHB2ENR |= 0xf1; 72 | *RCC_AHB3ENR |= 0x1; 73 | *RCC_APB1ENR |= 0xf6fec9ff; 74 | *RCC_APB2ENR |= 0x4777f33; 75 | 76 | } 77 | 78 | 79 | 80 | static void fmc_wait_busy(void) 81 | { 82 | volatile uint32_t *FMC_SDSR = (void *)(FMC_BASE + 0x158); 83 | 84 | while ((*FMC_SDSR & FMC_SDSR_BUSY)) { 85 | } 86 | } 87 | 88 | int main(void) 89 | { 90 | volatile uint32_t *FLASH_KEYR = (void *)(FLASH_BASE + 0x04); 91 | volatile uint32_t *FLASH_CR = (void *)(FLASH_BASE + 0x10); 92 | volatile uint32_t *FMC_SDCR1 = (void *)(FMC_BASE + 0x140); 93 | volatile uint32_t *FMC_SDTR1 = (void *)(FMC_BASE + 0x148); 94 | volatile uint32_t *FMC_SDCMR = (void *)(FMC_BASE + 0x150); 95 | volatile uint32_t *FMC_SDRTR = (void *)(FMC_BASE + 0x154); 96 | volatile uint32_t *SYSCFG_MEMRMP = (void *)(SYSCFG_BASE + 0x00); 97 | int i; 98 | 99 | mpu_config(0x0); 100 | 101 | if (*FLASH_CR & FLASH_CR_LOCK) { 102 | *FLASH_KEYR = 0x45670123; 103 | *FLASH_KEYR = 0xCDEF89AB; 104 | } 105 | *FLASH_CR &= ~(FLASH_CR_ERRIE | FLASH_CR_EOPIE | FLASH_CR_PSIZE_MASK); 106 | *FLASH_CR |= FLASH_CR_PSIZE_X32; 107 | *FLASH_CR |= FLASH_CR_LOCK; 108 | 109 | clock_setup(); 110 | 111 | gpio_set_fmc(gpio_base, 'D', 0); //D2 112 | gpio_set_fmc(gpio_base, 'D', 1); //D3 113 | gpio_set_fmc(gpio_base, 'D', 8); //D13 114 | gpio_set_fmc(gpio_base, 'D', 9); //D14 115 | gpio_set_fmc(gpio_base, 'D', 10); //D15 116 | gpio_set_fmc(gpio_base, 'D', 11); //A16 117 | gpio_set_fmc(gpio_base, 'D', 12); //A17 118 | gpio_set_fmc(gpio_base, 'D', 13); //A18 119 | gpio_set_fmc(gpio_base, 'D', 14); //D0 120 | gpio_set_fmc(gpio_base, 'D', 15); //D1 121 | gpio_set_fmc(gpio_base, 'E', 0); //NBL0 122 | gpio_set_fmc(gpio_base, 'E', 1); //NBL1 123 | gpio_set_fmc(gpio_base, 'E', 7); //D4 124 | gpio_set_fmc(gpio_base, 'E', 8); //D5 125 | gpio_set_fmc(gpio_base, 'E', 9); //D6 126 | gpio_set_fmc(gpio_base, 'E', 10); //D7 127 | gpio_set_fmc(gpio_base, 'E', 11); //D8 128 | gpio_set_fmc(gpio_base, 'E', 12); //D9 129 | gpio_set_fmc(gpio_base, 'E', 13); //D10 130 | gpio_set_fmc(gpio_base, 'E', 14); //D11 131 | gpio_set_fmc(gpio_base, 'E', 15); //D12 132 | gpio_set_fmc(gpio_base, 'F', 0); //A0 133 | gpio_set_fmc(gpio_base, 'F', 1); //A1 134 | gpio_set_fmc(gpio_base, 'F', 2); //A2 135 | gpio_set_fmc(gpio_base, 'F', 3); //A3 136 | gpio_set_fmc(gpio_base, 'F', 4); //A4 137 | gpio_set_fmc(gpio_base, 'F', 5); //A5 138 | gpio_set_fmc(gpio_base, 'F', 11); //SDNRAS 139 | gpio_set_fmc(gpio_base, 'F', 12); //A6 140 | gpio_set_fmc(gpio_base, 'F', 13); //A7 141 | gpio_set_fmc(gpio_base, 'F', 14); //A8 142 | gpio_set_fmc(gpio_base, 'F', 15); //A9 143 | gpio_set_fmc(gpio_base, 'G', 0); //A10 144 | gpio_set_fmc(gpio_base, 'G', 1); //A11 145 | gpio_set_fmc(gpio_base, 'G', 2); //A12 146 | gpio_set_fmc(gpio_base, 'G', 3); //A13 147 | gpio_set_fmc(gpio_base, 'G', 4); //A14 148 | gpio_set_fmc(gpio_base, 'G', 5); //A15 149 | gpio_set_fmc(gpio_base, 'G', 8); //SDCLK 150 | gpio_set_fmc(gpio_base, 'G', 15); //SDNCAS 151 | gpio_set_fmc(gpio_base, 'H', 2); //SDCKE0 152 | gpio_set_fmc(gpio_base, 'H', 3); //SDNE0 153 | gpio_set_fmc(gpio_base, 'H', 5); //SDNWE 154 | gpio_set_fmc(gpio_base, 'H', 8); //D16 155 | gpio_set_fmc(gpio_base, 'H', 9); //D17 156 | gpio_set_fmc(gpio_base, 'H', 10); //D18 157 | gpio_set_fmc(gpio_base, 'H', 11); //D19 158 | gpio_set_fmc(gpio_base, 'H', 12); //D20 159 | gpio_set_fmc(gpio_base, 'H', 13); //D21 160 | gpio_set_fmc(gpio_base, 'H', 14); //D22 161 | gpio_set_fmc(gpio_base, 'H', 15); //D23 162 | gpio_set_fmc(gpio_base, 'I', 0); //D24 163 | gpio_set_fmc(gpio_base, 'I', 1); //D25 164 | gpio_set_fmc(gpio_base, 'I', 2); //D26 165 | gpio_set_fmc(gpio_base, 'I', 3); //D27 166 | gpio_set_fmc(gpio_base, 'I', 4); //NBL2 167 | gpio_set_fmc(gpio_base, 'I', 5); //NBL3 168 | gpio_set_fmc(gpio_base, 'I', 6); //D28 169 | gpio_set_fmc(gpio_base, 'I', 7); //D29 170 | gpio_set_fmc(gpio_base, 'I', 9); //D30 171 | gpio_set_fmc(gpio_base, 'I', 10); //D31 172 | *FMC_SDCR1 = 0x000019E5; 173 | *FMC_SDTR1 = 0x01115351; 174 | 175 | fmc_wait_busy(); 176 | *FMC_SDCMR = 0x00000011; // clock 177 | for (i = 0; i < 50000000; i++) { // 10 ms 178 | asm volatile ("nop"); 179 | } 180 | fmc_wait_busy(); 181 | *FMC_SDCMR = 0x00000012; // PALL 182 | fmc_wait_busy(); 183 | *FMC_SDCMR = 0x00000073; // auto-refresh 184 | fmc_wait_busy(); 185 | *FMC_SDCMR = 0x00046014; // external memory mode 186 | fmc_wait_busy(); 187 | 188 | *FMC_SDRTR |= 2812<<1; // refresh rate 189 | *FMC_SDCR1 &= 0xFFFFFDFF; 190 | 191 | gpio_set_usart(gpio_base, 'A', 9, 7); 192 | gpio_set_usart(gpio_base, 'A', 10, 7); 193 | 194 | usart_setup(usart_base, 90000000); 195 | usart_putch(usart_base, '.'); 196 | 197 | *SYSCFG_MEMRMP = 0x4; 198 | 199 | start_kernel(); 200 | 201 | return 0; 202 | } 203 | 204 | static void noop(void) 205 | { 206 | usart_putch(usart_base, 'E'); 207 | while (1) { 208 | } 209 | } 210 | 211 | extern unsigned int _end_text; 212 | extern unsigned int _start_data; 213 | extern unsigned int _end_data; 214 | extern unsigned int _start_bss; 215 | extern unsigned int _end_bss; 216 | 217 | void reset(void) 218 | { 219 | unsigned int *src, *dst; 220 | 221 | asm volatile ("cpsid i"); 222 | 223 | src = &_end_text; 224 | dst = &_start_data; 225 | while (dst < &_end_data) { 226 | *dst++ = *src++; 227 | } 228 | 229 | dst = &_start_bss; 230 | while (dst < &_end_bss) { 231 | *dst++ = 0; 232 | } 233 | 234 | main(); 235 | } 236 | 237 | extern unsigned long _stack_top; 238 | 239 | __attribute__((section(".vector_table"))) 240 | void (*vector_table[16 + 91])(void) = { 241 | (void (*))&_stack_top, 242 | reset, 243 | noop, 244 | noop, 245 | noop, 246 | noop, 247 | noop, 248 | NULL, 249 | NULL, 250 | NULL, 251 | NULL, 252 | noop, 253 | noop, 254 | NULL, 255 | noop, 256 | noop, 257 | noop, 258 | noop, 259 | noop, 260 | noop, 261 | noop, 262 | noop, 263 | noop, 264 | noop, 265 | noop, 266 | noop, 267 | noop, 268 | noop, 269 | noop, 270 | noop, 271 | noop, 272 | noop, 273 | noop, 274 | noop, 275 | noop, 276 | noop, 277 | noop, 278 | noop, 279 | noop, 280 | noop, 281 | noop, 282 | noop, 283 | noop, 284 | noop, 285 | noop, 286 | noop, 287 | noop, 288 | noop, 289 | noop, 290 | noop, 291 | noop, 292 | noop, 293 | noop, 294 | noop, 295 | noop, 296 | noop, 297 | noop, 298 | noop, 299 | noop, 300 | noop, 301 | noop, 302 | noop, 303 | noop, 304 | noop, 305 | noop, 306 | noop, 307 | noop, 308 | noop, 309 | noop, 310 | noop, 311 | noop, 312 | noop, 313 | noop, 314 | noop, 315 | noop, 316 | noop, 317 | noop, 318 | noop, 319 | noop, 320 | noop, 321 | noop, 322 | noop, 323 | noop, 324 | noop, 325 | noop, 326 | noop, 327 | noop, 328 | noop, 329 | noop, 330 | noop, 331 | noop, 332 | noop, 333 | noop, 334 | noop, 335 | noop, 336 | noop, 337 | noop, 338 | noop, 339 | noop, 340 | noop, 341 | noop, 342 | noop, 343 | noop, 344 | noop, 345 | noop, 346 | noop, 347 | noop, 348 | }; 349 | 350 | -------------------------------------------------------------------------------- /stm32746g-eval.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "stm32f4_regs.h" 5 | #include "usart.h" 6 | #include "gpio.h" 7 | #include "mpu.h" 8 | #include "start_kernel.h" 9 | #include "qspi.h" 10 | 11 | #define CONFIG_HSE_HZ 25000000 12 | #define CONFIG_PLL_M 25 13 | #define CONFIG_PLL_N 432 14 | #define CONFIG_PLL_P 2 15 | #define CONFIG_PLL_Q 9 16 | #define PLLCLK_HZ (((CONFIG_HSE_HZ / CONFIG_PLL_M) * CONFIG_PLL_N) / CONFIG_PLL_P) 17 | #if PLLCLK_HZ == 216000000 18 | #define FLASH_LATENCY 9 19 | #else 20 | #error PLL clock does not match 216 MHz 21 | #endif 22 | 23 | static void *usart_base = (void *)USART1_BASE; 24 | static void *gpio_base = (void *)GPIOA_BASE; 25 | 26 | static void clock_setup(void) 27 | { 28 | volatile uint32_t *RCC_CR = (void *)(RCC_BASE + 0x00); 29 | volatile uint32_t *RCC_PLLCFGR = (void *)(RCC_BASE + 0x04); 30 | volatile uint32_t *RCC_CFGR = (void *)(RCC_BASE + 0x08); 31 | volatile uint32_t *FLASH_ACR = (void *)(FLASH_BASE + 0x00); 32 | volatile uint32_t *RCC_AHB1ENR = (void *)(RCC_BASE + 0x30); 33 | volatile uint32_t *RCC_AHB2ENR = (void *)(RCC_BASE + 0x34); 34 | volatile uint32_t *RCC_AHB3ENR = (void *)(RCC_BASE + 0x38); 35 | volatile uint32_t *RCC_APB1ENR = (void *)(RCC_BASE + 0x40); 36 | volatile uint32_t *RCC_APB2ENR = (void *)(RCC_BASE + 0x44); 37 | volatile uint32_t *RCC_AHB3RST = (void *)(RCC_BASE + 0x18); 38 | uint32_t val; 39 | 40 | 41 | *RCC_CR |= RCC_CR_HSEON; 42 | while (!(*RCC_CR & RCC_CR_HSERDY)) { 43 | } 44 | 45 | val = *RCC_CFGR; 46 | val &= ~RCC_CFGR_HPRE_MASK; 47 | //val |= 0 << 4; // not divided 48 | val &= ~RCC_CFGR_PPRE1_MASK; 49 | val |= 0x5 << 10; // divided by 4 50 | val &= ~RCC_CFGR_PPRE2_MASK; 51 | val |= 0x4 << 13; // divided by 2 52 | *RCC_CFGR = val; 53 | 54 | val = 0; 55 | val |= RCC_PLLCFGR_PLLSRC_HSE; 56 | val |= CONFIG_PLL_M; 57 | val |= CONFIG_PLL_N << 6; 58 | val |= ((CONFIG_PLL_P >> 1) - 1) << 16; 59 | val |= CONFIG_PLL_Q << 24; 60 | *RCC_PLLCFGR = val; 61 | 62 | *RCC_CR |= RCC_CR_PLLON; 63 | while (!(*RCC_CR & RCC_CR_PLLRDY)); 64 | 65 | *FLASH_ACR = FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | FLASH_LATENCY; 66 | 67 | *RCC_CFGR &= ~RCC_CFGR_SW_MASK; 68 | *RCC_CFGR |= RCC_CFGR_SW_PLL; 69 | while ((*RCC_CFGR & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL) { 70 | } 71 | 72 | /* Enable all clocks, unused ones will be gated at end of kernel boot */ 73 | *RCC_AHB1ENR |= 0x7ef417ff; 74 | *RCC_AHB2ENR |= 0xf1; 75 | *RCC_AHB3ENR |= 0x3; 76 | *RCC_APB1ENR |= 0xf6fec9ff; 77 | *RCC_APB2ENR |= 0x4777f33; 78 | 79 | /* togle reset QSPI */ 80 | *RCC_AHB3RST |= 0x2; 81 | *RCC_AHB3RST &= 0xfffffffd; 82 | } 83 | 84 | 85 | 86 | static void fmc_wait_busy(void) 87 | { 88 | volatile uint32_t *FMC_SDSR = (void *)(FMC_BASE + 0x158); 89 | 90 | while ((*FMC_SDSR & FMC_SDSR_BUSY)) { 91 | } 92 | } 93 | 94 | int main(void) 95 | { 96 | volatile uint32_t *FLASH_KEYR = (void *)(FLASH_BASE + 0x04); 97 | volatile uint32_t *FLASH_CR = (void *)(FLASH_BASE + 0x10); 98 | volatile uint32_t *FMC_SDCR1 = (void *)(FMC_BASE + 0x140); 99 | volatile uint32_t *FMC_SDTR1 = (void *)(FMC_BASE + 0x148); 100 | volatile uint32_t *FMC_SDCMR = (void *)(FMC_BASE + 0x150); 101 | volatile uint32_t *FMC_SDRTR = (void *)(FMC_BASE + 0x154); 102 | struct qspi_params qspi_746_params = { 103 | .address_size = QUADSPI_CCR_ADSIZE_32BITS, 104 | .fifo_threshold = QUADSPI_CR_FTHRES(3), 105 | .sshift = QUADSPI_CR_SSHIFT, 106 | .fsize = QUADSPI_DCR_FSIZE_64MB, 107 | .prescaler = 1, 108 | .dummy_cycle = 10, 109 | .fsel = 0, 110 | .dfm = 0, 111 | }; 112 | int i; 113 | 114 | mpu_config(0xc0000000); 115 | 116 | if (*FLASH_CR & FLASH_CR_LOCK) { 117 | *FLASH_KEYR = 0x45670123; 118 | *FLASH_KEYR = 0xCDEF89AB; 119 | } 120 | *FLASH_CR &= ~(FLASH_CR_ERRIE | FLASH_CR_EOPIE | FLASH_CR_PSIZE_MASK); 121 | *FLASH_CR |= FLASH_CR_PSIZE_X32; 122 | *FLASH_CR |= FLASH_CR_LOCK; 123 | 124 | clock_setup(); 125 | 126 | gpio_set_fmc(gpio_base, 'D', 0); //D2 127 | gpio_set_fmc(gpio_base, 'D', 1); //D3 128 | gpio_set_fmc(gpio_base, 'D', 8); //D13 129 | gpio_set_fmc(gpio_base, 'D', 9); //D14 130 | gpio_set_fmc(gpio_base, 'D', 10); //D15 131 | gpio_set_fmc(gpio_base, 'D', 11); //A16 132 | gpio_set_fmc(gpio_base, 'D', 12); //A17 133 | gpio_set_fmc(gpio_base, 'D', 13); //A18 134 | gpio_set_fmc(gpio_base, 'D', 14); //D0 135 | gpio_set_fmc(gpio_base, 'D', 15); //D1 136 | gpio_set_fmc(gpio_base,'E', 0); //NBL0 137 | gpio_set_fmc(gpio_base,'E', 1); //NBL1 138 | gpio_set_fmc(gpio_base, 'E', 7); //D4 139 | gpio_set_fmc(gpio_base, 'E', 8); //D5 140 | gpio_set_fmc(gpio_base, 'E', 9); //D6 141 | gpio_set_fmc(gpio_base, 'E', 10); //D7 142 | gpio_set_fmc(gpio_base, 'E', 11); //D8 143 | gpio_set_fmc(gpio_base, 'E', 12); //D9 144 | gpio_set_fmc(gpio_base, 'E', 13); //D10 145 | gpio_set_fmc(gpio_base, 'E', 14); //D11 146 | gpio_set_fmc(gpio_base, 'E', 15); //D12 147 | gpio_set_fmc(gpio_base, 'F', 0); //A0 148 | gpio_set_fmc(gpio_base, 'F', 1); //A1 149 | gpio_set_fmc(gpio_base, 'F', 2); //A2 150 | gpio_set_fmc(gpio_base, 'F', 3); //A3 151 | gpio_set_fmc(gpio_base, 'F', 4); //A4 152 | gpio_set_fmc(gpio_base, 'F', 5); //A5 153 | gpio_set_fmc(gpio_base, 'F', 11); //SDNRAS 154 | gpio_set_fmc(gpio_base, 'F', 12); //A6 155 | gpio_set_fmc(gpio_base, 'F', 13); //A7 156 | gpio_set_fmc(gpio_base, 'F', 14); //A8 157 | gpio_set_fmc(gpio_base, 'F', 15); //A9 158 | gpio_set_fmc(gpio_base, 'G', 0); //A10 159 | gpio_set_fmc(gpio_base, 'G', 1); //A11 160 | gpio_set_fmc(gpio_base, 'G', 2); //A12 161 | gpio_set_fmc(gpio_base, 'G', 3); //A13 162 | gpio_set_fmc(gpio_base, 'G', 4); //A14 163 | gpio_set_fmc(gpio_base, 'G', 5); //A15 164 | gpio_set_fmc(gpio_base, 'G', 8); //SDCLK 165 | gpio_set_fmc(gpio_base, 'G', 15); //SDNCAS 166 | gpio_set_fmc(gpio_base, 'H', 2); //SDCKE0 167 | gpio_set_fmc(gpio_base, 'H', 3); //SDNE0 168 | gpio_set_fmc(gpio_base, 'H', 5); //SDNWE 169 | gpio_set_fmc(gpio_base, 'H', 8); //D16 170 | gpio_set_fmc(gpio_base, 'H', 9); //D17 171 | gpio_set_fmc(gpio_base, 'H', 10); //D18 172 | gpio_set_fmc(gpio_base, 'H', 11); //D19 173 | gpio_set_fmc(gpio_base, 'H', 12); //D20 174 | gpio_set_fmc(gpio_base, 'H', 13); //D21 175 | gpio_set_fmc(gpio_base, 'H', 14); //D22 176 | gpio_set_fmc(gpio_base, 'H', 15); //D23 177 | gpio_set_fmc(gpio_base, 'I', 0); //D24 178 | gpio_set_fmc(gpio_base, 'I', 1); //D25 179 | gpio_set_fmc(gpio_base, 'I', 2); //D26 180 | gpio_set_fmc(gpio_base, 'I', 3); //D27 181 | gpio_set_fmc(gpio_base, 'I', 4); //NBL2 182 | gpio_set_fmc(gpio_base, 'I', 5); //NBL3 183 | gpio_set_fmc(gpio_base, 'I', 6); //D28 184 | gpio_set_fmc(gpio_base, 'I', 7); //D29 185 | gpio_set_fmc(gpio_base, 'I', 9); //D30 186 | gpio_set_fmc(gpio_base, 'I', 10); //D31 187 | *FMC_SDCR1 = 0x000019E5; 188 | *FMC_SDTR1 = 0x01116361; 189 | 190 | fmc_wait_busy(); 191 | *FMC_SDCMR = 0x00000011; // clock 192 | for (i = 0; i < 50000000; i++) { // 10 ms 193 | asm volatile ("nop"); 194 | } 195 | 196 | fmc_wait_busy(); 197 | *FMC_SDCMR = 0x00000012; // PALL 198 | fmc_wait_busy(); 199 | *FMC_SDCMR = 0x00000073; // auto-refresh 200 | fmc_wait_busy(); 201 | *FMC_SDCMR = 0x00046014; // external memory mode 202 | fmc_wait_busy(); 203 | 204 | *FMC_SDRTR |= 2812<<1; // refresh rate 205 | *FMC_SDCR1 &= 0xFFFFFDFF; 206 | 207 | gpio_set_qspi(gpio_base, 'B', 6, GPIOx_PUPDR_PULLUP, 0xa); //CS 208 | gpio_set_qspi(gpio_base, 'B', 2, GPIOx_PUPDR_NOPULL, 0x9); //CLK 209 | gpio_set_qspi(gpio_base, 'F', 8, GPIOx_PUPDR_NOPULL, 0xa); //DO 210 | gpio_set_qspi(gpio_base, 'F', 9, GPIOx_PUPDR_NOPULL, 0xa); //D1 211 | gpio_set_qspi(gpio_base, 'F', 7, GPIOx_PUPDR_NOPULL, 0x9); //D2 212 | gpio_set_qspi(gpio_base, 'F', 6, GPIOx_PUPDR_NOPULL, 0x9); //D3 213 | 214 | quadspi_init(&qspi_746_params, (void *)QUADSPI_BASE); 215 | 216 | gpio_set_usart(gpio_base,'A', 9, 7); 217 | gpio_set_usart(gpio_base,'A', 10, 7); 218 | 219 | usart_setup(usart_base, 108000000); 220 | usart_putch(usart_base, '.'); 221 | 222 | start_kernel(); 223 | 224 | return 0; 225 | } 226 | 227 | static void noop(void) 228 | { 229 | usart_putch(usart_base, 'E'); 230 | while (1) { 231 | } 232 | } 233 | 234 | extern unsigned int _end_text; 235 | extern unsigned int _start_data; 236 | extern unsigned int _end_data; 237 | extern unsigned int _start_bss; 238 | extern unsigned int _end_bss; 239 | 240 | void reset(void) 241 | { 242 | unsigned int *src, *dst; 243 | 244 | asm volatile ("cpsid i"); 245 | 246 | src = &_end_text; 247 | dst = &_start_data; 248 | while (dst < &_end_data) { 249 | *dst++ = *src++; 250 | } 251 | 252 | dst = &_start_bss; 253 | while (dst < &_end_bss) { 254 | *dst++ = 0; 255 | } 256 | 257 | main(); 258 | } 259 | 260 | extern unsigned long _stack_top; 261 | 262 | __attribute__((section(".vector_table"))) 263 | void (*vector_table[16 + 91])(void) = { 264 | (void (*))&_stack_top, 265 | reset, 266 | noop, 267 | noop, 268 | noop, 269 | noop, 270 | noop, 271 | NULL, 272 | NULL, 273 | NULL, 274 | NULL, 275 | noop, 276 | noop, 277 | NULL, 278 | noop, 279 | noop, 280 | noop, 281 | noop, 282 | noop, 283 | noop, 284 | noop, 285 | noop, 286 | noop, 287 | noop, 288 | noop, 289 | noop, 290 | noop, 291 | noop, 292 | noop, 293 | noop, 294 | noop, 295 | noop, 296 | noop, 297 | noop, 298 | noop, 299 | noop, 300 | noop, 301 | noop, 302 | noop, 303 | noop, 304 | noop, 305 | noop, 306 | noop, 307 | noop, 308 | noop, 309 | noop, 310 | noop, 311 | noop, 312 | noop, 313 | noop, 314 | noop, 315 | noop, 316 | noop, 317 | noop, 318 | noop, 319 | noop, 320 | noop, 321 | noop, 322 | noop, 323 | noop, 324 | noop, 325 | noop, 326 | noop, 327 | noop, 328 | noop, 329 | noop, 330 | noop, 331 | noop, 332 | noop, 333 | noop, 334 | noop, 335 | noop, 336 | noop, 337 | noop, 338 | noop, 339 | noop, 340 | noop, 341 | noop, 342 | noop, 343 | noop, 344 | noop, 345 | noop, 346 | noop, 347 | noop, 348 | noop, 349 | noop, 350 | noop, 351 | noop, 352 | noop, 353 | noop, 354 | noop, 355 | noop, 356 | noop, 357 | noop, 358 | noop, 359 | noop, 360 | noop, 361 | noop, 362 | noop, 363 | noop, 364 | noop, 365 | noop, 366 | noop, 367 | noop, 368 | noop, 369 | noop, 370 | noop, 371 | }; 372 | 373 | -------------------------------------------------------------------------------- /stm32f469i-disco.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "stm32f4_regs.h" 5 | #include "usart.h" 6 | #include "gpio.h" 7 | #include "mpu.h" 8 | #include "qspi.h" 9 | #include "start_kernel.h" 10 | 11 | #define CONFIG_HSE_HZ 8000000 12 | #define CONFIG_PLL_M 8 13 | #define CONFIG_PLL_N 360 14 | #define CONFIG_PLL_P 2 15 | #define CONFIG_PLL_Q 7 16 | #define CONFIG_PLLSAI_N 192 17 | #define CONFIG_PLLSAI_P 4 18 | #define PLLCLK_HZ (((CONFIG_HSE_HZ / CONFIG_PLL_M) * CONFIG_PLL_N) / CONFIG_PLL_P) 19 | #define PLLSAICLK_HZ (((CONFIG_HSE_HZ / CONFIG_PLL_M) * CONFIG_PLLSAI_N) / CONFIG_PLLSAI_P) 20 | 21 | #if PLLCLK_HZ == 180000000 22 | #define FLASH_LATENCY 5 23 | #else 24 | #error PLL clock does not match 180 MHz 25 | #endif 26 | 27 | #if PLLSAICLK_HZ != 48000000 28 | #error PLLSAI clock does not match 48MHz 29 | #endif 30 | 31 | static void *usart_base = (void *)USART3_BASE; 32 | static void *gpio_base = (void *)GPIOA_BASE; 33 | 34 | static void clock_setup(void) 35 | { 36 | volatile uint32_t *RCC_CR = (void *)(RCC_BASE + 0x00); 37 | volatile uint32_t *RCC_PLLCFGR = (void *)(RCC_BASE + 0x04); 38 | volatile uint32_t *RCC_CFGR = (void *)(RCC_BASE + 0x08); 39 | volatile uint32_t *FLASH_ACR = (void *)(FLASH_BASE + 0x00); 40 | volatile uint32_t *RCC_AHB1ENR = (void *)(RCC_BASE + 0x30); 41 | volatile uint32_t *RCC_AHB2ENR = (void *)(RCC_BASE + 0x34); 42 | volatile uint32_t *RCC_AHB3ENR = (void *)(RCC_BASE + 0x38); 43 | volatile uint32_t *RCC_APB1ENR = (void *)(RCC_BASE + 0x40); 44 | volatile uint32_t *RCC_APB2ENR = (void *)(RCC_BASE + 0x44); 45 | volatile uint32_t *RCC_PLLSAICFGR = (void *)(RCC_BASE + 0x88); 46 | volatile uint32_t *RCC_DCKCFGR = (void *)(RCC_BASE + 0x8C); 47 | uint32_t val; 48 | 49 | *RCC_CR |= RCC_CR_HSEON; 50 | while (!(*RCC_CR & RCC_CR_HSERDY)) { 51 | } 52 | 53 | val = *RCC_CFGR; 54 | val &= ~RCC_CFGR_HPRE_MASK; 55 | //val |= 0 << 4; // not divided 56 | val &= ~RCC_CFGR_PPRE1_MASK; 57 | val |= 0x5 << 10; // divided by 4 58 | val &= ~RCC_CFGR_PPRE2_MASK; 59 | val |= 0x4 << 13; // divided by 2 60 | *RCC_CFGR = val; 61 | 62 | val = 0; 63 | val |= RCC_PLLCFGR_PLLSRC_HSE; 64 | val |= CONFIG_PLL_M; 65 | val |= CONFIG_PLL_N << 6; 66 | val |= ((CONFIG_PLL_P >> 1) - 1) << 16; 67 | val |= CONFIG_PLL_Q << 24; 68 | *RCC_PLLCFGR = val; 69 | 70 | val = 0; 71 | val |= CONFIG_PLLSAI_N << 6; 72 | val |= ((CONFIG_PLLSAI_P >> 1)- 1) << 16; 73 | *RCC_PLLSAICFGR = val; 74 | 75 | *RCC_CR |= RCC_CR_PLLON; 76 | while (!(*RCC_CR & RCC_CR_PLLRDY)); 77 | 78 | *RCC_CR |= RCC_CR_SAION; 79 | while (!(*RCC_CR & RCC_CR_SAIRDY)) { 80 | } 81 | *RCC_DCKCFGR |= RCC_DCKCFGR_48SRC_SAI; 82 | *RCC_DCKCFGR |= RCC_DCKCFGR_SDIO48; 83 | 84 | *FLASH_ACR = FLASH_ACR_ICEN | FLASH_ACR_PRFTEN | FLASH_LATENCY; 85 | 86 | *RCC_CFGR &= ~RCC_CFGR_SW_MASK; 87 | *RCC_CFGR |= RCC_CFGR_SW_PLL; 88 | while ((*RCC_CFGR & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL) { 89 | } 90 | 91 | /* Enable all clocks, unused ones will be gated at end of kernel boot */ 92 | *RCC_AHB1ENR |= 0x7ef417ff; 93 | *RCC_AHB2ENR |= 0xf1; 94 | *RCC_AHB3ENR |= 0x3; 95 | *RCC_APB1ENR |= 0xf6fec9ff; 96 | *RCC_APB2ENR |= 0x4777f33; 97 | 98 | } 99 | 100 | static void fmc_wait_busy(void) 101 | { 102 | volatile uint32_t *FMC_SDSR = (void *)(FMC_BASE + 0x158); 103 | 104 | while ((*FMC_SDSR & FMC_SDSR_BUSY)) { 105 | } 106 | } 107 | 108 | int main(void) 109 | { 110 | volatile uint32_t *FLASH_KEYR = (void *)(FLASH_BASE + 0x04); 111 | volatile uint32_t *FLASH_CR = (void *)(FLASH_BASE + 0x10); 112 | volatile uint32_t *FMC_SDCR1 = (void *)(FMC_BASE + 0x140); 113 | volatile uint32_t *FMC_SDTR1 = (void *)(FMC_BASE + 0x148); 114 | volatile uint32_t *FMC_SDCMR = (void *)(FMC_BASE + 0x150); 115 | volatile uint32_t *FMC_SDRTR = (void *)(FMC_BASE + 0x154); 116 | volatile uint32_t *SYSCFG_MEMRMP = (void *)(SYSCFG_BASE + 0x00); 117 | struct qspi_params qspi_469_params = { 118 | .address_size = QUADSPI_CCR_ADSIZE_24BITS, 119 | .fifo_threshold = QUADSPI_CR_FTHRES(1), 120 | .sshift = QUADSPI_CR_SSHIFT, 121 | .fsize = QUADSPI_DCR_FSIZE_64MB, 122 | .prescaler = 1, 123 | .dummy_cycle = 10, 124 | .fsel = 0, 125 | .dfm = 0, 126 | }; 127 | 128 | int i; 129 | 130 | mpu_config(0x0); 131 | 132 | if (*FLASH_CR & FLASH_CR_LOCK) { 133 | *FLASH_KEYR = 0x45670123; 134 | *FLASH_KEYR = 0xCDEF89AB; 135 | } 136 | *FLASH_CR &= ~(FLASH_CR_ERRIE | FLASH_CR_EOPIE | FLASH_CR_PSIZE_MASK); 137 | *FLASH_CR |= FLASH_CR_PSIZE_X32; 138 | *FLASH_CR |= FLASH_CR_LOCK; 139 | 140 | clock_setup(); 141 | 142 | gpio_set_fmc(gpio_base, 'C', 0); //SDNWE 143 | gpio_set_fmc(gpio_base, 'D', 0); //D2 144 | gpio_set_fmc(gpio_base, 'D', 1); //D3 145 | gpio_set_fmc(gpio_base, 'D', 8); //D13 146 | gpio_set_fmc(gpio_base, 'D', 9); //D14 147 | gpio_set_fmc(gpio_base, 'D', 10); //D15 148 | gpio_set_fmc(gpio_base, 'D', 14); //D0 149 | gpio_set_fmc(gpio_base, 'D', 15); //D1 150 | gpio_set_fmc(gpio_base, 'E', 0); //NBL0 151 | gpio_set_fmc(gpio_base, 'E', 1); //NBL1 152 | gpio_set_fmc(gpio_base, 'E', 7); //D4 153 | gpio_set_fmc(gpio_base, 'E', 8); //D5 154 | gpio_set_fmc(gpio_base, 'E', 9); //D6 155 | gpio_set_fmc(gpio_base, 'E', 10); //D7 156 | gpio_set_fmc(gpio_base, 'E', 11); //D8 157 | gpio_set_fmc(gpio_base, 'E', 12); //D9 158 | gpio_set_fmc(gpio_base, 'E', 13); //D10 159 | gpio_set_fmc(gpio_base, 'E', 14); //D11 160 | gpio_set_fmc(gpio_base, 'E', 15); //D12 161 | gpio_set_fmc(gpio_base, 'F', 0); //A0 162 | gpio_set_fmc(gpio_base, 'F', 1); //A1 163 | gpio_set_fmc(gpio_base, 'F', 2); //A2 164 | gpio_set_fmc(gpio_base, 'F', 3); //A3 165 | gpio_set_fmc(gpio_base, 'F', 4); //A4 166 | gpio_set_fmc(gpio_base, 'F', 5); //A5 167 | gpio_set_fmc(gpio_base, 'F', 11); //SDNRAS 168 | gpio_set_fmc(gpio_base, 'F', 12); //A6 169 | gpio_set_fmc(gpio_base, 'F', 13); //A7 170 | gpio_set_fmc(gpio_base, 'F', 14); //A8 171 | gpio_set_fmc(gpio_base, 'F', 15); //A9 172 | gpio_set_fmc(gpio_base, 'G', 0); //A10 173 | gpio_set_fmc(gpio_base, 'G', 1); //A11 174 | gpio_set_fmc(gpio_base, 'G', 4); //A14 175 | gpio_set_fmc(gpio_base, 'G', 5); //A15 176 | gpio_set_fmc(gpio_base, 'G', 8); //SDCLK 177 | gpio_set_fmc(gpio_base, 'G', 15); //SDNCAS 178 | gpio_set_fmc(gpio_base, 'H', 2); //SDCKE0 179 | gpio_set_fmc(gpio_base, 'H', 3); //SDNE0 180 | gpio_set_fmc(gpio_base, 'H', 8); //D16 181 | gpio_set_fmc(gpio_base, 'H', 9); //D17 182 | gpio_set_fmc(gpio_base, 'H', 10); //D18 183 | gpio_set_fmc(gpio_base, 'H', 11); //D19 184 | gpio_set_fmc(gpio_base, 'H', 12); //D20 185 | gpio_set_fmc(gpio_base, 'H', 13); //D21 186 | gpio_set_fmc(gpio_base, 'H', 14); //D22 187 | gpio_set_fmc(gpio_base, 'H', 15); //D23 188 | gpio_set_fmc(gpio_base, 'I', 0); //D24 189 | gpio_set_fmc(gpio_base, 'I', 1); //D25 190 | gpio_set_fmc(gpio_base, 'I', 2); //D26 191 | gpio_set_fmc(gpio_base, 'I', 3); //D27 192 | gpio_set_fmc(gpio_base, 'I', 4); //NBL2 193 | gpio_set_fmc(gpio_base, 'I', 5); //NBL3 194 | gpio_set_fmc(gpio_base, 'I', 6); //D28 195 | gpio_set_fmc(gpio_base, 'I', 7); //D29 196 | gpio_set_fmc(gpio_base, 'I', 9); //D30 197 | gpio_set_fmc(gpio_base, 'I', 10); //D31 198 | *FMC_SDCR1 = 0x000019E4; 199 | *FMC_SDTR1 = 0x01115351; 200 | 201 | fmc_wait_busy(); 202 | *FMC_SDCMR = 0x00000011; // clock 203 | for (i = 0; i < 50000000; i++) { // 10 ms 204 | asm volatile ("nop"); 205 | } 206 | fmc_wait_busy(); 207 | *FMC_SDCMR = 0x00000012; // PALL 208 | fmc_wait_busy(); 209 | *FMC_SDCMR = 0x00000073; // auto-refresh 210 | fmc_wait_busy(); 211 | *FMC_SDCMR = 0x00046014; // external memory mode 212 | fmc_wait_busy(); 213 | 214 | *FMC_SDRTR |= 1292<<1; // refresh rate 215 | *FMC_SDCR1 &= 0xFFFFFDFF; 216 | 217 | gpio_set_qspi(gpio_base, 'B', 6, GPIOx_PUPDR_PULLUP, 0xa); //CS 218 | gpio_set_qspi(gpio_base, 'F', 10, GPIOx_PUPDR_NOPULL, 0x9); //CLK 219 | gpio_set_qspi(gpio_base, 'F', 8, GPIOx_PUPDR_NOPULL, 0xa); //DO 220 | gpio_set_qspi(gpio_base, 'F', 9, GPIOx_PUPDR_NOPULL, 0xa); //D1 221 | gpio_set_qspi(gpio_base, 'F', 7, GPIOx_PUPDR_NOPULL, 0x9); //D2 222 | gpio_set_qspi(gpio_base, 'F', 6, GPIOx_PUPDR_NOPULL, 0x9); //D3 223 | 224 | quadspi_init(&qspi_469_params, (void *)QUADSPI_BASE); 225 | 226 | gpio_set_usart(gpio_base, 'B', 10, 7); 227 | gpio_set_usart(gpio_base, 'B', 11, 7); 228 | 229 | usart_setup(usart_base, 45000000); 230 | usart_putch(usart_base, '.'); 231 | 232 | *SYSCFG_MEMRMP = 0x4; 233 | 234 | start_kernel(); 235 | 236 | return 0; 237 | } 238 | 239 | static void noop(void) 240 | { 241 | usart_putch(usart_base, 'E'); 242 | while (1) { 243 | } 244 | } 245 | 246 | extern unsigned int _end_text; 247 | extern unsigned int _start_data; 248 | extern unsigned int _end_data; 249 | extern unsigned int _start_bss; 250 | extern unsigned int _end_bss; 251 | 252 | void reset(void) 253 | { 254 | unsigned int *src, *dst; 255 | 256 | asm volatile ("cpsid i"); 257 | 258 | src = &_end_text; 259 | dst = &_start_data; 260 | while (dst < &_end_data) { 261 | *dst++ = *src++; 262 | } 263 | 264 | dst = &_start_bss; 265 | while (dst < &_end_bss) { 266 | *dst++ = 0; 267 | } 268 | 269 | main(); 270 | } 271 | 272 | extern unsigned long _stack_top; 273 | 274 | __attribute__((section(".vector_table"))) 275 | void (*vector_table[16 + 91])(void) = { 276 | (void (*))&_stack_top, 277 | reset, 278 | noop, 279 | noop, 280 | noop, 281 | noop, 282 | noop, 283 | NULL, 284 | NULL, 285 | NULL, 286 | NULL, 287 | noop, 288 | noop, 289 | NULL, 290 | noop, 291 | noop, 292 | noop, 293 | noop, 294 | noop, 295 | noop, 296 | noop, 297 | noop, 298 | noop, 299 | noop, 300 | noop, 301 | noop, 302 | noop, 303 | noop, 304 | noop, 305 | noop, 306 | noop, 307 | noop, 308 | noop, 309 | noop, 310 | noop, 311 | noop, 312 | noop, 313 | noop, 314 | noop, 315 | noop, 316 | noop, 317 | noop, 318 | noop, 319 | noop, 320 | noop, 321 | noop, 322 | noop, 323 | noop, 324 | noop, 325 | noop, 326 | noop, 327 | noop, 328 | noop, 329 | noop, 330 | noop, 331 | noop, 332 | noop, 333 | noop, 334 | noop, 335 | noop, 336 | noop, 337 | noop, 338 | noop, 339 | noop, 340 | noop, 341 | noop, 342 | noop, 343 | noop, 344 | noop, 345 | noop, 346 | noop, 347 | noop, 348 | noop, 349 | noop, 350 | noop, 351 | noop, 352 | noop, 353 | noop, 354 | noop, 355 | noop, 356 | noop, 357 | noop, 358 | noop, 359 | noop, 360 | noop, 361 | noop, 362 | noop, 363 | noop, 364 | noop, 365 | noop, 366 | noop, 367 | noop, 368 | noop, 369 | noop, 370 | noop, 371 | noop, 372 | noop, 373 | noop, 374 | noop, 375 | noop, 376 | noop, 377 | noop, 378 | noop, 379 | noop, 380 | noop, 381 | noop, 382 | noop, 383 | }; 384 | -------------------------------------------------------------------------------- /stm32h743i-eval.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "stm32h7_regs.h" 5 | #include "usart.h" 6 | #include "gpio.h" 7 | #include "mpu.h" 8 | #include "qspi.h" 9 | #include "start_kernel.h" 10 | 11 | static void *usart_base = (void *)USART1_BASE; 12 | static void *gpio_base = (void *)GPIOA_BASE; 13 | 14 | void clock_setup(void) 15 | { 16 | volatile uint32_t *RCC_CR = (void *)(RCC_BASE_REG); 17 | volatile uint32_t *RCC_CFGR = (void *)(RCC_BASE_REG + 0x10); 18 | volatile uint32_t *RCC_D1CFGR = (void *)(RCC_BASE_REG + 0x18); 19 | volatile uint32_t *RCC_D2CFGR = (void *)(RCC_BASE_REG + 0x1c); 20 | volatile uint32_t *RCC_D3CFGR = (void *)(RCC_BASE_REG + 0x20); 21 | volatile uint32_t *RCC_PLLCKSELR = (void *)(RCC_BASE_REG + 0x28); 22 | volatile uint32_t *RCC_PLLCFGR = (void *)(RCC_BASE_REG + 0x2c); 23 | volatile uint32_t *RCC_PLL1DIVR = (void *)(RCC_BASE_REG + 0x30); 24 | volatile uint32_t *RCC_PLL1FRACR = (void *)(RCC_BASE_REG + 0x34); 25 | volatile uint32_t *RCC_PLL2DIVR = (void *)(RCC_BASE_REG + 0x38); 26 | volatile uint32_t *RCC_PLL2FRACR = (void *)(RCC_BASE_REG + 0x3c); 27 | volatile uint32_t *RCC_PLL3DIVR = (void *)(RCC_BASE_REG + 0x40); 28 | volatile uint32_t *RCC_PLL3FRACR = (void *)(RCC_BASE_REG + 0x44); 29 | volatile uint32_t *RCC_D1CCIPR = (void *)(RCC_BASE_REG + 0x4c); 30 | volatile uint32_t *RCC_D2CCIP1R = (void *)(RCC_BASE_REG + 0x50); 31 | volatile uint32_t *RCC_D2CCIP2R = (void *)(RCC_BASE_REG + 0x54); 32 | volatile uint32_t *RCC_D1AHB1ENR = (void *)(RCC_BASE_REG + 0xd4); 33 | volatile uint32_t *RCC_D2AHB1ENR = (void *)(RCC_BASE_REG + 0xd8); 34 | volatile uint32_t *RCC_D2AHB2ENR = (void *)(RCC_BASE_REG + 0xdc); 35 | volatile uint32_t *RCC_D3AHB1ENR = (void *)(RCC_BASE_REG + 0xe0); 36 | volatile uint32_t *RCC_D1APB1ENR = (void *)(RCC_BASE_REG + 0xe4); 37 | volatile uint32_t *RCC_D2APB1LENR = (void *)(RCC_BASE_REG + 0xe8); 38 | volatile uint32_t *RCC_D2APB1HENR = (void *)(RCC_BASE_REG + 0xec); 39 | volatile uint32_t *RCC_D2APB2ENR = (void *)(RCC_BASE_REG + 0xf0); 40 | volatile uint32_t *RCC_D3APB1ENR = (void *)(RCC_BASE_REG + 0xf4); 41 | volatile uint32_t *RCC_AHB3RST = (void *)(RCC_BASE_REG + 0x7c); 42 | volatile uint32_t *FLASH_FACR = (void *)(FLASH_BASE); 43 | volatile uint32_t *PWR_D3CR = (void *)(PWR_BASE + 0x18); 44 | volatile uint32_t *PWR_CR3 = (void *)(PWR_BASE + 0xc); 45 | uint32_t divm, divn, divp, divq, divr; 46 | 47 | /* enable HSI */ 48 | *RCC_CR |= RCC_CR_HSION; 49 | 50 | /* Reset CFGR register */ 51 | /* HSI by default as system clock*/ 52 | *RCC_CFGR = 0; 53 | 54 | /* reset registers ... */ 55 | *RCC_D1CFGR = 0; 56 | *RCC_D2CFGR = 0; 57 | *RCC_D3CFGR = 0; 58 | *RCC_PLLCKSELR = 0; 59 | *RCC_PLLCFGR = 0; 60 | *RCC_PLL1DIVR = 0; 61 | *RCC_PLL1FRACR = 0; 62 | *RCC_PLL2DIVR = 0; 63 | *RCC_PLL2FRACR = 0; 64 | *RCC_PLL3DIVR = 0; 65 | *RCC_PLL3FRACR = 0; 66 | 67 | /* Activate all clock */ 68 | *RCC_D3AHB1ENR = 0xFFFFFFFF; 69 | *RCC_D2APB2ENR = 0xFFFFFFFF; 70 | *RCC_D1AHB1ENR = 0xFFFFFFFF; 71 | *RCC_D2AHB1ENR = 0xFFFFFFFF; 72 | *RCC_D2AHB2ENR = 0xFFFFFFFF; 73 | *RCC_D1APB1ENR = 0xFFFFFFFF; 74 | *RCC_D2APB1LENR = 0xFFFFFFFF; 75 | *RCC_D2APB1HENR = 0xFFFFFFFF; 76 | *RCC_D3APB1ENR = 0xFFFFFFFF; 77 | *RCC_D1CCIPR = 0x00000000; 78 | *RCC_D2CCIP1R = 0x00000000; 79 | *RCC_D2CCIP2R = 0x00000000; 80 | 81 | /* Second level */ 82 | *PWR_D3CR |= 0xc000; 83 | *PWR_CR3 &= ~(0x4); 84 | 85 | while (!(*PWR_D3CR & (1 <<13))) { 86 | } 87 | /* disable HSE to configure it */ 88 | *RCC_CR &= ~(RCC_CR_HSEON); 89 | while ((*RCC_CR & RCC_CR_HSERDY)) { 90 | } 91 | /* clear HSE bypass and set it ON */ 92 | *RCC_CR &= (~RCC_CR_HSEBYP); 93 | *RCC_CR |=RCC_CR_HSEON; 94 | while (!(*RCC_CR & RCC_CR_HSERDY)) { 95 | } 96 | 97 | /* setup pll */ 98 | /* disable pll1 */ 99 | *RCC_CR &= ~(RCC_CR_PLL1ON); 100 | while ((*RCC_CR & RCC_CR_PLL1RDY)) { 101 | } 102 | /* Configure PLL1 as clock source: 103 | * OSC_HSE = 25 MHz 104 | * VCO = 500MHz 105 | * pll1_p = 250MHz / pll1_q = 250MHz*/ 106 | divm = 4; 107 | divn = 80; 108 | divp = 2; 109 | divq = 2; 110 | divr = 2; 111 | 112 | /* PLL SRC = HSE */ 113 | *RCC_PLLCKSELR |= (divm << 4 ) | 0x2; 114 | *RCC_PLL1DIVR |= ((divr - 1) << (24)) | ((divq - 1) << (16)) | ( (divp - 1) << 9) | (divn - 1); 115 | 116 | /* Enable divP1, divQ1, divR1, pll1fracn */ 117 | *RCC_PLLCFGR |= (2 << 2); 118 | *RCC_PLLCFGR |= (1 << 18) | (1 << 17) | (1 << 16); 119 | 120 | /* enable the main PLL */ 121 | *RCC_CR |= (1 << 24 ); 122 | while (!(*RCC_CR & RCC_CR_PLL1RDY)) { 123 | } 124 | 125 | /* set flash latency */ 126 | *FLASH_FACR &=0xfffffff0; 127 | *FLASH_FACR |= 0xa; 128 | 129 | /* set HPRE (/2) DI clk --> 125MHz */ 130 | *RCC_D1CFGR |= 8; 131 | 132 | /* select PLL1 as clcok source */ 133 | *RCC_CFGR |= 0x3; 134 | while ((((*RCC_CFGR)&0x3) != 0x3)) { 135 | } 136 | /* test for sdram: use pll1_q as fmc_k clk */ 137 | *RCC_D1CCIPR = 1 | (3 << 4); 138 | 139 | /* togle reset QSPI */ 140 | *RCC_AHB3RST |= (1 << 14); 141 | *RCC_AHB3RST &= ~(1 << 14); 142 | 143 | } 144 | 145 | void ext_mem_setup(void) 146 | { 147 | volatile uint32_t *RCC_D1AHB1RSTR = (void *)(RCC_BASE_REG + 0x7c); 148 | volatile uint32_t *FMC_BCR1 = (void *)(FMC_BASE); 149 | volatile uint32_t *FMC_SDCR1 = (void *)(FMC_BASE + 0x140); 150 | volatile uint32_t *FMC_SDCR2 = (void *)(FMC_BASE + 0x144); 151 | volatile uint32_t *FMC_SDTR1 = (void *)(FMC_BASE + 0x148); 152 | volatile uint32_t *FMC_SDTR2 = (void *)(FMC_BASE + 0x14c); 153 | volatile uint32_t *FMC_SDCMR = (void *)(FMC_BASE + 0x150); 154 | volatile uint32_t *FMC_SDRTR = (void *)(FMC_BASE + 0x154); 155 | volatile uint32_t *FMC_SDSR = (void *)(FMC_BASE + 0x158); 156 | uint32_t index, tmpreg = 0, timeout = 0xFFFF; 157 | 158 | /* Enable GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface 159 | clock */ 160 | /* GPIOC */ 161 | gpio_set_fmc(gpio_base, 'C', 0); 162 | gpio_set_fmc(gpio_base, 'C', 2); 163 | gpio_set_fmc(gpio_base, 'C', 3); 164 | /* GPIOD */ 165 | gpio_set_fmc(gpio_base, 'D', 0); 166 | gpio_set_fmc(gpio_base, 'D', 1); 167 | gpio_set_fmc(gpio_base, 'D', 8); 168 | gpio_set_fmc(gpio_base, 'D', 9); 169 | gpio_set_fmc(gpio_base, 'D', 10); 170 | gpio_set_fmc(gpio_base, 'D', 14); 171 | gpio_set_fmc(gpio_base, 'D', 15); 172 | /* GPIOE */ 173 | gpio_set_fmc(gpio_base, 'E', 0); 174 | gpio_set_fmc(gpio_base, 'E', 1); 175 | gpio_set_fmc(gpio_base, 'E', 7); 176 | gpio_set_fmc(gpio_base, 'E', 8); 177 | gpio_set_fmc(gpio_base, 'E', 9); 178 | gpio_set_fmc(gpio_base, 'E', 10); 179 | gpio_set_fmc(gpio_base, 'E', 11); 180 | gpio_set_fmc(gpio_base, 'E', 12); 181 | gpio_set_fmc(gpio_base, 'E', 13); 182 | gpio_set_fmc(gpio_base, 'E', 14); 183 | gpio_set_fmc(gpio_base, 'E', 15); 184 | /* GPIOF */ 185 | gpio_set_fmc(gpio_base, 'F', 0); 186 | gpio_set_fmc(gpio_base, 'F', 1); 187 | gpio_set_fmc(gpio_base, 'F', 2); 188 | gpio_set_fmc(gpio_base, 'F', 3); 189 | gpio_set_fmc(gpio_base, 'F', 4); 190 | gpio_set_fmc(gpio_base, 'F', 5); 191 | gpio_set_fmc(gpio_base, 'F', 11); 192 | gpio_set_fmc(gpio_base, 'F', 12); 193 | gpio_set_fmc(gpio_base, 'F', 13); 194 | gpio_set_fmc(gpio_base, 'F', 14); 195 | gpio_set_fmc(gpio_base, 'F', 15); 196 | /* GPIOG */ 197 | gpio_set_fmc(gpio_base, 'G', 0); 198 | gpio_set_fmc(gpio_base, 'G', 1); 199 | gpio_set_fmc(gpio_base, 'G', 2); 200 | gpio_set_fmc(gpio_base, 'G', 3); 201 | gpio_set_fmc(gpio_base, 'G', 4); 202 | gpio_set_fmc(gpio_base, 'G', 5); 203 | gpio_set_fmc(gpio_base, 'G', 8); 204 | gpio_set_fmc(gpio_base, 'G', 15); 205 | /* GPIOH */ 206 | gpio_set_fmc(gpio_base, 'H', 2); 207 | gpio_set_fmc(gpio_base, 'H', 3); 208 | gpio_set_fmc(gpio_base, 'H', 5); 209 | gpio_set_fmc(gpio_base, 'H', 6); 210 | gpio_set_fmc(gpio_base, 'H', 7); 211 | gpio_set_fmc(gpio_base, 'H', 8); 212 | gpio_set_fmc(gpio_base, 'H', 9); 213 | gpio_set_fmc(gpio_base, 'H', 10); 214 | gpio_set_fmc(gpio_base, 'H', 11); 215 | gpio_set_fmc(gpio_base, 'H', 12); 216 | gpio_set_fmc(gpio_base, 'H', 13); 217 | gpio_set_fmc(gpio_base, 'H', 14); 218 | gpio_set_fmc(gpio_base, 'H', 15); 219 | /* GPIOI */ 220 | gpio_set_fmc(gpio_base, 'I', 0); 221 | gpio_set_fmc(gpio_base, 'I', 1); 222 | gpio_set_fmc(gpio_base, 'I', 2); 223 | gpio_set_fmc(gpio_base, 'I', 3); 224 | gpio_set_fmc(gpio_base, 'I', 4); 225 | gpio_set_fmc(gpio_base, 'I', 5); 226 | gpio_set_fmc(gpio_base, 'I', 6); 227 | gpio_set_fmc(gpio_base, 'I', 7); 228 | gpio_set_fmc(gpio_base, 'I', 9); 229 | gpio_set_fmc(gpio_base, 'I', 10); 230 | 231 | /* Reset FMC */ 232 | *RCC_D1AHB1RSTR &= 0xffffefff; 233 | *RCC_D1AHB1RSTR |= 0x1000; 234 | *RCC_D1AHB1RSTR &= 0xffffefff; 235 | 236 | /*FMC controller Enable*/ 237 | *FMC_BCR1 |= 0x80000000; 238 | 239 | /* Bank2 config (SDCR2/SDTR2) is the most of time done by bank1 registers 240 | * (SDCR1 /SDTR1) FMC_CLK/2 */ 241 | *FMC_SDCR1 = 0x000019e5; 242 | *FMC_SDCR2 = 0x000019e5; 243 | 244 | *FMC_SDTR1 = 0x0fffffff; 245 | *FMC_SDTR2 = 0x0fffffff; 246 | 247 | /* SDRAM initialization sequence */ 248 | /* Clock enable command */ 249 | *FMC_SDCMR = 0x00000009; 250 | 251 | tmpreg = *FMC_SDSR & 0x00000020; 252 | while((tmpreg != 0) && (timeout-- > 0)) 253 | { 254 | tmpreg = *FMC_SDSR & 0x00000020; 255 | } 256 | /* Delay */ 257 | for (index = 0; index<1000; index++); 258 | 259 | /* PALL command */ 260 | *FMC_SDCMR = 0x000000a; 261 | timeout = 0xFFFF; 262 | while((tmpreg != 0) && (timeout-- > 0)) 263 | { 264 | tmpreg = *FMC_SDSR & 0x00000020; 265 | } 266 | 267 | *FMC_SDCMR = 0x000000eb; 268 | timeout = 0xFFFF; 269 | while((tmpreg != 0) && (timeout-- > 0)) 270 | { 271 | tmpreg = *FMC_SDSR & 0x00000020; 272 | } 273 | 274 | *FMC_SDCMR = 0x0004400c; 275 | timeout = 0xFFFF; 276 | while((tmpreg != 0) && (timeout-- > 0)) 277 | { 278 | tmpreg = *FMC_SDSR & 0x00000020; 279 | } 280 | /* Set refresh count */ 281 | tmpreg = *FMC_SDRTR; 282 | *FMC_SDRTR = (tmpreg | (0x00000603<<1)); 283 | 284 | tmpreg = *FMC_SDCR2; 285 | 286 | *FMC_SDCR1 = (tmpreg & 0xFFFFFDFF); 287 | *FMC_SDCR2 = (tmpreg & 0xFFFFFDFF); 288 | } 289 | 290 | #define SCB_BASE 0xe000ed00 291 | 292 | static void clean_icache(void) 293 | { 294 | volatile uint32_t *SCB_ICIALLU = (void *)(SCB_BASE + 0x250); 295 | 296 | asm volatile ("dsb"); 297 | asm volatile ("isb"); 298 | 299 | *SCB_ICIALLU = 0; 300 | 301 | asm volatile ("dsb"); 302 | asm volatile ("isb"); 303 | } 304 | 305 | static uint32_t clz(uint32_t data) 306 | { 307 | uint32_t count = 0; 308 | uint32_t mask = 0x80000000; 309 | 310 | while((data & mask) == 0) 311 | { 312 | count += 1u; 313 | mask = mask >> 1u; 314 | } 315 | 316 | return (count); 317 | } 318 | 319 | static void clean_dcache(void) 320 | { 321 | volatile uint32_t *SCB_CCSIDR = (void *)(SCB_BASE + 0x80); 322 | volatile uint32_t *SCB_CSSELR = (void *)(SCB_BASE + 0x84); 323 | volatile uint32_t *SCB_DCISW = (void *)(SCB_BASE + 0x260); 324 | uint32_t ccsidr, sshift, wshift, sets, ways, i, j; 325 | 326 | asm volatile ("dsb"); 327 | asm volatile ("isb"); 328 | 329 | *SCB_CSSELR = 0; 330 | 331 | ccsidr = *SCB_CCSIDR; 332 | sets = (ccsidr >> 13) & 0x7fff; 333 | sshift = (ccsidr & 7) + 4; 334 | ways = (ccsidr >> 3) & 0x3ff; 335 | wshift = clz(ways) & 0x1f; 336 | 337 | asm volatile ("dsb"); 338 | for (i = 0; i < sets; i++) 339 | for (j = 0; j < ways; j++) 340 | *SCB_DCISW = ((j << wshift) | (i << sshift)); 341 | 342 | asm volatile ("dsb"); 343 | asm volatile ("isb"); 344 | } 345 | 346 | int main(void) 347 | { 348 | struct qspi_params qspi_h743_params = { 349 | .address_size = QUADSPI_CCR_ADSIZE_32BITS, 350 | .fifo_threshold = QUADSPI_CR_FTHRES(0), 351 | .sshift = QUADSPI_CR_SSHIFT, 352 | .fsize = QUADSPI_DCR_FSIZE_128MB, 353 | .prescaler = 0, 354 | .dummy_cycle = 8, 355 | .fsel = QUADSPI_CR_FSEL, 356 | .dfm = QUADSPI_CR_DFM, 357 | }; 358 | 359 | mpu_config(0xd0000000); 360 | 361 | /* configure clocks */ 362 | clock_setup(); 363 | 364 | /* configure external memory controler */ 365 | ext_mem_setup(); 366 | 367 | gpio_set_qspi(gpio_base, 'B', 2, GPIOx_PUPDR_NOPULL, 0x9); //CLK 368 | /* QSPI BANK1 */ 369 | gpio_set_qspi(gpio_base, 'G', 6, GPIOx_PUPDR_PULLUP, 0xa); //CS 370 | gpio_set_qspi(gpio_base, 'F', 8, GPIOx_PUPDR_NOPULL, 0xa); //DO 371 | gpio_set_qspi(gpio_base, 'F', 9, GPIOx_PUPDR_NOPULL, 0xa); //D1 372 | gpio_set_qspi(gpio_base, 'F', 7, GPIOx_PUPDR_NOPULL, 0x9); //D2 373 | gpio_set_qspi(gpio_base, 'F', 6, GPIOx_PUPDR_NOPULL, 0x9); //D3 374 | /* QSPI BANK2 */ 375 | gpio_set_qspi(gpio_base, 'C', 11, GPIOx_PUPDR_PULLUP, 0x9); //CS 376 | gpio_set_qspi(gpio_base, 'H', 2, GPIOx_PUPDR_NOPULL, 0x9); //DO 377 | gpio_set_qspi(gpio_base, 'H', 3, GPIOx_PUPDR_NOPULL, 0x9); //D1 378 | gpio_set_qspi(gpio_base, 'G', 9, GPIOx_PUPDR_NOPULL, 0x9); //D2 379 | gpio_set_qspi(gpio_base, 'G', 14, GPIOx_PUPDR_NOPULL, 0x9); //D3 380 | 381 | quadspi_init(&qspi_h743_params, (void *)QUADSPI_BASE); 382 | 383 | gpio_set_usart(gpio_base, 'B', 14, 4); 384 | gpio_set_usart(gpio_base, 'B', 15, 4); 385 | 386 | usart_setup(usart_base, 125000000); 387 | usart_putch(usart_base, '.'); 388 | 389 | clean_dcache(); 390 | clean_icache(); 391 | 392 | start_kernel(); 393 | 394 | return 0; 395 | } 396 | 397 | extern unsigned int _end_text; 398 | extern unsigned int _start_data; 399 | extern unsigned int _end_data; 400 | extern unsigned int _start_bss; 401 | extern unsigned int _end_bss; 402 | 403 | void reset(void) 404 | { 405 | unsigned int *src, *dst; 406 | 407 | asm volatile ("cpsid i"); 408 | 409 | src = &_end_text; 410 | dst = &_start_data; 411 | while (dst < &_end_data) { 412 | *dst++ = *src++; 413 | } 414 | 415 | dst = &_start_bss; 416 | while (dst < &_end_bss) { 417 | *dst++ = 0; 418 | } 419 | main(); 420 | } 421 | 422 | static void noop(void) 423 | { 424 | usart_putch(usart_base, 'E'); 425 | while (1) { 426 | } 427 | } 428 | 429 | extern unsigned long _stack_top; 430 | 431 | __attribute__((section(".vector_table"))) 432 | void (*vector_table[16 + 91])(void) = { 433 | (void (*))&_stack_top, 434 | reset, 435 | noop, 436 | noop, 437 | noop, 438 | noop, 439 | noop, 440 | NULL, 441 | NULL, 442 | NULL, 443 | NULL, 444 | noop, 445 | noop, 446 | NULL, 447 | noop, 448 | noop, 449 | noop, 450 | noop, 451 | noop, 452 | noop, 453 | noop, 454 | noop, 455 | noop, 456 | noop, 457 | noop, 458 | noop, 459 | noop, 460 | noop, 461 | noop, 462 | noop, 463 | noop, 464 | noop, 465 | noop, 466 | noop, 467 | noop, 468 | noop, 469 | noop, 470 | noop, 471 | noop, 472 | noop, 473 | noop, 474 | noop, 475 | noop, 476 | noop, 477 | noop, 478 | noop, 479 | noop, 480 | noop, 481 | noop, 482 | noop, 483 | noop, 484 | noop, 485 | noop, 486 | noop, 487 | noop, 488 | noop, 489 | noop, 490 | noop, 491 | noop, 492 | noop, 493 | noop, 494 | noop, 495 | noop, 496 | noop, 497 | noop, 498 | noop, 499 | noop, 500 | noop, 501 | noop, 502 | noop, 503 | noop, 504 | noop, 505 | noop, 506 | noop, 507 | noop, 508 | noop, 509 | noop, 510 | noop, 511 | noop, 512 | noop, 513 | noop, 514 | noop, 515 | noop, 516 | noop, 517 | noop, 518 | noop, 519 | noop, 520 | noop, 521 | noop, 522 | noop, 523 | noop, 524 | noop, 525 | noop, 526 | noop, 527 | noop, 528 | noop, 529 | noop, 530 | noop, 531 | noop, 532 | noop, 533 | noop, 534 | noop, 535 | noop, 536 | noop, 537 | noop, 538 | noop, 539 | noop, 540 | }; 541 | --------------------------------------------------------------------------------