Various small fixes towards building with other compilers (#1285)

* Fix various non-GCC warnings (no effect on GCC)
* Reduce use of typeof since non GCC compilers may not support it
* Introduce PICO_C_COMPILER_IS_GNU, PICO_C_COMPILER_IS_CLANG, PICO_C_COMPILER_IS_IAR to CMake as if (CMAKE_C_COMPILER_ID STREQUAL "xxx") is a bit verbose
* Use "unified_asm" macro for all inline asm (it is "volatile __asm" on GNU with a .syntex unified)
* Use NOLOAD instead of COPY in linker scripts (arguably more correct anyway)
* Use the same style for setting _etext in all 4 linker scripts (to the beginning of .data). Clang aligns .data on a 16 byte boundary. Note ideally we'd
  add a new symbol __data_source, however that would break backwards compatibility with existing user linker scripts
* Use "a" for .stack, .heap sections because clang complains otherwise, and they are explicitly NOLOAD anyway
* Avoid duplicating __sev, __wfe, __wfi which Clang sometimes seems to provide as built-ins
* Add missing kitchen_sink_blocked_ram binary
* Allow build with LLVM Embedded Toolchain Form ARM v 14.0.0 (unsupported atm)
This commit is contained in:
Graham Sanderson 2023-03-01 15:10:18 -06:00 committed by GitHub
parent bc7d9ce95a
commit 1ac90374e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 315 additions and 212 deletions

View File

@ -9,6 +9,13 @@ if (NOT TARGET _pico_sdk_inclusion_marker)
project(pico_sdk C CXX ASM)
string(REGEX MATCH "Clang" PICO_C_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
string(REGEX MATCH "GNU" PICO_C_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}")
string(REGEX MATCH "IAR" PICO_C_COMPILER_IS_IAR "${CMAKE_C_COMPILER_ID}")
pico_register_common_scope_var(PICO_C_COMPILER_IS_CLANG)
pico_register_common_scope_var(PICO_C_COMPILER_IS_GNU)
pico_register_common_scope_var(PICO_C_COMPILER_IS_IAR)
message("Build type is ${CMAKE_BUILD_TYPE}")
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
if (PICO_DEOPTIMIZED_DEBUG)

View File

@ -1,4 +1,5 @@
# NOTE: THIS IS A WIP ONLY PICO_ARM_GCC IS CURRENTLY SUPPORTED
# NOTE: THIS IS A WIP ONLY PICO_ARM_GCC IS CURRENTLY SUPPORTED, however should work with LLVM Embedded Toolchain for ARM
# version 14.0.0 https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/tag/release-14.0.0
# todo there is probably a more "cmake" way of doing this going thru the standard path with our "PICO" platform
# i.e. CMake<Lang>Information and whatnot
include(${CMAKE_CURRENT_LIST_DIR}/find_compiler.cmake)
@ -37,9 +38,10 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
include_directories(/usr/include/newlib)
option(PICO_DEOPTIMIZED_DEBUG "Build debug builds with -O0" 0)
set(ARM_TOOLCHAIN_COMMON_FLAGS " --target=arm-none-eabi -mcpu=cortex-m0plus -mthumb")
# Oz is preferred for Clang (verses CMake default -Os) see also https://gitlab.kitware.com/cmake/cmake/-/issues/22458
set(CMAKE_C_FLAGS_MINSIZEREL "-Oz -DNDEBUG")
set(ARM_TOOLCHAIN_COMMON_FLAGS "--target=armv6m-none-eabi -mfloat-abi=soft -march=armv6m --sysroot ${PICO_COMPILER_DIR}/../lib/clang-runtimes/armv6m_soft_nofp")
include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake)

View File

@ -16,12 +16,12 @@
#include "pico/binary_info/structure.h"
#if !PICO_NO_BINARY_INFO
#define __bi_decl(name, bi, section_prefix, attr) static const attr __attribute__((section(section_prefix __STRING(name)))) struct _binary_info_core *name = bi
#define __bi_decl(name, bi, section_prefix, attr) static const attr __attribute__((section(section_prefix __STRING(name)))) struct _binary_info_core *const name = bi
#define __bi_lineno_var_name __CONCAT(__bi_, __LINE__)
#define __bi_ptr_lineno_var_name __CONCAT(__bi_ptr, __LINE__)
#define __bi_enclosure_check_lineno_var_name __CONCAT(_error_bi_is_missing_enclosing_decl_,__LINE__)
#define __bi_mark_enclosure static const __unused int __bi_enclosure_check_lineno_var_name=0;
#if !defined(__GNUC__) || __cplusplus || __GNUC__ >= 8
#if __cplusplus || __GNUC__ >= 8
#define __bi_enclosure_check(x) (x + __bi_enclosure_check_lineno_var_name)
#else
// skip the version check on older GCC non C++, as it doesn't compile.. this is only here to catch the
@ -39,10 +39,10 @@
* binary information declared this way will also be stripped
* \ingroup pico_binary_info
*/
#define bi_decl_if_func_used(_decl) ({__bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(volatile uint8_t *)&__bi_ptr_lineno_var_name;});
#define bi_decl_if_func_used(_decl) ({__bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(const volatile uint8_t *)&__bi_ptr_lineno_var_name;});
#define bi_decl_with_attr(_decl, _attr) __bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.keep.", __used);
#define bi_decl_if_func_used_with_attr(_decl, _attr) ({__bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(volatile uint8_t *)&__bi_ptr_lineno_var_name;});
#define bi_decl_if_func_used_with_attr(_decl, _attr) ({__bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(const volatile uint8_t *)&__bi_ptr_lineno_var_name;});
#else
#define __bi_decl(bi, name, attr)
#define bi_decl_with_attr(_decl, _attr)

View File

@ -15,7 +15,12 @@ void sem_init(semaphore_t *sem, int16_t initial_permits, int16_t max_permits) {
}
int __time_critical_func(sem_available)(semaphore_t *sem) {
#ifdef __GNUC__
return *(volatile typeof(sem->permits) *) &sem->permits;
#else
static_assert(sizeof(sem->permits) == 2, "");
return *(volatile int16_t *) &sem->permits;
#endif
}
void __time_critical_func(sem_acquire_blocking)(semaphore_t *sem) {

View File

@ -22,7 +22,7 @@ typedef struct alarm_pool_entry {
void *user_data;
} alarm_pool_entry_t;
typedef struct alarm_pool {
struct alarm_pool {
pheap_t *heap;
spin_lock_t *lock;
alarm_pool_entry_t *entries;
@ -32,7 +32,7 @@ typedef struct alarm_pool {
alarm_id_t alarm_in_progress; // this is set during a callback from the IRQ handler... it can be cleared by alarm_cancel to prevent repeats
uint8_t hardware_alarm_num;
uint8_t core_num;
} alarm_pool_t;
};
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
// To avoid bringing in calloc, we statically allocate the arrays and the heap

View File

@ -59,7 +59,7 @@ void queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count,
* \param element_count Maximum number of entries in the queue
*/
static inline void queue_init(queue_t *q, uint element_size, uint element_count) {
return queue_init_with_spinlock(q, element_size, element_count, next_striped_spin_lock_num());
queue_init_with_spinlock(q, element_size, element_count, next_striped_spin_lock_num());
}
/*! \brief Destroy the specified queue.

View File

@ -40,9 +40,9 @@ function(pico_define_boot_stage2 NAME SOURCES)
)
# todo bit of an abstraction failure - revisit for Clang support anyway
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
if (PICO_C_COMPILER_IS_CLANG)
target_link_options(${NAME} PRIVATE "-nostdlib")
else ()
elseif (PICO_C_COMPILER_IS_GNU)
target_link_options(${NAME} PRIVATE "--specs=nosys.specs")
target_link_options(${NAME} PRIVATE "-nostartfiles")
endif ()

View File

@ -6,7 +6,7 @@
#include "hardware/claim.h"
uint32_t hw_claim_lock() {
uint32_t hw_claim_lock(void) {
return spin_lock_blocking(spin_lock_instance(PICO_SPINLOCK_ID_HARDWARE_CLAIM));
}

View File

@ -78,8 +78,7 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc,
// Note XOSC_COUNT is not helpful here because XOSC is not
// necessarily running, nor is timer... so, 3 cycles per loop:
uint delay_cyc = configured_freq[clk_sys] / configured_freq[clk_index] + 1;
asm volatile (
".syntax unified \n\t"
unified_asm (
"1: \n\t"
"subs %0, #1 \n\t"
"bne 1b"

View File

@ -85,10 +85,10 @@ 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
asm volatile (
unified_asm (
"hw_divider_result_loop_%=:"
"ldr %0, [%1, %2]\n\t"
"lsr %0, #1\n\t"
"lsrs %0, %0, #1\n\t"
"bcc hw_divider_result_loop_%=\n\t"
: "=&l" (tmp)
: "l" (sio_hw), "I" (SIO_DIV_CSR_OFFSET)
@ -105,7 +105,8 @@ static inline void hw_divider_wait_ready(void) {
*/
static inline divmod_result_t hw_divider_result_nowait(void) {
// as ugly as this looks it is actually quite efficient
divmod_result_t rc = (((divmod_result_t) sio_hw->div_remainder) << 32u) | sio_hw->div_quotient;
divmod_result_t rc = ((divmod_result_t) sio_hw->div_remainder) << 32u;
rc |= sio_hw->div_quotient;
return rc;
}
@ -295,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) {
asm volatile (
unified_asm (
"b _1_%=\n"
"_1_%=:\n"
"b _2_%=\n"

View File

@ -13,8 +13,8 @@ check_hw_size(dma_channel_hw_t, DMA_CHAN_STRIDE);
check_hw_layout(dma_hw_t, abort, DMA_CHAN_ABORT_OFFSET);
// sanity check
static_assert(__builtin_offsetof(dma_hw_t, ch[0].ctrl_trig) == DMA_CH0_CTRL_TRIG_OFFSET, "hw mismatch");
static_assert(__builtin_offsetof(dma_hw_t, ch[1].ctrl_trig) == DMA_CH1_CTRL_TRIG_OFFSET, "hw mismatch");
static_assert(offsetof(dma_hw_t, ch[0].ctrl_trig) == DMA_CH0_CTRL_TRIG_OFFSET, "hw mismatch");
static_assert(offsetof(dma_hw_t, ch[1].ctrl_trig) == DMA_CH1_CTRL_TRIG_OFFSET, "hw mismatch");
static_assert(NUM_DMA_CHANNELS <= 16, "");
static uint16_t _claimed;

View File

@ -41,7 +41,7 @@ static void __no_inline_not_in_flash_func(flash_init_boot2_copyout)(void) {
}
static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) {
((void (*)(void))boot2_copyout+1)();
((void (*)(void))((intptr_t)boot2_copyout+1))();
}
#else

View File

@ -27,9 +27,7 @@ static inline void i2c_unreset(i2c_inst_t *i2c) {
// Addresses of the form 000 0xxx or 111 1xxx are reserved. No slave should
// have these addresses.
static inline bool i2c_reserved_addr(uint8_t addr) {
return (addr & 0x78) == 0 || (addr & 0x78) == 0x78;
}
#define i2c_reserved_addr(addr) (((addr) & 0x78) == 0 || ((addr) & 0x78) == 0x78)
uint i2c_init(i2c_inst_t *i2c, uint baudrate) {
i2c_reset(i2c);

View File

@ -10,7 +10,7 @@
// These two config items are also used by assembler, so keeping separate
// PICO_CONFIG: PICO_MAX_SHARED_IRQ_HANDLERS, Maximum number of shared IRQ handlers, default=4, advanced=true, group=hardware_irq
#ifndef PICO_MAX_SHARED_IRQ_HANDLERS
#define PICO_MAX_SHARED_IRQ_HANDLERS 4u
#define PICO_MAX_SHARED_IRQ_HANDLERS 4
#endif
// PICO_CONFIG: PICO_DISABLE_SHARED_IRQ_HANDLERS, Disable shared IRQ handlers, type=bool, default=0, group=hardware_irq

View File

@ -186,11 +186,11 @@ 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
asm (".syntax unified\n"
unified_asm (
"subs %1, %2\n"
"adcs %1, %1\n" // * 2 (and + 1 if negative for rounding)
"muls %0, %1\n"
"lsrs %0, 20\n"
"lsrs %0, %0, #20\n"
: "+l" (result), "+l" (to)
: "l" (from)
:
@ -221,9 +221,9 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
// start new chain
hard_assert(vtable_handler == __unhandled_user_irq);
struct irq_handler_chain_slot slot_data = {
.inst1 = 0xa100, // add r1, pc, #0
.inst2 = make_branch(&slot->inst2, irq_handler_chain_first_slot), // b irq_handler_chain_first_slot
.inst3 = 0xbd01, // pop {r0, pc}
.inst1 = 0xa100, // add r1, pc, #0
.inst2 = make_branch(&slot->inst2, (void *) irq_handler_chain_first_slot), // b irq_handler_chain_first_slot
.inst3 = 0xbd01, // pop {r0, pc}
.link = -1,
.priority = order_priority,
.handler = handler
@ -233,7 +233,7 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
} else {
assert(!((((uintptr_t)vtable_handler) - ((uintptr_t)irq_handler_chain_slots) - 1)%sizeof(struct irq_handler_chain_slot)));
struct irq_handler_chain_slot *prev_slot = NULL;
struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit(vtable_handler);
struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit((void *) vtable_handler);
struct irq_handler_chain_slot *cur_slot = existing_vtable_slot;
while (cur_slot->priority > order_priority) {
prev_slot = cur_slot;
@ -259,9 +259,9 @@ void irq_add_shared_handler(uint num, irq_handler_t handler, uint8_t order_prior
} else {
// update with new chain head
struct irq_handler_chain_slot slot_data = {
.inst1 = 0xa100, // add r1, pc, #0
.inst2 = make_branch(&slot->inst2, irq_handler_chain_first_slot), // b irq_handler_chain_first_slot
.inst3 = make_branch(&slot->inst3, existing_vtable_slot), // b existing_slot
.inst1 = 0xa100, // add r1, pc, #0
.inst2 = make_branch(&slot->inst2, (void *) irq_handler_chain_first_slot), // b irq_handler_chain_first_slot
.inst3 = make_branch(&slot->inst3, existing_vtable_slot), // b existing_slot
.link = get_slot_index(existing_vtable_slot),
.priority = order_priority,
.handler = handler
@ -309,7 +309,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
hard_assert(!exception || exception == num + VTABLE_FIRST_IRQ);
struct irq_handler_chain_slot *prev_slot = NULL;
struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit(vtable_handler);
struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit((void *) vtable_handler);
struct irq_handler_chain_slot *to_free_slot = existing_vtable_slot;
while (to_free_slot->handler != handler) {
prev_slot = to_free_slot;
@ -354,7 +354,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
// it to bl to irq_handler_chain_remove_tail which will remove the slot.
// NOTE THAT THIS TRASHES PRIORITY AND LINK SINCE THIS IS A 4 BYTE INSTRUCTION
// BUT THEY ARE NOT NEEDED NOW
insert_branch_and_link(&to_free_slot->inst3, irq_handler_chain_remove_tail);
insert_branch_and_link(&to_free_slot->inst3, (void *) irq_handler_chain_remove_tail);
}
}
} else {

View File

@ -114,9 +114,11 @@ typedef volatile uint32_t spin_lock_t;
* The SEV (send event) instruction sends an event to both cores.
*/
#if !__has_builtin(__sev)
__force_inline static void __sev(void) {
__asm volatile ("sev");
unified_asm ("sev");
}
#endif
/*! \brief Insert a WFE instruction in to the code path.
* \ingroup hardware_sync
@ -124,18 +126,22 @@ __force_inline static void __sev(void) {
* The WFE (wait for event) instruction waits until one of a number of
* events occurs, including events signalled by the SEV instruction on either core.
*/
#if !__has_builtin(__wfe)
__force_inline static void __wfe(void) {
__asm volatile ("wfe");
unified_asm ("wfe");
}
#endif
/*! \brief Insert a WFI instruction in to the code path.
* \ingroup hardware_sync
*
* The WFI (wait for interrupt) instruction waits for a interrupt to wake up the core.
*/
#if !__has_builtin(__wfi)
__force_inline static void __wfi(void) {
__asm volatile ("wfi");
unified_asm ("wfi");
}
#endif
/*! \brief Insert a DMB instruction in to the code path.
* \ingroup hardware_sync
@ -144,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) {
__asm volatile ("dmb" : : : "memory");
unified_asm ("dmb" : : : "memory");
}
/*! \brief Insert a DSB instruction in to the code path.
@ -155,7 +161,7 @@ __force_inline static void __dmb(void) {
* accesses before this instruction complete.
*/
__force_inline static void __dsb(void) {
__asm volatile ("dsb" : : : "memory");
unified_asm ("dsb" : : : "memory");
}
/*! \brief Insert a ISB instruction in to the code path.
@ -166,7 +172,7 @@ __force_inline static void __dsb(void) {
* the ISB instruction has been completed.
*/
__force_inline static void __isb(void) {
__asm volatile ("isb");
unified_asm ("isb");
}
/*! \brief Acquire a memory fence
@ -207,8 +213,8 @@ __force_inline static void __mem_fence_release(void) {
*/
__force_inline static uint32_t save_and_disable_interrupts(void) {
uint32_t status;
__asm volatile ("mrs %0, PRIMASK" : "=r" (status)::);
__asm volatile ("cpsid i");
unified_asm ("mrs %0, PRIMASK" : "=r" (status)::);
unified_asm ("cpsid i");
return status;
}
@ -218,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) {
__asm volatile ("msr PRIMASK,%0"::"r" (status) : );
unified_asm ("msr PRIMASK,%0"::"r" (status) : );
}
/*! \brief Get HW Spinlock instance from number
@ -389,7 +395,8 @@ int spin_lock_claim_unused(bool required);
*/
bool spin_lock_is_claimed(uint lock_num);
#define remove_volatile_cast(t, x) ({__mem_fence_acquire(); (t)(x); })
// no longer use __mem_fence_acquire here, as it is overkill on cortex M0+
#define remove_volatile_cast(t, x) ({__compiler_memory_barrier(); Clang_Pragma("clang diagnostic push"); Clang_Pragma("clang diagnostic ignored \"-Wcast-qual\""); (t)(x); Clang_Pragma("clang diagnostic pop"); })
#ifdef __cplusplus
}

View File

@ -8,10 +8,6 @@
/// \tag::table_lookup[]
// Bootrom function: rom_table_lookup
// Returns the 32 bit pointer into the ROM if found or NULL otherwise.
typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);
void *rom_func_lookup(uint32_t code) {
return rom_func_lookup_inline(code);
}

View File

@ -116,7 +116,7 @@ bool rom_funcs_lookup(uint32_t *table, unsigned int count);
// Returns the 32 bit pointer into the ROM if found or NULL otherwise.
typedef void *(*rom_table_lookup_fn)(uint16_t *table, uint32_t code);
#if defined(__GNUC__) && (__GNUC__ >= 12)
#if PICO_C_COMPILER_IS_GNU && (__GNUC__ >= 12)
// Convert a 16 bit pointer stored at the given rom address into a 32 bit pointer
static inline void *rom_hword_as_ptr(uint16_t rom_address) {
#pragma GCC diagnostic push

View File

@ -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) {
__asm ("rev16 %0, %0" : "+l" (a) : : );
unified_asm ("rev16 %0, %0" : "+l" (a) : : );
return a;
}
#define SWAP32(a) __swap16x2(a)

View File

@ -47,7 +47,7 @@ void __aeabi_double_init(void) {
#endif
if (rom_version >= 2) {
void *rom_table = rom_data_lookup(rom_table_code('S', 'D'));
assert(*((uint8_t *)(((void *)rom_data_lookup(rom_table_code('S', 'F')))-2)) * 4 >= SF_TABLE_V2_SIZE);
assert(*((uint8_t *)rom_data_lookup(rom_table_code('S', 'F'))-2) * 4 >= SF_TABLE_V2_SIZE);
memcpy(&sd_table, rom_table, SF_TABLE_V2_SIZE);
if (rom_version == 2) {
#ifndef NDEBUG

View File

@ -8,9 +8,9 @@
#include "pico/double.h"
// opened a separate issue https://github.com/raspberrypi/pico-sdk/issues/166 to deal with these warnings if at all
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wconversion\"")
_Pragma("GCC diagnostic ignored \"-Wsign-conversion\"")
GCC_Pragma("GCC diagnostic push")
GCC_Pragma("GCC diagnostic ignored \"-Wconversion\"")
GCC_Pragma("GCC diagnostic ignored \"-Wsign-conversion\"")
typedef uint64_t ui64;
typedef uint32_t ui32;
@ -56,13 +56,13 @@ static inline ui64 double2ui64(double d) {
return tmp.ix;
}
#if PICO_DOUBLE_PROPAGATE_NANS
static inline bool disnan(double x) {
ui64 ix= double2ui64(x);
// checks the top bit of the low 32 bit of the NAN, but it I think that is ok
return ((uint32_t)(ix >> 31)) > 0xffe00000u;
}
#if PICO_DOUBLE_PROPAGATE_NANS
#define check_nan_d1(x) if (disnan((x))) return (x)
#define check_nan_d2(x,y) if (disnan((x))) return (x); else if (disnan((y))) return (y);
#else
@ -109,8 +109,8 @@ double WRAPPER_FUNC(copysign)(double x, double y) {
return dcopysign(x, y);
}
static inline int diszero(double x) { return dgetexp (x)==0; }
static inline int dispzero(double x) { return dgetsignexp(x)==0; }
static inline int dismzero(double x) { return dgetsignexp(x)==0x800; }
//static inline int dispzero(double x) { return dgetsignexp(x)==0; }
//static inline int dismzero(double x) { return dgetsignexp(x)==0x800; }
static inline int disinf(double x) { return dgetexp (x)==0x7ff; }
static inline int dispinf(double x) { return dgetsignexp(x)==0x7ff; }
static inline int disminf(double x) { return dgetsignexp(x)==0xfff; }
@ -419,10 +419,10 @@ static double dpowint_0(double x,int y) {
}
double WRAPPER_FUNC(powint)(double x,int y) {
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
GCC_Like_Pragma("GCC diagnostic push")
GCC_Like_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
if(x==1.0||y==0) return 1;
_Pragma("GCC diagnostic pop")
GCC_Like_Pragma("GCC diagnostic pop")
check_nan_d1(x);
if(diszero(x)) {
if(y>0) {
@ -468,13 +468,13 @@ static double dpow_0(double x,double y) {
}
double WRAPPER_FUNC(pow)(double x,double y) {
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
GCC_Like_Pragma("GCC diagnostic push")
GCC_Like_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
if(x==1.0||diszero(y)) return 1;
check_nan_d2(x, y);
if(x==-1.0&&disinf(y)) return 1;
_Pragma("GCC diagnostic pop")
GCC_Like_Pragma("GCC diagnostic pop")
if(diszero(x)) {
if(!disneg(y)) {
@ -621,4 +621,4 @@ double WRAPPER_FUNC(drem)(double x,double y) { check_nan_d2(x, y); return remquo
double WRAPPER_FUNC(remainder)(double x,double y) { check_nan_d2(x, y); return remquo(x,y,0); }
_Pragma("GCC diagnostic pop") // conversion
GCC_Pragma("GCC diagnostic pop") // conversion

View File

@ -110,8 +110,9 @@ static void hw_enumeration_fix_force_ls_j(void) {
gpio_set_inover(dp, GPIO_OVERRIDE_HIGH);
// Force PHY pull up to stay before switching away from the phy
hw_set_alias(usb_hw)->phy_direct = USB_USBPHY_DIRECT_DP_PULLUP_EN_BITS;
hw_set_alias(usb_hw)->phy_direct_override = USB_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN_BITS;
usb_hw_t *usb_hw_set = (usb_hw_t *)hw_set_alias_untyped(usb_hw);
usb_hw_set->phy_direct = USB_USBPHY_DIRECT_DP_PULLUP_EN_BITS;
usb_hw_set->phy_direct_override = USB_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN_BITS;
// Switch to GPIO phy with LS_J forced
usb_hw->muxing = USB_USB_MUXING_TO_DIGITAL_PAD_BITS | USB_USB_MUXING_SOFTCON_BITS;
@ -138,7 +139,7 @@ static void hw_enumeration_fix_finish(void) {
usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
// Get rid of DP pullup override
hw_clear_alias(usb_hw)->phy_direct_override = USB_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN_BITS;
hw_clear_bits(&usb_hw->phy_direct_override, USB_USBPHY_DIRECT_OVERRIDE_DP_PULLUP_EN_OVERRIDE_EN_BITS);
// Finally, restore the gpio ctrl value back to GPIO15
iobank0_hw->io[dp].ctrl = gpio_ctrl_prev;

View File

@ -63,7 +63,7 @@ void __aeabi_float_init(void) {
}
#endif
if (rom_version >= 2) {
assert(*((uint8_t *)(rom_table-2)) * 4 >= SF_TABLE_V2_SIZE);
assert(*((uint8_t *)rom_table-2) * 4 >= SF_TABLE_V2_SIZE);
memcpy(&sf_table, rom_table, SF_TABLE_V2_SIZE);
}
sf_clz_func = rom_func_lookup(ROM_FUNC_CLZ32);

View File

@ -7,9 +7,9 @@
#include "pico/float.h"
// opened a separate issue https://github.com/raspberrypi/pico-sdk/issues/166 to deal with these warnings if at all
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wconversion\"")
_Pragma("GCC diagnostic ignored \"-Wsign-conversion\"")
GCC_Pragma("GCC diagnostic push")
GCC_Pragma("GCC diagnostic ignored \"-Wconversion\"")
GCC_Pragma("GCC diagnostic ignored \"-Wsign-conversion\"")
typedef uint32_t ui32;
typedef int32_t i32;
@ -54,12 +54,12 @@ static inline ui32 float2ui32(float f) {
return tmp.ix;
}
#if PICO_FLOAT_PROPAGATE_NANS
static inline bool fisnan(float x) {
ui32 ix=float2ui32(x);
return ix * 2 > 0xff000000u;
}
#if PICO_FLOAT_PROPAGATE_NANS
#define check_nan_f1(x) if (fisnan((x))) return (x)
#define check_nan_f2(x,y) if (fisnan((x))) return (x); else if (fisnan((y))) return (y);
#else
@ -106,8 +106,8 @@ float WRAPPER_FUNC(copysignf)(float x, float y) {
}
static inline int fiszero(float x) { return fgetexp (x)==0; }
static inline int fispzero(float x) { return fgetsignexp(x)==0; }
static inline int fismzero(float x) { return fgetsignexp(x)==0x100; }
//static inline int fispzero(float x) { return fgetsignexp(x)==0; }
//static inline int fismzero(float x) { return fgetsignexp(x)==0x100; }
static inline int fisinf(float x) { return fgetexp (x)==0xff; }
static inline int fispinf(float x) { return fgetsignexp(x)==0xff; }
static inline int fisminf(float x) { return fgetsignexp(x)==0x1ff; }
@ -377,8 +377,8 @@ static float fpowint_0(float x,int y) {
}
float WRAPPER_FUNC(powintf)(float x,int y) {
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
GCC_Pragma("GCC diagnostic push")
GCC_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
if(x==1.0f||y==0) return 1;
if(x==0.0f) {
if(y>0) {
@ -388,7 +388,7 @@ float WRAPPER_FUNC(powintf)(float x,int y) {
if((y&1)) return fcopysign(FPINF,x);
return FPINF;
}
_Pragma("GCC diagnostic pop")
GCC_Pragma("GCC diagnostic pop")
check_nan_f1(x);
if(fispinf(x)) {
if(y<0) return 0;
@ -426,12 +426,12 @@ static float fpow_0(float x,float y) {
}
float WRAPPER_FUNC(powf)(float x,float y) {
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
GCC_Like_Pragma("GCC diagnostic push")
GCC_Like_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
if(x==1.0f||fiszero(y)) return 1;
check_nan_f2(x,y);
if(x==-1.0f&&fisinf(y)) return 1;
_Pragma("GCC diagnostic pop")
GCC_Like_Pragma("GCC diagnostic pop")
if(fiszero(x)) {
if(!fisneg(y)) {
if(fisoddint(y)) return x;
@ -579,4 +579,4 @@ float WRAPPER_FUNC(dremf)(float x,float y) { check_nan_f2(x,y); return remquof(x
float WRAPPER_FUNC(remainderf)(float x,float y) { check_nan_f2(x,y); return remquof(x,y,0); }
_Pragma("GCC diagnostic pop") // conversion
GCC_Pragma("GCC diagnostic pop") // conversion

View File

@ -29,7 +29,6 @@ wrapper_func __aeabi_i2f
wrapper_func __aeabi_l2f
wrapper_func __aeabi_ui2f
wrapper_func __aeabi_ul2f
wrapper_func __aeabi_i2f
wrapper_func __aeabi_f2iz
wrapper_func __aeabi_f2lz
wrapper_func __aeabi_f2uiz

View File

@ -15,10 +15,6 @@ typedef struct i2c_slave {
static i2c_slave_t i2c_slaves[2];
static inline i2c_inst_t *get_hw_instance(const i2c_slave_t *slave) {
return i2c_get_instance(slave - i2c_slaves);
}
static void __isr __not_in_flash_func(i2c_slave_irq_handler)(void) {
uint i2c_index = __get_current_exception() - VTABLE_FIRST_IRQ - I2C0_IRQ;
i2c_slave_t *slave = &i2c_slaves[i2c_index];

View File

@ -5,7 +5,6 @@
*/
#include <stdlib.h>
#include <stdio.h>
#include "pico.h"
#include "pico/malloc.h"
@ -14,10 +13,10 @@
auto_init_mutex(malloc_mutex);
#endif
extern void *__real_malloc(size_t size);
extern void *__real_calloc(size_t count, size_t size);
extern void *__real_realloc(void *mem, size_t size);
extern void __real_free(void *mem);
extern void *REAL_FUNC(malloc)(size_t size);
extern void *REAL_FUNC(calloc)(size_t count, size_t size);
extern void *REAL_FUNC(realloc)(void *mem, size_t size);
extern void REAL_FUNC(free)(void *mem);
extern char __StackLimit; /* Set by linker. */
@ -29,11 +28,11 @@ static inline void check_alloc(__unused void *mem, __unused uint size) {
#endif
}
void *__wrap_malloc(size_t size) {
void *WRAPPER_FUNC(malloc)(size_t size) {
#if PICO_USE_MALLOC_MUTEX
mutex_enter_blocking(&malloc_mutex);
#endif
void *rc = __real_malloc(size);
void *rc = REAL_FUNC(malloc)(size);
#if PICO_USE_MALLOC_MUTEX
mutex_exit(&malloc_mutex);
#endif
@ -46,11 +45,11 @@ void *__wrap_malloc(size_t size) {
return rc;
}
void *__wrap_calloc(size_t count, size_t size) {
void *WRAPPER_FUNC(calloc)(size_t count, size_t size) {
#if PICO_USE_MALLOC_MUTEX
mutex_enter_blocking(&malloc_mutex);
#endif
void *rc = __real_calloc(count, size);
void *rc = REAL_FUNC(calloc)(count, size);
#if PICO_USE_MALLOC_MUTEX
mutex_exit(&malloc_mutex);
#endif
@ -63,11 +62,11 @@ void *__wrap_calloc(size_t count, size_t size) {
return rc;
}
void *__wrap_realloc(void *mem, size_t size) {
void *WRAPPER_FUNC(realloc)(void *mem, size_t size) {
#if PICO_USE_MALLOC_MUTEX
mutex_enter_blocking(&malloc_mutex);
#endif
void *rc = __real_realloc(mem, size);
void *rc = REAL_FUNC(realloc)(mem, size);
#if PICO_USE_MALLOC_MUTEX
mutex_exit(&malloc_mutex);
#endif
@ -80,11 +79,11 @@ void *__wrap_realloc(void *mem, size_t size) {
return rc;
}
void __wrap_free(void *mem) {
void WRAPPER_FUNC(free)(void *mem) {
#if PICO_USE_MALLOC_MUTEX
mutex_enter_blocking(&malloc_mutex);
#endif
__real_free(mem);
REAL_FUNC(free)(mem);
#if PICO_USE_MALLOC_MUTEX
mutex_exit(&malloc_mutex);
#endif

View File

@ -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) {
__asm("pop {r0, r1, pc}");
unified_asm ("pop {r0, r1, pc}");
}
int core1_wrapper(int (*entry)(void), void *stack_base) {

View File

@ -68,9 +68,80 @@
#ifndef __ASSEMBLER__
#if defined __GNUC__
#include <sys/cdefs.h>
// note LLVM defines __GNUC__
#ifdef __clang__
#define PICO_C_COMPILER_IS_CLANG 1
#else
#define PICO_C_COMPILER_IS_GNU 1
#endif
#elif defined __ICCARM__
#ifndef __aligned
#define __aligned(x) __attribute__((__aligned__(x)))
#endif
#ifndef __always_inline
#define __always_inline __attribute__((__always_inline__))
#endif
#ifndef __noinline
#define __noinline __attribute__((__noinline__))
#endif
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif
#ifndef __printflike
#define __printflike(a, b)
#endif
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
#ifndef __used
#define __used __attribute__((__used__))
#endif
#ifndef __CONCAT1
#define __CONCAT1(a, b) a ## b
#endif
#ifndef __CONCAT
#define __CONCAT(a, b) __CONCAT1(a, b)
#endif
#ifndef __STRING
#define __STRING(a) #a
#endif
/* Compatible definitions of GCC builtins */
static inline uint __builtin_ctz(uint x) {
extern uint32_t __ctzsi2(uint32_t);
return __ctzsi2(x);
}
#define __builtin_expect(x, y) (x)
#define __builtin_isnan(x) __iar_isnan(x)
#else
#error Unsupported toolchain
#endif
#include "pico/types.h"
// GCC_Like_Pragma(x) is a pragma on GNUC compatible compilers
#ifdef __GNUC__
#define GCC_Like_Pragma _Pragma
#else
#define GCC_Like_Pragma(x)
#endif
// Clang_Pragma(x) is a pragma on Clang only
#ifdef __clang__
#define Clang_Pragma _Pragma
#else
#define Clang_Pragma(x)
#endif
// GCC_Pragma(x) is a pragma on GCC only
#if PICO_C_COMPILER_IS_GNU
#define GCC_Pragma _Pragma
#else
#define GCC_Pragma(x)
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -236,7 +307,8 @@ extern "C" {
* int __force_inline my_function(int x) {
*
*/
#if defined(__GNUC__) && (__GNUC__ <= 6 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || !defined(__cplusplus))))
#if PICO_C_COMPILER_IS_GNU && (__GNUC__ <= 6 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || !defined(__cplusplus))))
#define __force_inline inline __always_inline
#else
#define __force_inline __always_inline
@ -263,11 +335,13 @@ extern "C" {
#define MIN(a, b) ((b)>(a)?(a):(b))
#endif
#define unified_asm(...) __asm volatile (".syntax unified\n" __VA_ARGS__)
/*! \brief Execute a breakpoint instruction
* \ingroup pico_platform
*/
static inline void __breakpoint(void) {
__asm__("bkpt #0");
unified_asm ("bkpt #0");
}
/*! \brief Ensure that the compiler does not move memory access across this method call
@ -283,7 +357,7 @@ static inline void __breakpoint(void) {
* might - even above the memory store!)
*/
__force_inline static void __compiler_memory_barrier(void) {
__asm__ volatile ("" : : : "memory");
unified_asm ("" : : : "memory");
}
/*! \brief Macro for converting memory addresses to 32 bit addresses suitable for DMA
@ -343,10 +417,10 @@ uint8_t rp2040_chip_version(void);
* @return the RP2040 rom version number (1 for RP2040-B0, 2 for RP2040-B1, 3 for RP2040-B2)
*/
static inline uint8_t rp2040_rom_version(void) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
GCC_Pragma("GCC diagnostic push")
GCC_Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
return *(uint8_t*)0x13;
#pragma GCC diagnostic pop
GCC_Pragma("GCC diagnostic pop")
}
/*! \brief No-op function for the body of tight loops
@ -369,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) {
asm ("mul %0, %1" : "+l" (a) : "l" (b) : );
unified_asm ("muls %0, %1" : "+l" (a) : "l" (b) : );
return a;
}
@ -405,7 +479,7 @@ __force_inline static int32_t __mul_instruction(int32_t a, int32_t b) {
*/
static inline uint __get_current_exception(void) {
uint exception;
asm ("mrs %0, ipsr" : "=l" (exception));
unified_asm ("mrs %0, ipsr" : "=l" (exception));
return exception;
}
@ -431,8 +505,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) {
__asm volatile (
".syntax unified\n"
unified_asm (
"1: subs %0, #3\n"
"bcs 1b\n"
: "+r" (minimum_cycles) : : "memory"

View File

@ -18,7 +18,7 @@
#if !PICO_NO_FPGA_CHECK
// Inline stub provided in header if this code is unused (so folding can be
// done in each TU instead of relying on LTO)
bool running_on_fpga() {
bool running_on_fpga(void) {
return !!((*(io_ro_32 *)TBMAN_BASE) & TBMAN_PLATFORM_FPGA_BITS);
}
#endif
@ -26,7 +26,7 @@ bool running_on_fpga() {
#define MANUFACTURER_RPI 0x927
#define PART_RP2 0x2
uint8_t rp2040_chip_version() {
uint8_t rp2040_chip_version(void) {
// First register of sysinfo is chip id
uint32_t chip_id = *((io_ro_32*)(SYSINFO_BASE + SYSINFO_CHIP_ID_OFFSET));
uint32_t __unused manufacturer = chip_id & SYSINFO_CHIP_ID_MANUFACTURER_BITS;

View File

@ -107,15 +107,6 @@
#endif
/**
* Output a character to a custom device like UART, used by the printf() function
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
static void _putchar(char character) {
putchar(character);
}
// output function type
typedef void (*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen);
@ -148,17 +139,6 @@ static inline void _out_null(char character, void *buffer, size_t idx, size_t ma
(void) maxlen;
}
// internal _putchar wrapper
static inline void _out_char(char character, void *buffer, size_t idx, size_t maxlen) {
(void) buffer;
(void) idx;
(void) maxlen;
if (character) {
_putchar(character);
}
}
// internal output function wrapper
static inline void _out_fct(char character, void *buffer, size_t idx, size_t maxlen) {
(void) idx;
@ -920,6 +900,25 @@ int vfctprintf(void (*out)(char character, void *arg), void *arg, const char *fo
#if LIB_PICO_PRINTF_PICO
#if !PICO_PRINTF_ALWAYS_INCLUDED
/**
* Output a character to a custom device like UART, used by the printf() function
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
static void _putchar(char character) {
putchar(character);
}
// internal _putchar wrapper
static inline void _out_char(char character, void *buffer, size_t idx, size_t maxlen) {
(void) buffer;
(void) idx;
(void) maxlen;
if (character) {
_putchar(character);
}
}
bool weak_raw_printf(const char *fmt, ...) {
va_list va;
va_start(va, fmt);

View File

@ -40,5 +40,9 @@ if (TARGET pico_standard_link)
endif()
# todo is this correct/needed?
target_link_options(pico_runtime INTERFACE "--specs=nosys.specs")
if (PICO_C_COMPILER_IS_GNU)
target_link_options(pico_runtime INTERFACE "--specs=nosys.specs")
elseif (PICO_C_COMPILER_IS_CLANG)
# target_link_options(pico_runtime INTERFACE "-nostdlib")
endif()

View File

@ -114,8 +114,9 @@ void runtime_init(void) {
#if !PICO_IE_26_29_UNCHANGED_ON_RESET
// after resetting BANK0 we should disable IE on 26-29
hw_clear_alias(padsbank0_hw)->io[26] = hw_clear_alias(padsbank0_hw)->io[27] =
hw_clear_alias(padsbank0_hw)->io[28] = hw_clear_alias(padsbank0_hw)->io[29] = PADS_BANK0_GPIO0_IE_BITS;
padsbank0_hw_t *padsbank0_hw_clear = (padsbank0_hw_t *)hw_clear_alias_untyped(padsbank0_hw);
padsbank0_hw_clear->io[26] = padsbank0_hw_clear->io[27] =
padsbank0_hw_clear->io[28] = padsbank0_hw_clear->io[29] = PADS_BANK0_GPIO0_IE_BITS;
#endif
// this is an array of either mutex_t or recursive_mutex_t (i.e. not necessarily the same size)
@ -150,7 +151,7 @@ void runtime_init(void) {
#ifndef NDEBUG
if (__get_current_exception()) {
// crap; started in exception handler
__asm ("bkpt #0");
unified_asm ("bkpt #0");
}
#endif
@ -260,8 +261,8 @@ void exit(int status) {
}
// incorrect warning from GCC 6
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
GCC_Pragma("GCC diagnostic push")
GCC_Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=format\"")
void __assert_func(const char *file, int line, const char *func, const char *failedexpr) {
weak_raw_printf("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
failedexpr, file, line, func ? ", function: " : "",
@ -269,10 +270,9 @@ void __assert_func(const char *file, int line, const char *func, const char *fai
_exit(1);
}
GCC_Pragma("GCC diagnostic pop")
#pragma GCC diagnostic pop
void __attribute__((noreturn)) panic_unsupported() {
void __attribute__((noreturn)) panic_unsupported(void) {
panic("not supported");
}
@ -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!
__asm (
unified_asm (
"push {lr}\n"
#if !PICO_PANIC_FUNCTION_EMPTY
"bl " __XSTRING(PICO_PANIC_FUNCTION) "\n"

View File

@ -10,8 +10,8 @@ if (NOT TARGET pico_standard_link)
pico_add_map_output(pico_standard_link)
# todo revisit when we do Clang
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(pico_standard_link INTERFACE "LINKER:-nostdlib")
if (PICO_C_COMPILER_IS_CLANG)
# target_link_options(pico_standard_link INTERFACE "LINKER:-fuse-ld=lld")
endif ()
pico_mirrored_target_link_libraries(pico_standard_link INTERFACE hardware_regs pico_bootrom pico_binary_info)
@ -74,9 +74,11 @@ if (NOT TARGET pico_standard_link)
target_compile_definitions(pico_standard_link INTERFACE PICO_DEOPTIMIZED_DEBUG=1)
endif()
# todo revisit/recall reasoning for why not -nostartfiles always?
# -nostartfiles will be added if PICO_NO_FLASH would be defined to 1
target_link_options(pico_standard_link INTERFACE $<$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>:-nostartfiles>)
# -nostartfiles will be added if not using C++ exceptions (which is the only thing that seems to need it)
if (PICO_C_COMPILER_IS_GNU AND NOT PICO_CXX_ENABLE_EXCEPTIONS)
# target_link_options(pico_standard_link INTERFACE $<$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>:-nostartfiles>)
target_link_options(pico_standard_link INTERFACE -nostartfiles)
endif()
# boot_stage2 will be linked if PICO_NO_FLASH would be defined to 0
target_link_libraries(pico_standard_link INTERFACE $<$<NOT:$<IF:$<STREQUAL:$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>,no_flash>,1,$<AND:$<BOOL:${PICO_NO_FLASH}>,$<STREQUAL:,$<TARGET_PROPERTY:PICO_TARGET_BINARY_TYPE>>>>>:$<IF:$<BOOL:$<TARGET_PROPERTY:PICO_TARGET_BOOT_STAGE2>>,$<TARGET_PROPERTY:PICO_TARGET_BOOT_STAGE2>,bs2_default>_library>)
@ -96,7 +98,7 @@ if (NOT TARGET pico_standard_link)
target_link_options(pico_standard_link INTERFACE "LINKER:--gc-sections")
endif()
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
if (PICO_C_COMPILER_IS_GNU)
# Ignore warnings about rwx segments introduced in binutils 2.39
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-prog-name=ld RESULT_VARIABLE RUN_C_RESULT OUTPUT_VARIABLE FULL_LD_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE)

View File

@ -325,13 +325,13 @@ hold_non_core0_in_bootrom:
// ----------------------------------------------------------------------------
// Stack/heap dummies to set size
.section .stack
.section .stack, "a"
// align to allow for memory protection (although this alignment is pretty much ignored by linker script)
.align 5
.equ StackSize, PICO_STACK_SIZE
.space StackSize
.section .heap
.section .heap, "a"
.align 2
.equ HeapSize, PICO_HEAP_SIZE
.space HeapSize

View File

@ -117,10 +117,7 @@ SECTIONS
__binary_info_end = .;
. = ALIGN(4);
/* End of .text-like segments */
__etext = .;
.ram_vector_table (COPY): {
.ram_vector_table (NOLOAD): {
*(.ram_vector_table)
} > RAM
@ -173,8 +170,10 @@ SECTIONS
/* All data end */
__data_end__ = .;
} > RAM AT> FLASH
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
__etext = LOADADDR(.data);
.uninitialized_data (COPY): {
.uninitialized_data (NOLOAD): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
@ -205,7 +204,7 @@ SECTIONS
__bss_end__ = .;
} > RAM
.heap (COPY):
.heap (NOLOAD):
{
__end__ = .;
end = __end__;
@ -222,17 +221,17 @@ SECTIONS
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY):
.stack1_dummy (NOLOAD):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY):
.stack_dummy (NOLOAD):
{
*(.stack*)
} > SCRATCH_Y
.flash_end : {
__flash_binary_end = .;
PROVIDE(__flash_binary_end = .);
} > FLASH
/* stack limit is poorly named, but historically is maximum heap ptr */

View File

@ -96,7 +96,7 @@ SECTIONS
. = ALIGN(4);
/* Vector table goes first in RAM, to avoid large alignment hole */
.ram_vector_table (COPY): {
.ram_vector_table (NOLOAD): {
*(.ram_vector_table)
} > RAM
@ -123,7 +123,7 @@ SECTIONS
__ram_text_end__ = .;
} > RAM AT> FLASH
__ram_text_source__ = LOADADDR(.text);
. = ALIGN(4);
.data : {
__data_start__ = .;
@ -172,10 +172,10 @@ SECTIONS
/* All data end */
__data_end__ = .;
} > RAM AT> FLASH
/* __etext is the name of the .data init source pointer (...) */
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
__etext = LOADADDR(.data);
.uninitialized_data (COPY): {
.uninitialized_data (NOLOAD): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
@ -206,7 +206,7 @@ SECTIONS
__bss_end__ = .;
} > RAM
.heap (COPY):
.heap (NOLOAD):
{
__end__ = .;
end = __end__;
@ -223,11 +223,11 @@ SECTIONS
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY):
.stack1_dummy (NOLOAD):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY):
.stack_dummy (NOLOAD):
{
*(.stack*)
} > SCRATCH_Y

View File

@ -117,10 +117,7 @@ SECTIONS
__binary_info_end = .;
. = ALIGN(4);
/* End of .text-like segments */
__etext = .;
.ram_vector_table (COPY): {
.ram_vector_table (NOLOAD): {
*(.ram_vector_table)
} > RAM
@ -173,8 +170,10 @@ SECTIONS
/* All data end */
__data_end__ = .;
} > RAM AT> FLASH
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
__etext = LOADADDR(.data);
.uninitialized_data (COPY): {
.uninitialized_data (NOLOAD): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
@ -205,7 +204,7 @@ SECTIONS
__bss_end__ = .;
} > RAM
.heap (COPY):
.heap (NOLOAD):
{
__end__ = .;
end = __end__;
@ -222,17 +221,17 @@ SECTIONS
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY):
.stack1_dummy (NOLOAD):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY):
.stack_dummy (NOLOAD):
{
*(.stack*)
} > SCRATCH_Y
.flash_end : {
__flash_binary_end = .;
PROVIDE(__flash_binary_end = .);
} > FLASH
/* stack limit is poorly named, but historically is maximum heap ptr */

View File

@ -100,8 +100,6 @@ SECTIONS
. = ALIGN(4);
.data : {
/* End of .text-like segments */
__etext = .;
__data_start__ = .;
*(vtable)
*(.data*)
@ -143,10 +141,12 @@ SECTIONS
__data_end__ = .;
} > RAM
.uninitialized_data (COPY): {
.uninitialized_data (NOLOAD): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
__etext = LOADADDR(.data);
/* Start and end symbols must be word-aligned */
.scratch_x : {
@ -174,7 +174,7 @@ SECTIONS
__bss_end__ = .;
} > RAM
.heap (COPY):
.heap (NOLOAD):
{
__end__ = .;
end = __end__;
@ -191,11 +191,11 @@ SECTIONS
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
* stack is not used then all of SCRATCH_X is free.
*/
.stack1_dummy (COPY):
.stack1_dummy (NOLOAD):
{
*(.stack1*)
} > SCRATCH_X
.stack_dummy (COPY):
.stack_dummy (NOLOAD):
{
*(.stack*)
} > SCRATCH_Y

View File

@ -9,6 +9,7 @@
#if !PICO_CXX_DISABLE_ALLOCATION_OVERRIDES // Let user override
#include <cstdlib>
#include "pico.h"
void *operator new(std::size_t n) {
return std::malloc(n);

View File

@ -25,11 +25,11 @@ static void stdio_semihosting_out_chars(const char *buf, int length) {
args.buf = buf;
args.len = length;
__asm (
unified_asm (
// r1 must contain a pointer to the arguments
"mov r1, %[args]\n"
"movs r1, %[args]\n"
// semihosting call number 0x05 = SYS_WRITE
"mov r0, #5\n"
"movs r0, #5\n"
// make the semihosting call: https://developer.arm.com/documentation/dui0375/g/What-is-Semihosting-/The-semihosting-interface
"bkpt 0xab\n"
:

View File

@ -20,9 +20,6 @@
#include "device/usbd_pvt.h" // for usbd_defer_func
static mutex_t stdio_usb_mutex;
#ifndef NDEBUG
static uint8_t stdio_usb_core_num;
#endif
#if PICO_STDIO_USB_SUPPORT_CHARS_AVAILABLE_CALLBACK
static void (*chars_available_callback)(void*);
@ -181,9 +178,6 @@ bool stdio_usb_init(void) {
assert(false);
return false;
}
#ifndef NDEBUG
stdio_usb_core_num = (uint8_t)get_core_num();
#endif
#if !PICO_NO_BI_STDIO_USB
bi_decl_if_func_used(bi_program_feature("USB stdin / stdout"));
#endif

View File

@ -49,10 +49,12 @@ if (EXISTS ${PICO_TINYUSB_PATH}/${TINYUSB_TEST_PATH})
# Override suppress_tinyusb_warnings to add suppression of (falsely) reported GCC 11.2 warnings
function(suppress_tinyusb_warnings)
_suppress_tinyusb_warnings()
set_source_files_properties(
${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/rp2040_usb.c
PROPERTIES
COMPILE_FLAGS "-Wno-stringop-overflow -Wno-array-bounds")
if (PICO_C_COMPILER_IS_GNU)
set_source_files_properties(
${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/rp2040_usb.c
PROPERTIES
COMPILE_FLAGS "-Wno-stringop-overflow -Wno-array-bounds")
endif()
endfunction()
pico_promote_common_scope_vars()

View File

@ -80,6 +80,14 @@ target_compile_options(kitchen_sink_options INTERFACE
#-Wundef
)
if (PICO_C_COMPILER_IS_CLANG)
# todo fix up clang warnings
target_compile_options(kitchen_sink_options INTERFACE
-Wno-cast-qual
-Wno-unused-function
-Wno-format)
endif()
target_compile_definitions(kitchen_sink_libs INTERFACE
PARAM_ASSERTIONS_ENABLE_ALL=1 # want to check all the assertions for compilation warnings
PICO_AUDIO_DMA_IRQ=1
@ -97,6 +105,8 @@ if (COMMAND suppress_tinyusb_warnings)
# TinyUSB itself, so we have to guard against TinyUSB not being present with the above if
suppress_tinyusb_warnings()
endif()
target_compile_definitions(kitchen_sink_extra_stdio PRIVATE
TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX=1)
if (TARGET pico_lwip)
set_source_files_properties(
${PICO_LWIP_PATH}/src/core/ipv4/ip4_frag.c
@ -119,6 +129,11 @@ pico_set_binary_type(kitchen_sink_no_flash no_flash)
target_link_libraries(kitchen_sink_no_flash kitchen_sink_libs kitchen_sink_options)
pico_add_extra_outputs(kitchen_sink_no_flash)
add_executable(kitchen_sink_blocked_ram ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink.c)
pico_set_binary_type(kitchen_sink_blocked_ram blocked_ram)
target_link_libraries(kitchen_sink_blocked_ram kitchen_sink_libs kitchen_sink_options)
pico_add_extra_outputs(kitchen_sink_blocked_ram)
add_executable(kitchen_sink_cpp ${CMAKE_CURRENT_LIST_DIR}/kitchen_sink_cpp.cpp)
target_link_libraries(kitchen_sink_cpp kitchen_sink_libs kitchen_sink_options)
pico_set_program_name(kitchen_sink_cpp "Wombat tentacles CPP")

View File

@ -100,9 +100,6 @@ bi_decl(bi_block_device(
BINARY_INFO_BLOCK_DEV_FLAG_READ | BINARY_INFO_BLOCK_DEV_FLAG_WRITE |
BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN));
//#pragma GCC push_options
//#pragma GCC optimize ("O3")
uint32_t *foo = (uint32_t *) 200;
uint32_t dma_to = 0;
@ -133,11 +130,14 @@ int main(void) {
puts("Hello Everything!");
puts("Hello Everything2!");
printf("main at %p\n", (void *)main);
static uint x[2];
printf("x[0] = %p, x[1] = %p\n", x, x+1);
hard_assert(mutex_try_enter(&mutex, NULL));
hard_assert(!mutex_try_enter(&mutex, NULL));
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+
__asm volatile("SVC #3");
unified_asm ("SVC #3");
}

View File

@ -34,16 +34,16 @@ bool timer_callback(repeating_timer_t *t) {
FAILED();
}
}
float fz = z;
float fz = (float)z;
float fa = fz / 11.0f;
float fb = fmodf(fz, 11.0f);
if (fabsf(fz - (fa * 11.0 + fb) > 1e-9)) {
if (fabs(fz - (fa * 11.0 + fb)) > 1e-9) {
FAILED();
}
double dz = z;
double da = dz / 11.0;
double db = fmod(dz, 11.0);
if (fabsf(dz - (da * 11.0 + db) > 1e-9)) {
if (fabs(dz - (da * 11.0 + db)) > 1e-9) {
FAILED();
}

View File

@ -193,10 +193,9 @@ 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)) {
asm(
".syntax unified\n"
unified_asm (
"push {r4, r5, lr}\n"
"ldr r4, =#0xe000e018\n"
"ldr r4, =0xe000e018\n"
"ldr r5, [r4]\n"
"blx r2\n"
"ldr r0, [r4]\n"
@ -208,11 +207,10 @@ 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)) {
asm(
".syntax unified\n"
unified_asm (
"push {r4-r6, lr}\n"
"ldr r6, [sp, #16]\n"
"ldr r4, =#0xe000e018\n"
"ldr r4, =0xe000e018\n"
"ldr r5, [r4]\n"
"blx r6\n"
"ldr r0, [r4]\n"

View File

@ -398,7 +398,10 @@ int main() {
printf("FEXP %10.18f\n", check_close1(expf, x));
printf("FLN %10.18f\n", check_close1(logf, x));
printf("POWF %10.18f\n", check_close2(powf, x, x));
// todo clang why does this not compile?
#ifndef __clang__
printf("TRUNCF %10.18f\n", check_close1(truncf, x));
#endif
printf("LDEXPF %10.18f\n", check_close2(ldexpf, x, x));
printf("FMODF %10.18f\n", check_close2(fmodf, x, 3.0f));
sincosf(x, &s, &c);
@ -528,6 +531,10 @@ int main() {
}
for(float x = 4294967296.f * 4294967296.f; x>=0.5f; x/=2.f) {
printf("d2i32 %f->%d\n", x, (int32_t)x);
#ifdef __clang__
// seems to be a bug in clang wgere f2iz(2147483648.f) returns -2147483648
if (x != 2147483648.f)
#endif
check1(__aeabi_f2iz, x);
}

View File

@ -129,7 +129,7 @@ int check_address_range(const address_ranges& valid_ranges, uint32_t addr, uint3
for(const auto& range : valid_ranges) {
if (range.from <= addr && range.to >= addr + size) {
if (range.type == address_range::type::NO_CONTENTS && !uninitialized) {
return fail(ERROR_INCOMPATIBLE, "ELF contains memory contents for uninitialized memory at 0x%p", addr);
return fail(ERROR_INCOMPATIBLE, "ELF contains memory contents for uninitialized memory at %p", addr);
}
ar = range;
if (verbose) {