Add files via upload

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