diff --git a/RA-0x0001-GPIO-Output/image_def.s b/RA-0x0001-GPIO-Output/image_def.s index 0bd6fa7..ba63d51 100644 --- a/RA-0x0001-GPIO-Output/image_def.s +++ b/RA-0x0001-GPIO-Output/image_def.s @@ -1,38 +1,33 @@ -/** - * FILE: image_def.s - * - * DESCRIPTION: - * RP2350 IMAGE_DEF Block. - * A minimum amount of metadata (a valid IMAGE_DEF block) must be embedded in any - * binary for the bootrom to recognise it as a valid program image, as opposed to, - * for example, blank flash contents or a disconnected flash device. This must - * appear within the first 4 kB of a flash image, or anywhere in a RAM or OTP image. - * Unlike RP2040, there is no requirement for flash binaries to have a checksummed - * "boot2" flash setup function at flash address 0. The RP2350 bootrom performs a - * simple best‑effort XIP setup during flash scanning, and a flash‑resident program - * can continue executing in this state, or can choose to reconfigure the QSPI - * interface at a later time for best performance. - * - * AUTHOR: Kevin Thomas - * CREATION DATE: October 5, 2025 - * UPDATE DATE: October 5, 2025 - * - * REFERENCE: - * RP2350 Datasheet, Section 5.9.5 Minimum viable image metadata - * - * NOTES: - * In the Pico SDK, this block is generated automatically from - * embedded_start_block.inc.S / embedded_end_block.inc.S. - */ - -.section .picobin_block, "a" // place IMAGE_DEF block in flash - -.word 0xffffded3 // PICOBIN_BLOCK_MARKER_START -.byte 0x42 // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE -.byte 0x1 // item is 1 word in size -.hword 0b0001000000100001 // SECURE mode (0x1021) -.byte 0xff // PICOBIN_BLOCK_ITEM_2BS_LAST -.hword 0x0001 // item is 1 word in size -.byte 0x0 // pad -.word 0x0 // relative pointer to next block (0 = loop to self) -.word 0xab123579 // PICOBIN_BLOCK_MARKER_END +/** + * FILE: image_def.s + * + * DESCRIPTION: + * RP2350 IMAGE_DEF Block. + * + * BRIEF: + * A minimum amount of metadata (a valid IMAGE_DEF block) must be embedded in any + * binary for the bootrom to recognise it as a valid program image, as opposed to, + * for example, blank flash contents or a disconnected flash device. This must + * appear within the first 4 kB of a flash image, or anywhere in a RAM or OTP image. + * Unlike RP2040, there is no requirement for flash binaries to have a checksummed + * "boot2" flash setup function at flash address 0. The RP2350 bootrom performs a + * simple best‑effort XIP setup during flash scanning, and a flash‑resident program + * can continue executing in this state, or can choose to reconfigure the QSPI + * interface at a later time for best performance. + * + * AUTHOR: Kevin Thomas + * CREATION DATE: October 5, 2025 + * UPDATE DATE: October 5, 2025 + */ + +.section .picobin_block, "a" // place IMAGE_DEF block in flash + +.word 0xFFFFDED3 // PICOBIN_BLOCK_MARKER_START +.byte 0x42 // PICOBIN_BLOCK_ITEM_1BS_IMAGE_TYPE +.byte 0x1 // item is 1 word in size +.hword 0b0001000000100001 // SECURE mode (0x1021) +.byte 0xFF // PICOBIN_BLOCK_ITEM_2BS_LAST +.hword 0x0001 // item is 1 word in size +.byte 0x0 // pad +.word 0x0 // relative pointer to next block (0 = loop to self) +.word 0xAB123579 // PICOBIN_BLOCK_MARKER_END diff --git a/RA-0x0001-GPIO-Output/linker.ld b/RA-0x0001-GPIO-Output/linker.ld index f8aa36d..23bcbb8 100644 --- a/RA-0x0001-GPIO-Output/linker.ld +++ b/RA-0x0001-GPIO-Output/linker.ld @@ -1,104 +1,91 @@ -/** - * FILE: linker.ld - * - * DESCRIPTION: - * RP2350 Minimal Linker Script for bare‑metal development. - * Ensures the boot ROM accepts and runs the image by: - * - Placing the IMAGE_DEF block first at 0x10000000 - * - Aligning the vector table to a 128‑byte boundary within the first 4 KB - * - Defining a non‑secure stack region in SRAM - * - * AUTHOR: Kevin Thomas - * CREATION DATE: October 5, 2025 - * UPDATE DATE: October 5, 2025 - * - * KEY FEATURES: - * - FLASH origin at 0x10000000 (XIP base), 32 MB length - * - RAM origin at 0x20000000, 512 KB non‑secure window - * - IMAGE_DEF block emitted before all other sections - * - Vector table alignment and assertion to satisfy ROM requirements - * - Symbols for __StackTop, __StackLimit, and __Vectors provided - * - * REFERENCE: - * RP2350 Datasheet, Section 5.9.5 Minimum viable image metadata - * - * NOTES: - * This script is intentionally minimal to support reproducible, - * SDK‑free bare‑metal builds. It pairs with a standalone IMAGE_DEF - * assembly file and a vector table defined in your startup code. - */ - -ENTRY(Reset_Handler) - -/** - * Define memory regions. - */ -__XIP_BASE = 0x10000000; -__XIP_SIZE = 32M; - -__SRAM_BASE = 0x20000000; -__SRAM_SIZE = 512K; /* non-secure window */ -__STACK_SIZE = 32K; - -MEMORY -{ - RAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE - FLASH (rx) : ORIGIN = __XIP_BASE, LENGTH = __XIP_SIZE -} - -/** - * Program headers. - */ -PHDRS -{ - text PT_LOAD FLAGS(5); /* RX */ -} - -/** - * Section placement. - */ -SECTIONS -{ - . = ORIGIN(FLASH); - - /** - * Minimal IMAGE_DEF must be first. - */ - .embedded_block : - { - KEEP(*(.embedded_block)) - } > FLASH :text - - /** - * Force the vector table section start to a 128-byte boundary. - */ - .vectors ALIGN(128) : - { - KEEP(*(.vectors)) - } > FLASH :text - - ASSERT(((ADDR(.vectors) - ORIGIN(FLASH)) < 0x1000), - "Vector table must be in first 4KB of flash") - - /** - * Text and read-only data. - */ - .text : - { - . = ALIGN(4); - *(.text*) - *(.rodata*) - KEEP(*(.ARM.attributes)) - } > FLASH :text - - /** - * Non-secure stack symbols. - */ - __StackTop = ORIGIN(RAM) + LENGTH(RAM); /* 0x20080000 */ - __StackLimit = __StackTop - __STACK_SIZE; - __stack = __StackTop; - - .stack (NOLOAD) : { . = ALIGN(8); } > RAM - - PROVIDE(__Vectors = ADDR(.vectors)); -} +/** + * FILE: linker.ld + * + * DESCRIPTION: + * RP2350 Minimal Linker Script for bare‑metal development. + * + * BRIEF: + * Ensures the boot ROM accepts and runs the image by placing + * the IMAGE_DEF block first at 0x10000000, aligning the vector + * table to a 128‑byte boundary within the first 4 KB and defining + * a non‑secure stack region in SRAM. + * + * AUTHOR: Kevin Thomas + * CREATION DATE: October 5, 2025 + * UPDATE DATE: October 5, 2025 + */ + +ENTRY(Reset_Handler) + +/** + * Define memory regions. + */ +__XIP_BASE = 0x10000000; +__XIP_SIZE = 32M; + +__SRAM_BASE = 0x20000000; +__SRAM_SIZE = 512K; /* non-secure window */ +__STACK_SIZE = 32K; + +MEMORY +{ + RAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE + FLASH (rx) : ORIGIN = __XIP_BASE, LENGTH = __XIP_SIZE +} + +/** + * Program headers. + */ +PHDRS +{ + text PT_LOAD FLAGS(5); /* RX */ +} + +/** + * Section placement. + */ +SECTIONS +{ + . = ORIGIN(FLASH); + + /** + * Minimal IMAGE_DEF must be first. + */ + .embedded_block : + { + KEEP(*(.embedded_block)) + } > FLASH :text + + /** + * Force the vector table section start to a 128-byte boundary. + */ + .vectors ALIGN(128) : + { + KEEP(*(.vectors)) + } > FLASH :text + + ASSERT(((ADDR(.vectors) - ORIGIN(FLASH)) < 0x1000), + "Vector table must be in first 4KB of flash") + + /** + * Text and read-only data. + */ + .text : + { + . = ALIGN(4); + *(.text*) + *(.rodata*) + KEEP(*(.ARM.attributes)) + } > FLASH :text + + /** + * Non-secure stack symbols. + */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); /* 0x20080000 */ + __StackLimit = __StackTop - __STACK_SIZE; + __stack = __StackTop; + + .stack (NOLOAD) : { . = ALIGN(8); } > RAM + + PROVIDE(__Vectors = ADDR(.vectors)); +} diff --git a/RA-0x0001-GPIO-Output/main.s b/RA-0x0001-GPIO-Output/main.s index 7cc3ec7..04748a1 100644 --- a/RA-0x0001-GPIO-Output/main.s +++ b/RA-0x0001-GPIO-Output/main.s @@ -1,255 +1,338 @@ -/** - * FILE: main.s - * - * DESCRIPTION: - * RP2350 Bare-Metal GPIO16 Blink, Coprocessor Version. - * Minimal bare‑metal LED blink on the RP2350 using direct coprocessor - * (MCRR) instructions to manipulate GPIO control registers. This bypasses - * SDK abstractions and demonstrates register‑level control in assembler. - * - * AUTHOR: Kevin Thomas - * CREATION DATE: October 5, 2025 - * UPDATE DATE: October 5, 2025 - */ - -.syntax unified // use unified assembly syntax -.cpu cortex-m33 // target Cortex-M33 core -.thumb // use Thumb instruction set - -/** - * Memory addresses and constants. - */ -.equ IO_BANK0_BASE, 0x40028000 // base address of IO_BANK0 -.equ PADS_BANK0_BASE, 0x40038000 // base address of PADS_BANK0 -.equ SIO_BASE, 0xD0000000 // base address of SIO block -.equ GPIO16_CTRL, 0x84 // io[16].ctrl offset -.equ GPIO16_PAD, 0x44 // pads io[16] offset -.equ GPIO16_BIT, (1<<16) // bit mask for GPIO16 -.equ GPIO_OUT_SET, 0x18 // SIO->GPIO_OUT_SET offset -.equ GPIO_OUT_XOR, 0x28 // SIO->GPIO_OUT_XOR offset -.equ GPIO_OE_SET, 0x38 // SIO->GPIO_OE_SET offset -.equ STACK_TOP, 0x20082000 // top of non-secure SRAM -.equ STACK_LIMIT, 0x2007A000 // stack limit (32 KB below top) - -/** - * Initialize the .vectors section. The .vectors section contains vector - * table. - */ -.section .vectors, "ax" // vector table section -.align 2 // align to 4-byte boundary - -/** - * Vector table section. - */ -.global _vectors // export symbol -_vectors: - .word STACK_TOP // initial stack pointer - .word Reset_Handler + 1 // reset handler (Thumb bit set) - -/** - * @brief Reset handler for RP2350. - * - * @details Entry point after reset. Performs: - * - Stack initialization - * - Coprocessor enable - * - GPIO16 pad/function configuration - * - Branches to main() which contains the blink loop - * - * @param None - * @retval None - */ -.global Reset_Handler // export Reset_Handler -.type Reset_Handler, %function // mark as function -Reset_Handler: - BL Init_Stack // initialize MSP/PSP and limits - BL Enable_Coprocessor // enable CP0 in CPACR for MCRR - B main // branch to main loop -.size Reset_Handler, . - Reset_Handler - -/** - * @brief Initialize stack pointers. - * - * @details Sets Main and Process Stack Pointers (MSP/PSP) and their limits. - * - * @param None - * @retval None - */ -.type Init_Stack, %function -Init_Stack: - LDR R0, =STACK_TOP // load stack top - MSR PSP, R0 // set PSP - LDR R0, =STACK_LIMIT // load stack limit - MSR MSPLIM, R0 // set MSP limit - MSR PSPLIM, R0 // set PSP limit - LDR R0, =STACK_TOP // reload stack top - MSR MSP, R0 // set MSP - BX LR // return - -/** - * @brief Enable coprocessor access. - * - * @details Grants full access to coprocessor 0 (CP0) via CPACR. - * - * @param None - * @retval None - */ -.type Enable_Coprocessor , %function -Enable_Coprocessor: - LDR R0, =0xE000ED88 // CPACR address - LDR R1, [R0] // read CPACR - ORR R1, R1, #0x3 // set CP0 full access - STR R1, [R0] // write CPACR - DSB // data sync barrier - ISB // instruction sync barrier - BX LR // return - -/** - * Initialize the .text section. - * The .text section contains executable code. - */ -.section .text // code section -.align 2 // align to 4-byte boundary - -/** - * @brief Main application entry point. - * - * @details Implements the infinite blink loop: - * - Set GPIO16 high - * - Delay ~500 ms - * - Set GPIO16 low - * - Delay ~500 ms - * - Repeat forever - * - * @param None - * @retval None - */ -.global main // export main -.type main, %function // mark as function -main: -.Push_Registers: - PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack -.GPIO16_Config: - BL GPIO16_Config // configure pads and FUNCSEL for GPIO16 -.Loop: - BL GPIO16_Set // set GPIO16 high - BL Delay_500ms // ~500 ms delay - BL GPIO16_Clear // set GPIO16 low - BL Delay_500ms // ~500 ms delay - B .Loop // loop forever -.Pop_Registers: - POP {R4-R12, LR} // pop registers R4-R12, LR from the stack - BX LR // return to caller - -/** - * @brief Configure GPIO16 for SIO control. - * - * @details Sets pad control (IE, OD, ISO) and FUNCSEL = 5 (SIO). Enables OE. - * - * @param None - * @retval None - */ -.type GPIO16_Config, %function -GPIO16_Config: -.GPIO16_Config_Push_Registers: - PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack -.GPIO16_Config_Modify_Pad: - LDR R3, =PADS_BANK0_BASE + GPIO16_PAD // pad control address - LDR R2, [R3] // read pad config - BIC R2, R2, #0x80 // clear OD - ORR R2, R2, #0x40 // set IE - BIC R2, R2, #0x100 // clear ISO - STR R2, [R3] // write pad config -.GPIO16_Config_Modify_IO: - LDR R3, =IO_BANK0_BASE + GPIO16_CTRL // IO control address - LDR R2, [R3] // read IO config - BIC R2, R2, #0x1F // clear FUNCSEL - ORR R2, R2, #5 // set FUNCSEL=5 - STR R2, [R3] // write IO config -.GPIO16_Config_Enable_OE: - MOVS R4, #16 // GPIO number - MOVS R5, #1 // enable output - MCRR p0, #4, R4, R5, c4 // gpioc_bit_oe_put(16, 1) -.GPIO16_Config_Pop_Registers: - POP {R4-R12, LR} // pop registers R4-R12, LR from the stack - BX LR // return - -/** - * @brief Set GPIO16 high. - * - * @details Drives GPIO16 output = 1 via coprocessor MCRR. - * - * @param None - * @retval None - */ -.type GPIO16_Set, %function -GPIO16_Set: -.GPIO16_Set_Push_Registers: - PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack -.GPIO16_Set_Load_Operands: - MOVS R4, #16 // GPIO number - MOVS R5, #1 // logic high -.GPIO16_Set_Execute: - MCRR p0, #4, R4, R5, c0 // gpioc_bit_out_put(16, 1) -.GPIO16_Set_Pop_Registers: - POP {R4-R12, LR} // pop registers R4-R12, LR from the stack - BX LR // return to caller - -/** - * @brief Clear GPIO16 (set low). - * - * @details Drives GPIO16 output = 0 via coprocessor MCRR. - * - * @param None - * @retval None - */ -.type GPIO16_Clear, %function -GPIO16_Clear: -.GPIO16_Clear_Push_Registers: - PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack -.GPIO16_Clear_Load_Operands: - MOVS R4, #16 // GPIO number - MOVS R5, #0 // logic low -.GPIO16_Clear_Execute: - MCRR p0, #4, R4, R5, c0 // gpioc_bit_out_put(16, 0) -.GPIO16_Clear_Pop_Registers: - POP {R4-R12, LR} // pop registers R4-R12, LR from the stack - BX LR // return to caller - -/** - * @brief Busy‑wait Delay_500ms loop. - * - * @details Consumes ~2,000,000 cycles to approximate ~500 ms at boot clock. - * - * @param None - * @retval None - */ -.type Delay_500ms, %function -Delay_500ms: -.Delay_500ms_Push_Registers: - PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack -.Delay_500ms_Setup: - LDR R2, =2000000 // loop count (~500 ms) -.Delay_500ms_Loop: - SUBS R2, R2, #1 // decrement counter - BNE .Delay_500ms_Loop // branch until zero -.Delay_500ms_Pop_Registers: - POP {R4-R12, LR} // pop registers R4-R12, LR from the stack - BX LR // return to caller - -/** - * Test data and constants. - * The .rodata section is used for constants and static data. - */ -.section .rodata // read-only data section - -/** - * Initialized global data. - * The .data section is used for initialized global or static variables. - */ -.section .data // data section - -/** - * Uninitialized global data. - * The .bss section is used for uninitialized global or static variables. - */ -.section .bss // BSS section +/** + * FILE: main.s + * + * DESCRIPTION: + * RP2350 Bare-Metal GPIO16 Blink, Coprocessor Version. + * + * BRIEF: + * Minimal bare‑metal LED blink on the RP2350 using the direct coprocessor + * (MCRR) instructions to manipulate GPIO control registers. This bypasses + * SDK abstractions and demonstrates register‑level control in assembler. + * Clocks the external crystal oscillator (XOSC) at 14.5MHz. + * + * AUTHOR: Kevin Thomas + * CREATION DATE: October 24, 2025 + * UPDATE DATE: October 25, 2025 + */ + +.syntax unified // use unified assembly syntax +.cpu cortex-m33 // target Cortex-M33 core +.thumb // use Thumb instruction set + +/** + * Memory addresses and constants. + */ +.equ STACK_TOP, 0x20082000 // top of non-secure SRAM +.equ STACK_LIMIT, 0x2007A000 // stack limit (32 KB below top) +.equ XOSC_BASE, 0x40048000 // base address of XOSC +.equ XOSC_CTRL, XOSC_BASE + 0x00 // XOSC->CTRL +.equ XOSC_STATUS, XOSC_BASE + 0x04 // XOSC->STATUS +.equ XOSC_STARTUP, XOSC_BASE + 0x0C // XOSC->STARTUP +.equ PPB_BASE, 0xE0000000 // base address of PPB +.equ CPACR, PPB_BASE + 0x0ED88 // PPB_BASE->CPACR +.equ CLOCKS_BASE, 0x40010000 // base address of CLOCKS +.equ CLK_PERI_CTRL, CLOCKS_BASE + 0x48 // CLOCKS->CLK_PERI_CTRL +.equ RESETS_BASE, 0x40020000 // base address of RESETS +.equ RESETS_RESET, RESETS_BASE + 0x0 // RESETS->RESET +.equ RESETS_RESET_CLEAR, RESETS_BASE + 0x3000 // RESETS->RESET_CLEAR +.equ RESETS_RESET_DONE, RESETS_BASE + 0x8 // RESETS->RESET_DONE +.equ IO_BANK0_BASE, 0x40028000 // base address of IO_BANK0 +.equ IO_BANK0_GPIO16_CTRL_OFFSET, 0x84 // IO_BANK0->GPIO16 offset +.equ PADS_BANK0_BASE, 0x40038000 // base address of PADS_BANK0 +.equ PADS_BANK0_GPIO16_OFFSET, 0x44 // PADS_BANK0->GPIO16 offset + +/** + * Initialize the .vectors section. The .vectors section contains vector + * table and Reset_Handler. + */ +.section .vectors, "ax" // vector table section +.align 2 // align to 4-byte boundary + +/** + * Vector table section. + */ +.global _vectors // export _vectors symbol +_vectors: + .word STACK_TOP // initial stack pointer + .word Reset_Handler + 1 // reset handler (Thumb bit set) + +/** + * @brief Reset handler for RP2350. + * + * @details Entry point after reset. Performs: + * - Stack initialization + * - Coprocessor enable + * - GPIO16 pad/function configuration + * - Branches to main() which contains the blink loop + * + * @param None + * @retval None + */ +.global Reset_Handler // export Reset_Handler symbol +.type Reset_Handler, %function +Reset_Handler: + BL Init_Stack // initialize MSP/PSP and limits + BL Init_XOSC // initialize external crystal oscillator + BL Enable_XOSC_Peri_Clock // enable XOSC peripheral clock + BL Init_Subsystem // initialize subsystems + BL Enable_Coprocessor // enable CP0 coprocessor + B main // branch to main loop +.size Reset_Handler, . - Reset_Handler + +/** + * @brief Initialize stack pointers. + * + * @details Sets Main and Process Stack Pointers (MSP/PSP) and their limits. + * + * @param None + * @retval None + */ +.type Init_Stack, %function +Init_Stack: + LDR R0, =STACK_TOP // load stack top + MSR PSP, R0 // set PSP + LDR R0, =STACK_LIMIT // load stack limit + MSR MSPLIM, R0 // set MSP limit + MSR PSPLIM, R0 // set PSP limit + LDR R0, =STACK_TOP // reload stack top + MSR MSP, R0 // set MSP + BX LR // return + +/** + * @brief Init XOSC and wait until it is ready. + * + * @details Configures and initializes the external crystal oscillator (XOSC). + * Waits for the XOSC to become stable before returning. + * + * @param None + * @retval None + */ +.type Init_XOSC, %function +Init_XOSC: + LDR R0, =XOSC_STARTUP // load XOSC_STARTUP address + LDR R1, =0x00C4 // set delay 50,000 cycles + STR R1, [R0] // store value into XOSC_STARTUP + LDR R0, =XOSC_CTRL // load XOSC_CTRL address + LDR R1, =0x00FABAA0 // set 1_15MHz, freq range, actual 14.5MHz + STR R1, [R0] // store value into XOSC_CTRL +.Init_XOSC_Wait: + LDR R0, =XOSC_STATUS // load XOSC_STATUS address + LDR R1, [R0] // read XOSC_STATUS value + TST R1, #(1<<31) // test STABLE bit + BEQ .Init_XOSC_Wait // wait until stable bit is set + BX LR // return + +/** + * @brief Enable XOSC peripheral clock. + * + * @details Sets the peripheral clock to use XOSC as its AUXSRC. + * + * @param None + * @retval None + */ +.type Enable_XOSC_Peri_Clock, %function +Enable_XOSC_Peri_Clock: + LDR R0, =CLK_PERI_CTRL // load CLK_PERI_CTRL address + LDR R1, [R0] // read CLK_PERI_CTRL value + ORR R1, R1, #(1<<11) // set ENABLE bit + ORR R1, R1, #(4<<5) // set AUXSRC: XOSC_CLKSRC bit + STR R1, [R0] // store value into CLK_PERI_CTRL + BX LR // return + +/** + * @brief Init subsystem. + * + * @details Initiates the various subsystems by clearing their reset bits. + * + * @param None + * @retval None + */ +.type Init_Subsystem, %function +Init_Subsystem: +.GPIO_Subsystem_Reset: + LDR R0, =RESETS_RESET // load RESETS->RESET address + LDR R1, [R0] // read RESETS->RESET value + BIC R1, R1, #(1<<6) // clear IO_BANK0 bit + STR R1, [R0] // store value into RESETS->RESET address +.GPIO_Subsystem_Reset_Wait: + LDR R0, =RESETS_RESET_DONE // load RESETS->RESET_DONE address + LDR R1, [R0] // read RESETS->RESET_DONE value + TST R1, #(1<<6) // test IO_BANK0 reset done + BEQ .GPIO_Subsystem_Reset_Wait // wait until done + BX LR // return + +/** + * @brief Enable coprocessor access. + * + * @details Grants full access to coprocessor 0 via CPACR. + * + * @param None + * @retval None + */ +.type Enable_Coprocessor , %function +Enable_Coprocessor: + LDR R0, =CPACR // load CPACR address + LDR R1, [R0] // read CPACR value + ORR R1, R1, #(1<<1) // set CP0: Controls access priv coproc 0 bit + ORR R1, R1, #(1<<0) // set CP0: Controls access priv coproc 0 bit + STR R1, [R0] // store value into CPACR + DSB // data sync barrier + ISB // instruction sync barrier + BX LR // return + +/** + * Initialize the .text section. + * The .text section contains executable code. + */ +.section .text // code section +.align 2 // align to 4-byte boundary + +/** + * @brief Main application entry point. + * + * @details Implements the infinite blink loop. + * + * @param None + * @retval None + */ +.global main // export main +.type main, %function // mark as function +main: +.Push_Registers: + PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack +.GPIO16_Config: + LDR R0, =PADS_BANK0_GPIO16_OFFSET // load PADS_BANK0_GPIO16_OFFSET + LDR R1, =IO_BANK0_GPIO16_CTRL_OFFSET // load IO_BANK0_GPIO16_CTRL_OFFSET + LDR R2, =16 // load GPIO number + BL GPIO_Config // call GPIO_Config +.Loop: + LDR R0, =16 // load GPIO number + BL GPIO_Set // call GPIO_Set + LDR R0, =500 // 500ms + BL Delay_MS // call Delay_MS + LDR R0, =16 // load GPIO number + BL GPIO_Clear // call GPIO_Clear + LDR R0, =500 // 500ms + BL Delay_MS // call Delay_MS + B .Loop // loop forever +.Pop_Registers: + POP {R4-R12, LR} // pop registers R4-R12, LR from the stack + BX LR // return to caller + +/** + * @brief Configure GPIO. + * + * @details Configures a GPIO pin's pad control and function select. + * + * @param R0 - PAD_OFFSET + * @param R1 - CTRL_OFFSET + * @param R2 - GPIO + * @retval None + */ +.type GPIO_Config, %function +GPIO_Config: +.GPIO_Config_Push_Registers: + PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack +.GPIO_Config_Modify_Pad: + LDR R4, =PADS_BANK0_BASE // load PADS_BANK0_BASE address + ADD R4, R4, R0 // PADS_BANK0_BASE + PAD_OFFSET + LDR R5, [R4] // read PAD_OFFSET value + BIC R5, R5, #(1<<7) // clear OD bit + ORR R5, R5, #(1<<6) // set IE bit + BIC R5, R5, #(1<<8) // clear ISO bit + STR R5, [R4] // store value into PAD_OFFSET +.GPIO_Config_Modify_CTRL: + LDR R4, =IO_BANK0_BASE // load IO_BANK0 base + ADD R4, R4, R1 // IO_BANK0_BASE + CTRL_OFFSET + LDR R5, [R4] // read CTRL_OFFSET value + BIC R5, R5, #0x1F // clear FUNCSEL + ORR R5, R5, #0x05 // set FUNCSEL 0x05->SIO_0 + STR R5, [R4] // store value into CTRL_OFFSET +.GPIO_Config_Enable_OE: + LDR R4, =1 // enable output + MCRR P0, #4, R2, R4, C4 // gpioc_bit_oe_put(GPIO, 1) +.GPIO_Config_Pop_Registers: + POP {R4-R12, LR} // pop registers R4-R12, LR from the stack + BX LR // return + +/** + * @brief GPIO set. + * + * @details Drives GPIO output high via coprocessor. + * + * @param R0 - GPIO + * @retval None + */ +.type GPIO_Set, %function +GPIO_Set: +.GPIO_Set_Push_Registers: + PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack +.GPIO_Set_Execute: + LDR R4, =1 // enable output + MCRR P0, #4, R0, R4, C0 // gpioc_bit_out_put(GPIO, 1) +.GPIO_Set_Pop_Registers: + POP {R4-R12, LR} // pop registers R4-R12, LR from the stack + BX LR // return + +/** + * @brief GPIO clear. + * + * @details Drives GPIO output high via coprocessor. + * + * @param R0 - GPIO + * @retval None + */ +.type GPIO_Clear, %function +GPIO_Clear: +.GPIO_Clear_Push_Registers: + PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack +.GPIO_Clear_Execute: + LDR R4, =0 // disable output + MCRR P0, #4, R0, R4, C0 // gpioc_bit_out_put(GPIO, 1) +.GPIO_Clear_Pop_Registers: + POP {R4-R12, LR} // pop registers R4-R12, LR from the stack + BX LR // return + +/** + * @brief Delay_MS. + * + * @details Delays for R0 milliseconds. Conversion: loop_count = ms * 3600 + * based on a 14.5MHz clock. + * + * @param R0 - milliseconds + * @retval None + */ +.type Delay_MS, %function +Delay_MS: +.Delay_MS_Push_Registers: + PUSH {R4-R12, LR} // push registers R4-R12, LR to the stack +.Delay_MS_Check: + CMP R0, #0 // if MS is not valid, return + BLE .Delay_MS_Done // branch if less or equal to 0 +.Delay_MS_Setup: + LDR R4, =3600 // loops per MS based on 14.5MHz clock + MUL R5, R0, R4 // MS * 3600 +.Delay_MS_Loop: + SUBS R5, R5, #1 // decrement counter + BNE .Delay_MS_Loop // branch until zero +.Delay_MS_Done: + POP {R4-R12, LR} // pop registers R4-R12, LR from the stack + BX LR // return + +/** + * Test data and constants. + * The .rodata section is used for constants and static data. + */ +.section .rodata // read-only data section + +/** + * Initialized global data. + * The .data section is used for initialized global or static variables. + */ +.section .data // data section + +/** + * Uninitialized global data. + * The .bss section is used for uninitialized global or static variables. + */ +.section .bss // BSS section