diff --git a/src/host/hardware_divider/include/hardware/divider.h b/src/host/hardware_divider/include/hardware/divider.h index c1266885..0a6eccc0 100644 --- a/src/host/hardware_divider/include/hardware/divider.h +++ b/src/host/hardware_divider/include/hardware/divider.h @@ -7,7 +7,11 @@ #ifndef _HARDWARE_DIVIDER_H #define _HARDWARE_DIVIDER_H -#include "pico/types.h" +#include "pico.h" + +#ifdef __cplusplus +extern "C" { +#endif typedef uint64_t divmod_result_t; @@ -15,108 +19,313 @@ static inline int __sign_of(int32_t v) { return v > 0 ? 1 : (v < 0 ? -1 : 0); } -// divides unsigned values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0 -static inline uint64_t hw_divider_divmod_u32(uint32_t a, uint32_t b) { +/*! \brief Do an unsigned HW divide and wait for result + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return result as a pair of 32-bit quotient/remainder values. + * + * \param a The dividend + * \param b The divisor + * \return Results of divide as a pair of 32-bit quotient/remainder values. + */ +static inline divmod_result_t hw_divider_divmod_u32(uint32_t a, uint32_t b) { if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-1); // todo check this return (((uint64_t)(a%b))<<32u) | (a/b); } -// divides signed values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0 -static inline uint64_t hw_divider_divmod_s32(int32_t a, int32_t b) { +/*! \brief Do a signed HW divide and wait for result + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return result as a pair of 32-bit quotient/remainder values. + * + * \param a The dividend + * \param b The divisor + * \return Results of divide as a pair of 32-bit quotient/remainder values. + */ +static inline divmod_result_t hw_divider_divmod_s32(int32_t a, int32_t b) { if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-__sign_of(a)); return (((uint64_t)(a%b))<<32u) | (uint32_t)(a/b); } extern __thread divmod_result_t hw_divider_result_threadlocal; +/*! \brief Start a signed asynchronous divide + * \ingroup hardware_divider + * + * Start a divide of the specified signed parameters. You should wait for 8 cycles (__div_pause()) or wait for the ready bit to be set + * (hw_divider_wait_ready()) prior to reading the results. + * + * \param a The dividend + * \param b The divisor + */ static inline void hw_divider_divmod_s32_start(int32_t a, int32_t b) { hw_divider_result_threadlocal = hw_divider_divmod_s32(a, b); } +/*! \brief Start an unsigned asynchronous divide + * \ingroup hardware_divider + * + * Start a divide of the specified unsigned parameters. You should wait for 8 cycles (__div_pause()) or wait for the ready bit to be set + * (hw_divider_wait_ready()) prior to reading the results. + * + * \param a The dividend + * \param b The divisor + */ static inline void hw_divider_divmod_u32_start(uint32_t a, uint32_t b) { hw_divider_result_threadlocal = hw_divider_divmod_u32(a, b); } -static inline divmod_result_t hw_divider_result_wait() { +/*! \brief Return result of last asynchronous HW divide + * \ingroup hardware_divider + * + * This function waits for the result to be ready by calling hw_divider_wait_ready(). + * + * \return Current result. Most significant 32 bits are the remainder, lower 32 bits are the quotient. + */ +static inline divmod_result_t hw_divider_result_wait(void) { return hw_divider_result_threadlocal; } -static inline uint64_t hw_divider_result_nowait() { +/*! \brief Return result of HW divide, nowait + * \ingroup hardware_divider + * + * \note This is UNSAFE in that the calculation may not have been completed. + * + * \return Current result. Most significant 32 bits are the remainder, lower 32 bits are the quotient. + */ +static inline divmod_result_t hw_divider_result_nowait(void) { return hw_divider_result_threadlocal; } -inline static uint32_t to_quotient_u32(unsigned long long int r) { +/*! \brief Wait for a divide to complete + * \ingroup hardware_divider + * + * Wait for a divide to complete + */ +static inline void hw_divider_wait_ready(void) {} + + +/*! \brief Efficient extraction of unsigned quotient from 32p32 fixed point + * \ingroup hardware_divider + * + * \param r A pair of 32-bit quotient/remainder values. + * \return Unsigned quotient + */ +inline static uint32_t to_quotient_u32(divmod_result_t r) { return (uint32_t) r; } -inline static int32_t to_quotient_s32(unsigned long long int r) { +/*! \brief Efficient extraction of signed quotient from 32p32 fixed point + * \ingroup hardware_divider + * + * \param r A pair of 32-bit quotient/remainder values. + * \return Unsigned quotient + */ +inline static int32_t to_quotient_s32(divmod_result_t r) { return (int32_t)(uint32_t)r; } -inline static uint32_t to_remainder_u32(unsigned long long int r) { +/*! \brief Efficient extraction of unsigned remainder from 32p32 fixed point + * \ingroup hardware_divider + * + * \param r A pair of 32-bit quotient/remainder values. + * \return Unsigned remainder + * + * \note On Arm this is just a 32 bit register move or a nop + */ +inline static uint32_t to_remainder_u32(divmod_result_t r) { return (uint32_t)(r >> 32u); } -inline static int32_t to_remainder_s32(unsigned long long int r) { +/*! \brief Efficient extraction of signed remainder from 32p32 fixed point + * \ingroup hardware_divider + * + * \param r A pair of 32-bit quotient/remainder values. + * \return Signed remainder + * + * \note On arm this is just a 32 bit register move or a nop + */ +inline static int32_t to_remainder_s32(divmod_result_t r) { return (int32_t)(r >> 32u); } -static inline uint32_t hw_divider_u32_quotient_wait() { - return to_quotient_u32(hw_divider_result_wait()); -} - -static inline uint32_t hw_divider_u32_remainder_wait() { - return to_remainder_u32(hw_divider_result_wait()); -} - -static inline int32_t hw_divider_s32_quotient_wait() { - return to_quotient_s32(hw_divider_result_wait()); -} - -static inline int32_t hw_divider_s32_remainder_wait() { - return to_remainder_s32(hw_divider_result_wait()); -} +static inline void hw_divider_pause(void) {} +/*! \brief Do an unsigned HW divide, wait for result, return quotient + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return quotient. + * + * \param a The dividend + * \param b The divisor + * \return Quotient results of the divide + */ static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) { return b ? (a / b) : (uint32_t)(-1); } +/*! \brief Do an unsigned HW divide, wait for result, return remainder + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return remainder. + * + * \param a The dividend + * \param b The divisor + * \return Remainder results of the divide + */ static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) { return b ? (a % b) : a; } -static inline int32_t hw_divider_s32_quotient(int32_t a, int32_t b) { - return b ? (a / b) : -__sign_of(a); +/*! \brief Do a signed HW divide, wait for result, return quotient + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return quotient. + * + * \param a The dividend + * \param b The divisor + * \return Quotient results of the divide + */ +static inline int32_t hw_divider_quotient_s32(int32_t a, int32_t b) { + return to_quotient_s32(hw_divider_divmod_s32(a, b)); } -static inline int32_t hw_divider_s32_remainder(int32_t a, int32_t b) { +/*! \brief Do a signed HW divide, wait for result, return remainder + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return remainder. + * + * \param a The dividend + * \param b The divisor + * \return Remainder results of the divide + */ +static inline int32_t hw_divider_remainder_s32(int32_t a, int32_t b) { return b ? (a % b) : a; } +/*! \brief Return result of last asynchronous HW divide, unsigned quotient only + * \ingroup hardware_divider + * + * This function waits for the result to be ready by calling hw_divider_wait_ready(). + * + * \return Current unsigned quotient result. + */ +static inline uint32_t hw_divider_u32_quotient_wait(void) { + return to_quotient_u32(hw_divider_result_wait()); +} + +/*! \brief Return result of last asynchronous HW divide, signed quotient only + * \ingroup hardware_divider + * + * This function waits for the result to be ready by calling hw_divider_wait_ready(). + * + * \return Current signed quotient result. + */ +static inline int32_t hw_divider_s32_quotient_wait(void) { + return to_remainder_u32(hw_divider_result_wait()); +} + +/*! \brief Return result of last asynchronous HW divide, unsigned remainder only + * \ingroup hardware_divider + * + * This function waits for the result to be ready by calling hw_divider_wait_ready(). + * + * \return Current unsigned remainder result. + */ +static inline uint32_t hw_divider_u32_remainder_wait(void) { + return to_quotient_s32(hw_divider_result_wait()); +} + +/*! \brief Return result of last asynchronous HW divide, signed remainder only + * \ingroup hardware_divider + * + * This function waits for the result to be ready by calling hw_divider_wait_ready(). + * + * \return Current remainder results. + */ +static inline int32_t hw_divider_s32_remainder_wait(void) { + return to_remainder_s32(hw_divider_result_wait()); +} + +/*! \brief Do a hardware unsigned HW divide, wait for result, return quotient + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return quotient. + * + * \param a The dividend + * \param b The divisor + * \return Quotient result of the divide + */ static inline uint32_t hw_divider_u32_quotient_inlined(uint32_t a, uint32_t b) { return hw_divider_u32_quotient(a,b); } +/*! \brief Do a hardware unsigned HW divide, wait for result, return remainder + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return remainder. + * + * \param a The dividend + * \param b The divisor + * \return Remainder result of the divide + */ static inline uint32_t hw_divider_u32_remainder_inlined(uint32_t a, uint32_t b) { return hw_divider_u32_remainder(a,b); } +/*! \brief Do a hardware signed HW divide, wait for result, return quotient + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return quotient. + * + * \param a The dividend + * \param b The divisor + * \return Quotient result of the divide + */ static inline int32_t hw_divider_s32_quotient_inlined(int32_t a, int32_t b) { - return hw_divider_s32_quotient(a,b); + return hw_divider_quotient_s32(a,b); } +/*! \brief Do a hardware signed HW divide, wait for result, return remainder + * \ingroup hardware_divider + * + * Divide \p a by \p b, wait for calculation to complete, return remainder. + * + * \param a The dividend + * \param b The divisor + * \return Remainder result of the divide + */ static inline int32_t hw_divider_s32_remainder_inlined(int32_t a, int32_t b) { - return hw_divider_s32_remainder(a,b); + return hw_divider_remainder_s32(a,b); } typedef uint64_t hw_divider_state_t; -static inline void hw_divider_save_state(hw_divider_state_t *dest) { +/*! \brief Save the calling cores hardware divider state + * \ingroup hardware_divider + * + * Copy the current core's hardware divider state into the provided structure. This method + * waits for the divider results to be stable, then copies them to memory. + * They can be restored via hw_divider_restore_state() + * + * \param dest the location to store the divider state + */ + static inline void hw_divider_save_state(hw_divider_state_t *dest) { *dest = hw_divider_result_threadlocal; } -static inline void hw_divider_restore_state(hw_divider_state_t *src) { +/*! \brief Load a saved hardware divider state into the current core's hardware divider + * \ingroup hardware_divider + * + * Copy the passed hardware divider state into the hardware divider. + * + * \param src the location to load the divider state from + */ + static inline void hw_divider_restore_state(hw_divider_state_t *src) { hw_divider_result_threadlocal = *src; } +#ifdef __cplusplus +} +#endif #endif // _HARDWARE_DIVIDER_H diff --git a/src/host/pico_divider/divider.c b/src/host/pico_divider/divider.c index df0e2751..25ede84b 100644 --- a/src/host/pico_divider/divider.c +++ b/src/host/pico_divider/divider.c @@ -8,7 +8,7 @@ // These functions save/restore divider state, so are safe to call from interrupts int32_t div_s32s32(int32_t a, int32_t b) { - return hw_divider_s32_quotient(a, b); + return hw_divider_quotient_s32(a, b); } divmod_result_t divmod_s32s32(int32_t a, int32_t b) { diff --git a/src/rp2_common/boot_stage2/boot2_at25sf128a.S b/src/rp2_common/boot_stage2/boot2_at25sf128a.S index be232ff1..f013ea99 100644 --- a/src/rp2_common/boot_stage2/boot2_at25sf128a.S +++ b/src/rp2_common/boot_stage2/boot2_at25sf128a.S @@ -86,9 +86,7 @@ // Start of 2nd Stage Boot Code // ---------------------------------------------------------------------------- -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup .section .text @@ -97,10 +95,7 @@ // Otherwise it will be a return address -- second stage being called as a // function by user code, after copying out of XIP region. r3 holds SSI base, // r0...2 used as temporaries. Other GPRs not used. -.global _stage2_boot -.type _stage2_boot,%function -.thumb_func -_stage2_boot: +regular_func _stage2_boot push {lr} // Set pad configuration: diff --git a/src/rp2_common/boot_stage2/boot2_generic_03h.S b/src/rp2_common/boot_stage2/boot2_generic_03h.S index a10e66ab..3c8715f0 100644 --- a/src/rp2_common/boot_stage2/boot2_generic_03h.S +++ b/src/rp2_common/boot_stage2/boot2_generic_03h.S @@ -20,6 +20,8 @@ #include "hardware/regs/addressmap.h" #include "hardware/regs/ssi.h" +pico_default_asm_setup + // ---------------------------------------------------------------------------- // Config section // ---------------------------------------------------------------------------- @@ -53,25 +55,19 @@ // Start of 2nd Stage Boot Code // ---------------------------------------------------------------------------- -.cpu cortex-m0 -.thumb - .section .text -.global _stage2_boot -.type _stage2_boot,%function -.thumb_func -_stage2_boot: +regular_func _stage2_boot push {lr} ldr r3, =XIP_SSI_BASE // Use as base address where possible // Disable SSI to allow further config - mov r1, #0 + movs r1, #0 str r1, [r3, #SSI_SSIENR_OFFSET] // Set baud rate - mov r1, #PICO_FLASH_SPI_CLKDIV + movs r1, #PICO_FLASH_SPI_CLKDIV str r1, [r3, #SSI_BAUDR_OFFSET] ldr r1, =(CTRLR0_XIP) @@ -82,11 +78,11 @@ _stage2_boot: str r1, [r0] // NDF=0 (single 32b read) - mov r1, #0x0 + movs r1, #0x0 str r1, [r3, #SSI_CTRLR1_OFFSET] // Re-enable SSI - mov r1, #1 + movs r1, #1 str r1, [r3, #SSI_SSIENR_OFFSET] // We are now in XIP mode. Any bus accesses to the XIP address window will be diff --git a/src/rp2_common/boot_stage2/boot2_is25lp080.S b/src/rp2_common/boot_stage2/boot2_is25lp080.S index 80bf9d11..e2c24d42 100644 --- a/src/rp2_common/boot_stage2/boot2_is25lp080.S +++ b/src/rp2_common/boot_stage2/boot2_is25lp080.S @@ -80,25 +80,20 @@ // Start of 2nd Stage Boot Code // ---------------------------------------------------------------------------- -.cpu cortex-m0 -.thumb +pico_default_asm_setup -.section .text - -.global _stage2_boot -.type _stage2_boot,%function -.thumb_func -_stage2_boot: +.section text +regular_func _stage2_boot push {lr} ldr r3, =XIP_SSI_BASE // Use as base address where possible // Disable SSI to allow further config - mov r1, #0 + movs r1, #0 str r1, [r3, #SSI_SSIENR_OFFSET] // Set baud rate - mov r1, #PICO_FLASH_SPI_CLKDIV + movs r1, #PICO_FLASH_SPI_CLKDIV str r1, [r3, #SSI_BAUDR_OFFSET] // On QSPI parts we usually need a 01h SR-write command to enable QSPI mode @@ -113,7 +108,7 @@ program_sregs: str r1, [r3, #SSI_CTRLR0_OFFSET] // Enable SSI and select slave 0 - mov r1, #1 + movs r1, #1 str r1, [r3, #SSI_SSIENR_OFFSET] // Check whether SR needs updating @@ -124,7 +119,7 @@ program_sregs: beq skip_sreg_programming // Send write enable command - mov r1, #CMD_WRITE_ENABLE + movs r1, #CMD_WRITE_ENABLE str r1, [r3, #SSI_DR0_OFFSET] // Poll for completion and discard RX @@ -132,9 +127,9 @@ program_sregs: ldr r1, [r3, #SSI_DR0_OFFSET] // Send status write command followed by data bytes - mov r1, #CMD_WRITE_STATUS + movs r1, #CMD_WRITE_STATUS str r1, [r3, #SSI_DR0_OFFSET] - mov r0, #0 + movs r0, #0 str r2, [r3, #SSI_DR0_OFFSET] bl wait_ssi_ready @@ -145,7 +140,7 @@ program_sregs: 1: ldr r0, =CMD_READ_STATUS bl read_flash_sreg - mov r1, #1 + movs r1, #1 tst r0, r1 bne 1b @@ -157,7 +152,7 @@ skip_sreg_programming: // bl wait_ssi_ready // Disable SSI again so that it can be reconfigured - mov r1, #0 + movs r1, #0 str r1, [r3, #SSI_SSIENR_OFFSET] #endif @@ -182,7 +177,7 @@ dummy_read: ldr r1, =(CTRLR0_ENTER_XIP) str r1, [r3, #SSI_CTRLR0_OFFSET] - mov r1, #0x0 // NDF=0 (single 32b read) + movs r1, #0x0 // NDF=0 (single 32b read) str r1, [r3, #SSI_CTRLR1_OFFSET] #define SPI_CTRLR0_ENTER_XIP \ @@ -197,12 +192,12 @@ dummy_read: ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register str r1, [r0] - mov r1, #1 // Re-enable SSI + movs r1, #1 // Re-enable SSI str r1, [r3, #SSI_SSIENR_OFFSET] - mov r1, #CMD_READ + movs r1, #CMD_READ str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO - mov r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 + movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010 str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction // Poll for completion @@ -218,7 +213,7 @@ dummy_read: // to APM mode and generate a 28-bit address phase with the extra nibble set // to 4'b0000). - mov r1, #0 + movs r1, #0 str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config // Note that the INST_L field is used to select what XIP data gets pushed into @@ -240,7 +235,7 @@ configure_ssi: ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) str r1, [r0] - mov r1, #1 + movs r1, #1 str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI // We are now in XIP mode, with all transactions using Dual I/O and only diff --git a/src/rp2_common/boot_stage2/boot2_usb_blinky.S b/src/rp2_common/boot_stage2/boot2_usb_blinky.S index 74c47a3e..0249a455 100644 --- a/src/rp2_common/boot_stage2/boot2_usb_blinky.S +++ b/src/rp2_common/boot_stage2/boot2_usb_blinky.S @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "pico/asm_helper.S" + // Stub second stage which calls into USB bootcode, with parameters. // USB boot takes two parameters: // - A GPIO mask for activity LED -- if mask is 0, don't touch GPIOs at all @@ -19,17 +21,12 @@ #define ACTIVITY_LED 0 #define BOOT_MODE USB_BOOT_MSD_AND_PICOBOOT -.cpu cortex-m0 -.thumb +pico_default_asm_setup .section .text -.global _stage2_boot -.type _stage2_boot,%function - -.thumb_func -_stage2_boot: - mov r7, #0x14 // Pointer to _well_known pointer table in ROM +regular_func _stage2_boot + movs r7, #0x14 // Pointer to _well_known pointer table in ROM ldrh r0, [r7, #0] // Offset 0 is 16 bit pointer to function table ldrh r7, [r7, #4] // Offset 4 is 16 bit pointer to table lookup routine ldr r1, =('U' | ('B' << 8)) // Symbol for USB Boot @@ -39,7 +36,7 @@ _stage2_boot: mov r7, r0 ldr r0, =(1u << ACTIVITY_LED) // Mask of which GPIO (or GPIOs) to use - mov r1, #BOOT_MODE + movs r1, #BOOT_MODE blx r7 dead: diff --git a/src/rp2_common/boot_stage2/boot2_w25q080.S b/src/rp2_common/boot_stage2/boot2_w25q080.S index ad3238e2..7309f53b 100644 --- a/src/rp2_common/boot_stage2/boot2_w25q080.S +++ b/src/rp2_common/boot_stage2/boot2_w25q080.S @@ -86,9 +86,7 @@ // Start of 2nd Stage Boot Code // ---------------------------------------------------------------------------- -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup .section .text @@ -97,10 +95,7 @@ // Otherwise it will be a return address -- second stage being called as a // function by user code, after copying out of XIP region. r3 holds SSI base, // r0...2 used as temporaries. Other GPRs not used. -.global _stage2_boot -.type _stage2_boot,%function -.thumb_func -_stage2_boot: +regular_func _stage2_boot push {lr} // Set pad configuration: diff --git a/src/rp2_common/boot_stage2/boot2_w25x10cl.S b/src/rp2_common/boot_stage2/boot2_w25x10cl.S index 02628d4e..89d2cd10 100644 --- a/src/rp2_common/boot_stage2/boot2_w25x10cl.S +++ b/src/rp2_common/boot_stage2/boot2_w25x10cl.S @@ -40,6 +40,8 @@ #define PICO_FLASH_SPI_CLKDIV 4 #endif +pico_default_asm_setup + // ---------------------------------------------------------------------------- // The "System Control Block" is a set of internal Cortex-M0+ control registers // that are memory mapped and accessed like any other H/W register. They have @@ -69,31 +71,25 @@ // Start of 2nd Stage Boot Code // ---------------------------------------------------------------------------- -.cpu cortex-m0 -.thumb - .org 0 .section .text // This code will get copied to 0x20000000 and then executed -.global _stage2_boot -.type _stage2_boot,%function -.thumb_func -_stage2_boot: +regular_func _stage2_boot push {lr} ldr r3, =XIP_SSI_BASE // Use as base address where possible // We are primarily interested in setting up Flash for DSPI XIP w/ continuous read - mov r1, #0 + movs r1, #0 str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI to allow further config // The Boot ROM sets a very conservative SPI clock frequency to be sure it can // read the initial 256 bytes from any device. Here we can be more aggressive. - mov r1, #PICO_FLASH_SPI_CLKDIV + movs r1, #PICO_FLASH_SPI_CLKDIV str r1, [r3, #SSI_BAUDR_OFFSET] // Set SSI Clock // First we need to send the initial command to get us in to Fast Read Dual I/O @@ -116,7 +112,7 @@ _stage2_boot: ldr r1, =(CTRLR0_ENTER_XIP) str r1, [r3, #SSI_CTRLR0_OFFSET] - mov r1, #0x0 // NDF=0 (single 32b read) + movs r1, #0x0 // NDF=0 (single 32b read) str r1, [r3, #SSI_CTRLR1_OFFSET] #define SPI_CTRLR0_ENTER_XIP \ @@ -131,18 +127,18 @@ _stage2_boot: ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register str r1, [r0] - mov r1, #1 // Re-enable SSI + movs r1, #1 // Re-enable SSI str r1, [r3, #SSI_SSIENR_OFFSET] - mov r1, #W25X10CL_CMD_READ_DATA_FAST_DUAL_IO // 8b command = 0xBB + movs r1, #W25X10CL_CMD_READ_DATA_FAST_DUAL_IO // 8b command = 0xBB str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO - mov r1, #0x0000002 // 28-bit Address for dummy read = 0x000000 + 0x2 Mode bits to set M[5:4]=10 + movs r1, #0x0000002 // 28-bit Address for dummy read = 0x000000 + 0x2 Mode bits to set M[5:4]=10 str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction // Now we wait for the read transaction to complete by monitoring the SSI // status register and checking for the "RX FIFO Not Empty" flag to assert. - mov r1, #SSI_SR_RFNE_BITS + movs r1, #SSI_SR_RFNE_BITS 00: ldr r0, [r3, #SSI_SR_OFFSET] // Read status register tst r0, r1 // RFNE status flag set? @@ -158,7 +154,7 @@ _stage2_boot: // to APM mode and generate a 28-bit address phase with the extra nibble set // to 4'b0000). - mov r1, #0 + movs r1, #0 str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config // Note that the INST_L field is used to select what XIP data gets pushed into @@ -180,7 +176,7 @@ _stage2_boot: ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) str r1, [r0] - mov r1, #1 + movs r1, #1 str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI // We are now in XIP mode, with all transactions using Dual I/O and only diff --git a/src/rp2_common/hardware_clocks/clocks.c b/src/rp2_common/hardware_clocks/clocks.c index 75078931..152a9641 100644 --- a/src/rp2_common/hardware_clocks/clocks.c +++ b/src/rp2_common/hardware_clocks/clocks.c @@ -48,7 +48,7 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc, return false; // Div register is 24.8 int.frac divider so multiply by 2^8 (left shift by 8) - div = (uint32_t) (((uint64_t) src_freq << 8) / freq); + div = (uint32_t) (((uint64_t) src_freq << CLOCKS_CLK_GPOUT0_DIV_INT_LSB) / freq); clock_hw_t *clock = &clocks_hw->clk[clk_index]; @@ -76,14 +76,9 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc, if (configured_freq[clk_index] > 0) { // Delay for 3 cycles of the target clock, for ENABLE propagation. // Note XOSC_COUNT is not helpful here because XOSC is not - // necessarily running, nor is timer... so, 3 cycles per loop: + // necessarily running, nor is timer...: uint delay_cyc = configured_freq[clk_sys] / configured_freq[clk_index] + 1; - unified_asm ( - "1: \n\t" - "subs %0, #1 \n\t" - "bne 1b" - : "+r" (delay_cyc) - ); + busy_wait_at_least_cycles(delay_cyc * 3); } } diff --git a/src/rp2_common/hardware_divider/divider.S b/src/rp2_common/hardware_divider/divider.S index 55134f2c..9d90e24a 100644 --- a/src/rp2_common/hardware_divider/divider.S +++ b/src/rp2_common/hardware_divider/divider.S @@ -2,9 +2,7 @@ #include "hardware/regs/addressmap.h" #include "hardware/regs/sio.h" -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup // tag::hw_div_s32[] regular_func_with_section hw_divider_divmod_s32 diff --git a/src/rp2_common/hardware_divider/include/hardware/divider.h b/src/rp2_common/hardware_divider/include/hardware/divider.h index c5b91dec..cab3e043 100644 --- a/src/rp2_common/hardware_divider/include/hardware/divider.h +++ b/src/rp2_common/hardware_divider/include/hardware/divider.h @@ -85,7 +85,7 @@ static inline void hw_divider_wait_ready(void) { // we use one less register and instruction than gcc which uses a TST instruction uint32_t tmp; // allow compiler to pick scratch register - unified_asm ( + pico_default_asm ( "hw_divider_result_loop_%=:" "ldr %0, [%1, %2]\n\t" "lsrs %0, %0, #1\n\t" @@ -177,29 +177,29 @@ static inline int32_t hw_divider_s32_remainder_wait(void) { /*! \brief Do a signed HW divide and wait for result * \ingroup hardware_divider * - * Divide \p a by \p b, wait for calculation to complete, return result as a fixed point 32p32 value. + * Divide \p a by \p b, wait for calculation to complete, return result as a pair of 32-bit quotient/remainder values. * * \param a The dividend * \param b The divisor - * \return Results of divide as a 32p32 fixed point value. + * \return Results of divide as a pair of 32-bit quotient/remainder values. */ divmod_result_t hw_divider_divmod_s32(int32_t a, int32_t b); /*! \brief Do an unsigned HW divide and wait for result * \ingroup hardware_divider * - * Divide \p a by \p b, wait for calculation to complete, return result as a fixed point 32p32 value. + * Divide \p a by \p b, wait for calculation to complete, return result as a pair of 32-bit quotient/remainder values. * * \param a The dividend * \param b The divisor - * \return Results of divide as a 32p32 fixed point value. + * \return Results of divide as a pair of 32-bit quotient/remainder values. */ divmod_result_t hw_divider_divmod_u32(uint32_t a, uint32_t b); /*! \brief Efficient extraction of unsigned quotient from 32p32 fixed point * \ingroup hardware_divider * - * \param r 32p32 fixed point value. + * \param r A pair of 32-bit quotient/remainder values. * \return Unsigned quotient */ inline static uint32_t to_quotient_u32(divmod_result_t r) { @@ -209,7 +209,7 @@ inline static uint32_t to_quotient_u32(divmod_result_t r) { /*! \brief Efficient extraction of signed quotient from 32p32 fixed point * \ingroup hardware_divider * - * \param r 32p32 fixed point value. + * \param r A pair of 32-bit quotient/remainder values. * \return Unsigned quotient */ inline static int32_t to_quotient_s32(divmod_result_t r) { @@ -219,7 +219,7 @@ inline static int32_t to_quotient_s32(divmod_result_t r) { /*! \brief Efficient extraction of unsigned remainder from 32p32 fixed point * \ingroup hardware_divider * - * \param r 32p32 fixed point value. + * \param r A pair of 32-bit quotient/remainder values. * \return Unsigned remainder * * \note On Arm this is just a 32 bit register move or a nop @@ -231,7 +231,7 @@ inline static uint32_t to_remainder_u32(divmod_result_t r) { /*! \brief Efficient extraction of signed remainder from 32p32 fixed point * \ingroup hardware_divider * - * \param r 32p32 fixed point value. + * \param r A pair of 32-bit quotient/remainder values. * \return Signed remainder * * \note On arm this is just a 32 bit register move or a nop @@ -296,7 +296,7 @@ static inline int32_t hw_divider_remainder_s32(int32_t a, int32_t b) { * \ingroup hardware_divider */ static inline void hw_divider_pause(void) { - unified_asm ( + pico_default_asm ( "b _1_%=\n" "_1_%=:\n" "b _2_%=\n" diff --git a/src/rp2_common/hardware_divider/include/hardware/divider_helper.S b/src/rp2_common/hardware_divider/include/hardware/divider_helper.S index e69fab59..ff4ed919 100644 --- a/src/rp2_common/hardware_divider/include/hardware/divider_helper.S +++ b/src/rp2_common/hardware_divider/include/hardware/divider_helper.S @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +// Note this file is always included by another, so does not do pico_default_asm_setup #include "hardware/regs/addressmap.h" #include "hardware/regs/sio.h" diff --git a/src/rp2_common/hardware_exception/exception.c b/src/rp2_common/hardware_exception/exception.c index dd89401f..8e141a69 100644 --- a/src/rp2_common/hardware_exception/exception.c +++ b/src/rp2_common/hardware_exception/exception.c @@ -5,7 +5,7 @@ */ #include "hardware/exception.h" -#include "hardware/regs/m0plus.h" +#include "hardware/platform_defs.h" #include "hardware/structs/scb.h" #include "hardware/sync.h" #include "pico/assert.h" diff --git a/src/rp2_common/hardware_exception/include/hardware/exception.h b/src/rp2_common/hardware_exception/include/hardware/exception.h index b8bddea2..63af843e 100644 --- a/src/rp2_common/hardware_exception/include/hardware/exception.h +++ b/src/rp2_common/hardware_exception/include/hardware/exception.h @@ -9,7 +9,6 @@ #include "pico.h" #include "hardware/address_mapped.h" -#include "hardware/regs/m0plus.h" /** \file exception.h * \defgroup hardware_exception hardware_exception diff --git a/src/rp2_common/hardware_gpio/gpio.c b/src/rp2_common/hardware_gpio/gpio.c index 6e4261fc..4945738d 100644 --- a/src/rp2_common/hardware_gpio/gpio.c +++ b/src/rp2_common/hardware_gpio/gpio.c @@ -244,8 +244,8 @@ void gpio_set_input_enabled(uint gpio, bool enabled) { } void gpio_init(uint gpio) { - sio_hw->gpio_oe_clr = 1ul << gpio; - sio_hw->gpio_clr = 1ul << gpio; + gpio_set_dir(gpio, GPIO_IN); + gpio_put(gpio, 0); gpio_set_function(gpio, GPIO_FUNC_SIO); } diff --git a/src/rp2_common/hardware_irq/irq.c b/src/rp2_common/hardware_irq/irq.c index 3e66c189..1fbc3cc8 100644 --- a/src/rp2_common/hardware_irq/irq.c +++ b/src/rp2_common/hardware_irq/irq.c @@ -186,7 +186,7 @@ static inline int8_t slot_diff(struct irq_handler_chain_slot *to, struct irq_han int32_t result = 0xaaaa; // return (to - from); // note this implementation has limited range, but is fine for plenty more than -128->127 result - unified_asm ( + pico_default_asm ( "subs %1, %2\n" "adcs %1, %1\n" // * 2 (and + 1 if negative for rounding) "muls %0, %1\n" diff --git a/src/rp2_common/hardware_irq/irq_handler_chain.S b/src/rp2_common/hardware_irq/irq_handler_chain.S index bb65fb16..cd15ce77 100644 --- a/src/rp2_common/hardware_irq/irq_handler_chain.S +++ b/src/rp2_common/hardware_irq/irq_handler_chain.S @@ -6,11 +6,11 @@ #include "pico.h" #include "hardware/irq.h" +#include "pico/asm_helper.S" + +pico_default_asm_setup #if !PICO_DISABLE_SHARED_IRQ_HANDLERS -.syntax unified -.cpu cortex-m0plus -.thumb .data .align 2 diff --git a/src/rp2_common/hardware_sync/include/hardware/sync.h b/src/rp2_common/hardware_sync/include/hardware/sync.h index c5715421..2acf5a90 100644 --- a/src/rp2_common/hardware_sync/include/hardware/sync.h +++ b/src/rp2_common/hardware_sync/include/hardware/sync.h @@ -116,7 +116,7 @@ typedef volatile uint32_t spin_lock_t; */ #if !__has_builtin(__sev) __force_inline static void __sev(void) { - unified_asm ("sev"); + pico_default_asm ("sev"); } #endif @@ -128,7 +128,7 @@ __force_inline static void __sev(void) { */ #if !__has_builtin(__wfe) __force_inline static void __wfe(void) { - unified_asm ("wfe"); + pico_default_asm ("wfe"); } #endif @@ -139,7 +139,7 @@ __force_inline static void __wfe(void) { */ #if !__has_builtin(__wfi) __force_inline static void __wfi(void) { - unified_asm ("wfi"); + pico_default_asm ("wfi"); } #endif @@ -150,7 +150,7 @@ __force_inline static void __wfi(void) { * instruction will be observed before any explicit access after the instruction. */ __force_inline static void __dmb(void) { - unified_asm ("dmb" : : : "memory"); + pico_default_asm ("dmb" : : : "memory"); } /*! \brief Insert a DSB instruction in to the code path. @@ -161,7 +161,7 @@ __force_inline static void __dmb(void) { * accesses before this instruction complete. */ __force_inline static void __dsb(void) { - unified_asm ("dsb" : : : "memory"); + pico_default_asm ("dsb" : : : "memory"); } /*! \brief Insert a ISB instruction in to the code path. @@ -172,7 +172,7 @@ __force_inline static void __dsb(void) { * the ISB instruction has been completed. */ __force_inline static void __isb(void) { - unified_asm ("isb"); + pico_default_asm ("isb"); } /*! \brief Acquire a memory fence @@ -213,8 +213,8 @@ __force_inline static void __mem_fence_release(void) { */ __force_inline static uint32_t save_and_disable_interrupts(void) { uint32_t status; - unified_asm ("mrs %0, PRIMASK" : "=r" (status)::); - unified_asm ("cpsid i"); + pico_default_asm ("mrs %0, PRIMASK" : "=r" (status)::); + pico_default_asm ("cpsid i"); return status; } @@ -224,7 +224,7 @@ __force_inline static uint32_t save_and_disable_interrupts(void) { * \param status Previous interrupt status from save_and_disable_interrupts() */ __force_inline static void restore_interrupts(uint32_t status) { - unified_asm ("msr PRIMASK,%0"::"r" (status) : ); + pico_default_asm ("msr PRIMASK,%0"::"r" (status) : ); } /*! \brief Get HW Spinlock instance from number diff --git a/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S b/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S index 7b83edb9..02837dcf 100644 --- a/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S +++ b/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S @@ -4,14 +4,10 @@ * SPDX-License-Identifier: BSD-3-Clause */ -.syntax unified -.cpu cortex-m0plus -.thumb - #include "pico/asm_helper.S" #include "pico/bootrom.h" -__pre_init __aeabi_bits_init, 00010 +pico_default_asm_setup .macro bits_section name #if PICO_BITS_IN_RAM @@ -21,6 +17,8 @@ __pre_init __aeabi_bits_init, 00010 #endif .endm +__pre_init __aeabi_bits_init, 00010 + .section .data.aeabi_bits_funcs .global aeabi_bits_funcs, aeabi_bits_funcs_end .equ BITS_FUNC_COUNT, 4 diff --git a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c index 6976d479..16993301 100644 --- a/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c +++ b/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c @@ -63,7 +63,7 @@ static uint32_t counter = 0; //#define SWAP32(A) ((((A) & 0xff000000U) >> 8) | (((A) & 0xff0000U) << 8) | (((A) & 0xff00U) >> 8) | (((A) & 0xffU) << 8)) __force_inline static uint32_t __swap16x2(uint32_t a) { - unified_asm ("rev16 %0, %0" : "+l" (a) : : ); + pico_default_asm ("rev16 %0, %0" : "+l" (a) : : ); return a; } #define SWAP32(a) __swap16x2(a) diff --git a/src/rp2_common/pico_divider/divider.S b/src/rp2_common/pico_divider/divider.S index c095f350..493e39dd 100644 --- a/src/rp2_common/pico_divider/divider.S +++ b/src/rp2_common/pico_divider/divider.S @@ -4,17 +4,12 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "pico/asm_helper.S" #include "hardware/regs/addressmap.h" #include "hardware/divider_helper.S" -.syntax unified -.cpu cortex-m0plus -.thumb - // PICO_CONFIG: PICO_DIVIDER_DISABLE_INTERRUPTS, Disable interrupts around division such that divider state need not be saved/restored in exception handlers, default=0, group=pico_divider -#include "pico/asm_helper.S" - // PICO_CONFIG: PICO_DIVIDER_CALL_IDIV0, Whether 32 bit division by zero should call __aeabi_idiv0, default=1, group=pico_divider #ifndef PICO_DIVIDER_CALL_IDIV0 #define PICO_DIVIDER_CALL_IDIV0 1 @@ -25,6 +20,8 @@ #define PICO_DIVIDER_CALL_LDIV0 1 #endif +pico_default_asm_setup + // PICO_CONFIG: PICO_DIVIDER_IN_RAM, Whether divider functions should be placed in RAM, default=0, group=pico_divider .macro div_section name #if PICO_DIVIDER_IN_RAM @@ -37,11 +34,11 @@ @ wait 8-n cycles for the hardware divider .macro wait_div n .rept (8-\n) / 2 - b 9f + b 9f 9: .endr .if (8-\n) % 2 - nop + nop .endif .endm diff --git a/src/rp2_common/pico_double/double_aeabi.S b/src/rp2_common/pico_double/double_aeabi.S index 04cf22c6..425385e1 100644 --- a/src/rp2_common/pico_double/double_aeabi.S +++ b/src/rp2_common/pico_double/double_aeabi.S @@ -8,11 +8,9 @@ #include "pico/bootrom/sf_table.h" #include "hardware/divider_helper.S" -__pre_init __aeabi_double_init, 00020 +pico_default_asm_setup -.syntax unified -.cpu cortex-m0plus -.thumb +__pre_init __aeabi_double_init, 00020 .macro double_section name #if PICO_DOUBLE_IN_RAM diff --git a/src/rp2_common/pico_double/double_none.S b/src/rp2_common/pico_double/double_none.S index feded31c..89fb1177 100644 --- a/src/rp2_common/pico_double/double_none.S +++ b/src/rp2_common/pico_double/double_none.S @@ -7,9 +7,7 @@ #include "pico/asm_helper.S" #include "pico/bootrom/sf_table.h" -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup wrapper_func __aeabi_dadd wrapper_func __aeabi_ddiv diff --git a/src/rp2_common/pico_double/double_v1_rom_shim.S b/src/rp2_common/pico_double/double_v1_rom_shim.S index 6dac28ab..2e65170f 100644 --- a/src/rp2_common/pico_double/double_v1_rom_shim.S +++ b/src/rp2_common/pico_double/double_v1_rom_shim.S @@ -17,9 +17,7 @@ #include "pico/asm_helper.S" -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup .macro double_section name // todo separate flag for shims? diff --git a/src/rp2_common/pico_float/float_aeabi.S b/src/rp2_common/pico_float/float_aeabi.S index b3b6c04f..e2862b5c 100644 --- a/src/rp2_common/pico_float/float_aeabi.S +++ b/src/rp2_common/pico_float/float_aeabi.S @@ -10,9 +10,7 @@ __pre_init __aeabi_float_init, 00020 -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup .macro float_section name #if PICO_FLOAT_IN_RAM diff --git a/src/rp2_common/pico_float/float_none.S b/src/rp2_common/pico_float/float_none.S index db8e1268..5b1916a7 100644 --- a/src/rp2_common/pico_float/float_none.S +++ b/src/rp2_common/pico_float/float_none.S @@ -7,9 +7,7 @@ #include "pico/asm_helper.S" #include "pico/bootrom/sf_table.h" -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup wrapper_func __aeabi_fadd wrapper_func __aeabi_fdiv diff --git a/src/rp2_common/pico_float/float_v1_rom_shim.S b/src/rp2_common/pico_float/float_v1_rom_shim.S index 50df612f..665a6103 100644 --- a/src/rp2_common/pico_float/float_v1_rom_shim.S +++ b/src/rp2_common/pico_float/float_v1_rom_shim.S @@ -7,14 +7,13 @@ #include "pico/asm_helper.S" #if PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED -.syntax unified -.cpu cortex-m0plus -.thumb #ifndef PICO_FLOAT_IN_RAM #define PICO_FLOAT_IN_RAM 0 #endif +pico_default_asm_setup + .macro float_section name // todo separate flag for shims? #if PICO_FLOAT_IN_RAM diff --git a/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S b/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S index 114a1aa8..a1ad7e21 100644 --- a/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S +++ b/src/rp2_common/pico_int64_ops/pico_int64_ops_aeabi.S @@ -4,12 +4,10 @@ * SPDX-License-Identifier: BSD-3-Clause */ -.syntax unified -.cpu cortex-m0plus -.thumb - #include "pico/asm_helper.S" +pico_default_asm_setup + .macro int64_section name #if PICO_INT64_OPS_IN_RAM .section RAM_SECTION_NAME(\name), "ax" diff --git a/src/rp2_common/pico_mem_ops/mem_ops_aeabi.S b/src/rp2_common/pico_mem_ops/mem_ops_aeabi.S index 85409053..cb9bc89f 100644 --- a/src/rp2_common/pico_mem_ops/mem_ops_aeabi.S +++ b/src/rp2_common/pico_mem_ops/mem_ops_aeabi.S @@ -4,13 +4,11 @@ * SPDX-License-Identifier: BSD-3-Clause */ -.syntax unified -.cpu cortex-m0plus -.thumb - #include "pico/asm_helper.S" #include "pico/bootrom.h" +pico_default_asm_setup + __pre_init __aeabi_mem_init, 00001 .macro mem_section name diff --git a/src/rp2_common/pico_multicore/multicore.c b/src/rp2_common/pico_multicore/multicore.c index 1622145e..04856efc 100644 --- a/src/rp2_common/pico_multicore/multicore.c +++ b/src/rp2_common/pico_multicore/multicore.c @@ -75,7 +75,7 @@ bool multicore_fifo_pop_timeout_us(uint64_t timeout_us, uint32_t *out) { static uint32_t __attribute__((section(".stack1"))) core1_stack[PICO_CORE1_STACK_SIZE / sizeof(uint32_t)]; static void __attribute__ ((naked)) core1_trampoline(void) { - unified_asm ("pop {r0, r1, pc}"); + pico_default_asm ("pop {r0, r1, pc}"); } int core1_wrapper(int (*entry)(void), void *stack_base) { diff --git a/src/rp2_common/pico_platform/include/pico/asm_helper.S b/src/rp2_common/pico_platform/include/pico/asm_helper.S index 3e01c665..23a92583 100644 --- a/src/rp2_common/pico_platform/include/pico/asm_helper.S +++ b/src/rp2_common/pico_platform/include/pico/asm_helper.S @@ -6,6 +6,15 @@ #include "pico.h" +# note we don't do this by default in this file for backwards comaptibility with user code +# that may include this file, but not use unified syntax. Note that this macro does equivalent +# setup to the pico_default_asm macro for inline assembly in C code. +.macro pico_default_asm_setup +.syntax unified +.cpu cortex-m0plus +.thumb +.endm + // do not put align in here as it is used mid function sometimes .macro regular_func x .global \x diff --git a/src/rp2_common/pico_platform/include/pico/platform.h b/src/rp2_common/pico_platform/include/pico/platform.h index 91606deb..fde69af7 100644 --- a/src/rp2_common/pico_platform/include/pico/platform.h +++ b/src/rp2_common/pico_platform/include/pico/platform.h @@ -335,13 +335,13 @@ extern "C" { #define MIN(a, b) ((b)>(a)?(a):(b)) #endif -#define unified_asm(...) __asm volatile (".syntax unified\n" __VA_ARGS__) +#define pico_default_asm(...) __asm volatile (".syntax unified\n" __VA_ARGS__) /*! \brief Execute a breakpoint instruction * \ingroup pico_platform */ static inline void __breakpoint(void) { - unified_asm ("bkpt #0"); + pico_default_asm ("bkpt #0"); } /*! \brief Ensure that the compiler does not move memory access across this method call @@ -357,7 +357,7 @@ static inline void __breakpoint(void) { * might - even above the memory store!) */ __force_inline static void __compiler_memory_barrier(void) { - unified_asm ("" : : : "memory"); + pico_default_asm ("" : : : "memory"); } /*! \brief Macro for converting memory addresses to 32 bit addresses suitable for DMA @@ -443,7 +443,7 @@ static __force_inline void tight_loop_contents(void) {} * \return a * b */ __force_inline static int32_t __mul_instruction(int32_t a, int32_t b) { - unified_asm ("muls %0, %1" : "+l" (a) : "l" (b) : ); + pico_default_asm ("muls %0, %1" : "+l" (a) : "l" (b) : ); return a; } @@ -477,19 +477,15 @@ __force_inline static int32_t __mul_instruction(int32_t a, int32_t b) { * * \return the exception number if the CPU is handling an exception, or 0 otherwise */ -static inline uint __get_current_exception(void) { +static __force_inline uint __get_current_exception(void) { uint exception; - unified_asm ("mrs %0, ipsr" : "=l" (exception)); + pico_default_asm ("mrs %0, ipsr" : "=l" (exception)); return exception; } #define WRAPPER_FUNC(x) __wrap_ ## x #define REAL_FUNC(x) __real_ ## x -#ifdef __cplusplus -} -#endif - /*! \brief Helper method to busy-wait for at least the given number of cycles * \ingroup pico_platform * @@ -505,7 +501,7 @@ static inline uint __get_current_exception(void) { * \param minimum_cycles the minimum number of system clock cycles to delay for */ static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) { - unified_asm ( + pico_default_asm ( "1: subs %0, #3\n" "bcs 1b\n" : "+r" (minimum_cycles) : : "memory" @@ -521,6 +517,10 @@ __force_inline static uint get_core_num(void) { return (*(uint32_t *) (SIO_BASE + SIO_CPUID_OFFSET)); } +#ifdef __cplusplus +} +#endif + #else // __ASSEMBLER__ #define WRAPPER_FUNC_NAME(x) __wrap_##x diff --git a/src/rp2_common/pico_printf/printf_none.S b/src/rp2_common/pico_printf/printf_none.S index adc00ee5..212c1c50 100644 --- a/src/rp2_common/pico_printf/printf_none.S +++ b/src/rp2_common/pico_printf/printf_none.S @@ -7,9 +7,7 @@ #include "pico/asm_helper.S" #include "pico/bootrom/sf_table.h" -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup wrapper_func sprintf wrapper_func snprintf diff --git a/src/rp2_common/pico_runtime/runtime.c b/src/rp2_common/pico_runtime/runtime.c index b7076172..144ace1b 100644 --- a/src/rp2_common/pico_runtime/runtime.c +++ b/src/rp2_common/pico_runtime/runtime.c @@ -151,7 +151,7 @@ void runtime_init(void) { #ifndef NDEBUG if (__get_current_exception()) { // crap; started in exception handler - unified_asm ("bkpt #0"); + __breakpoint(); } #endif @@ -286,7 +286,7 @@ extern void __attribute__((noreturn)) __printflike(1, 0) PICO_PANIC_FUNCTION(__u // Use a forwarding method here as it is a little simpler than renaming the symbol as it is used from assembler void __attribute__((naked, noreturn)) __printflike(1, 0) panic(__unused const char *fmt, ...) { // if you get an undefined reference here, you didn't define your PICO_PANIC_FUNCTION! - unified_asm ( + pico_default_asm ( "push {lr}\n" #if !PICO_PANIC_FUNCTION_EMPTY "bl " __XSTRING(PICO_PANIC_FUNCTION) "\n" diff --git a/src/rp2_common/pico_standard_link/crt0.S b/src/rp2_common/pico_standard_link/crt0.S index 43b069d0..1187a9ad 100644 --- a/src/rp2_common/pico_standard_link/crt0.S +++ b/src/rp2_common/pico_standard_link/crt0.S @@ -5,10 +5,11 @@ */ #include "pico.h" +#include "pico/asm_helper.S" + #include "hardware/regs/m0plus.h" #include "hardware/regs/addressmap.h" #include "hardware/regs/sio.h" -#include "pico/asm_helper.S" #include "pico/binary_info/defs.h" #ifdef NDEBUG @@ -17,9 +18,7 @@ #endif #endif -.syntax unified -.cpu cortex-m0plus -.thumb +pico_default_asm_setup .section .vectors, "ax" .align 2 diff --git a/src/rp2_common/pico_stdio_semihosting/stdio_semihosting.c b/src/rp2_common/pico_stdio_semihosting/stdio_semihosting.c index 291e9396..7a7910ff 100644 --- a/src/rp2_common/pico_stdio_semihosting/stdio_semihosting.c +++ b/src/rp2_common/pico_stdio_semihosting/stdio_semihosting.c @@ -25,7 +25,7 @@ static void stdio_semihosting_out_chars(const char *buf, int length) { args.buf = buf; args.len = length; - unified_asm ( + pico_default_asm ( // r1 must contain a pointer to the arguments "movs r1, %[args]\n" // semihosting call number 0x05 = SYS_WRITE diff --git a/src/rp2_common/pico_stdlib/CMakeLists.txt b/src/rp2_common/pico_stdlib/CMakeLists.txt index 98693458..183ca52b 100644 --- a/src/rp2_common/pico_stdlib/CMakeLists.txt +++ b/src/rp2_common/pico_stdlib/CMakeLists.txt @@ -1,9 +1,9 @@ # PICO_CMAKE_CONFIG: PICO_STDIO_UART, OPTION: Globally enable stdio UART, default=1, group=pico_stdlib -option(PICO_STDIO_UART "Globablly enable stdio UART" 1) +option(PICO_STDIO_UART "Globally enable stdio UART" 1) # PICO_CMAKE_CONFIG: PICO_STDIO_USB, OPTION: Globally enable stdio USB, default=0, group=pico_stdlib -option(PICO_STDIO_USB "Globablly enable stdio USB" 0) +option(PICO_STDIO_USB "Globally enable stdio USB" 0) # PICO_CMAKE_CONFIG: PICO_STDIO_SEMIHOSTING, OPTION: Globally enable stdio semihosting, default=0, group=pico_stdlib -option(PICO_STDIO_SEMIHOSTING "Globablly enable stdio semihosting" 0) +option(PICO_STDIO_SEMIHOSTING "Globally enable stdio semi-hosting" 0) if (NOT TARGET pico_stdlib) pico_add_impl_library(pico_stdlib) diff --git a/test/kitchen_sink/kitchen_sink.c b/test/kitchen_sink/kitchen_sink.c index ab6118f1..3297dd05 100644 --- a/test/kitchen_sink/kitchen_sink.c +++ b/test/kitchen_sink/kitchen_sink.c @@ -138,6 +138,6 @@ int main(void) { hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); hard_assert(recursive_mutex_try_enter(&recursive_mutex, NULL)); // this should compile as we are Cortex M0+ - unified_asm ("SVC #3"); + pico_default_asm ("SVC #3"); } diff --git a/test/pico_divider_test/pico_divider_test.c b/test/pico_divider_test/pico_divider_test.c index 97936f8d..6f0984ee 100644 --- a/test/pico_divider_test/pico_divider_test.c +++ b/test/pico_divider_test/pico_divider_test.c @@ -193,7 +193,7 @@ void test_random() { #endif uint32_t __attribute__((naked)) time_32(uint32_t a, uint32_t b, uint32_t (*func)(uint32_t a, uint32_t b)) { - unified_asm ( + pico_default_asm ( "push {r4, r5, lr}\n" "ldr r4, =0xe000e018\n" "ldr r5, [r4]\n" @@ -207,7 +207,7 @@ uint32_t __attribute__((naked)) time_32(uint32_t a, uint32_t b, uint32_t (*func) } uint32_t __attribute__((naked)) time_64(uint64_t a, uint64_t b, uint64_t (*func64)(uint64_t a, uint64_t b)) { - unified_asm ( + pico_default_asm ( "push {r4-r6, lr}\n" "ldr r6, [sp, #16]\n" "ldr r4, =0xe000e018\n" diff --git a/test/pico_float_test/llvm/call_apsr.S b/test/pico_float_test/llvm/call_apsr.S index 6c7d3616..d24ccab4 100644 --- a/test/pico_float_test/llvm/call_apsr.S +++ b/test/pico_float_test/llvm/call_apsr.S @@ -12,9 +12,9 @@ // //===- -.syntax unified -.cpu cortex-m0plus -.thumb +#include "pico/asm_helper.S" + +pico_default_asm_setup .align 2 diff --git a/test/pico_float_test/pico_float_test.c b/test/pico_float_test/pico_float_test.c index 6cb034c3..4d45a9ab 100644 --- a/test/pico_float_test/pico_float_test.c +++ b/test/pico_float_test/pico_float_test.c @@ -518,7 +518,7 @@ int main() { } for(float x = 4294967296.f * 4294967296.f * 2.f; x>=0.5f; x/=2.f) { printf("f2i64 %f->%lld\n", x, (int64_t)x); - if (x >= INT64_MAX) { + if ((double)x >= (double)INT64_MAX) { // seems like there is a bug in the gcc version! assert(__aeabi_f2lz(x) == INT64_MAX); } else {