Small API additions and minor fixes (#406)
* Add missing DREQ_s * store actual clock frequency in clock_configure (fixes #368) * use dma DREQ values defined in dreqs/dma.h * Fix hw_is_claimed, and add xxx_is_claimed APIs * Add some PIO irq helper methods * Add DMA channel IRQ status getter and clear methods * Implement the correct PIO IRQ status/clear methods (good to have methods here as the h/w interrupt registers are super confusing) * fix pico_multicore dependencies * add missing wrapper func __aeabi_f2d * Further DMA/PIO IRQ API cleanup (and review fixes) * add PICO_INT64_OPS_IN_RAM flag
This commit is contained in:
parent
91e9327ff1
commit
5afa3636d6
@ -12,7 +12,7 @@ if (NOT PICO_GCC_TRIPLE)
|
||||
message("PICO_GCC_TRIPLE set from environment: $ENV{PICO_GCC_TRIPLE}")
|
||||
else()
|
||||
set(PICO_GCC_TRIPLE arm-none-eabi)
|
||||
pico_message_debug("PICO_GCC_TRIPLE defaulted to arm-none-eabi")
|
||||
#pico_message_debug("PICO_GCC_TRIPLE defaulted to arm-none-eabi")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -283,7 +283,7 @@ static void alarm_pool_dump_key(pheap_node_id_t id, void *user_data) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int64_t repeating_timer_callback(__unused alarm_id_t id, __unused void *user_data) {
|
||||
static int64_t repeating_timer_callback(__unused alarm_id_t id, void *user_data) {
|
||||
repeating_timer_t *rt = (repeating_timer_t *)user_data;
|
||||
assert(rt->alarm_id == id);
|
||||
if (rt->callback(rt)) {
|
||||
|
@ -50,7 +50,7 @@ set(PICO_CMSIS_VENDOR RaspberryPi)
|
||||
set(PICO_CMSIS_DEVICE RP2040)
|
||||
|
||||
if (PICO_CMSIS_CORE_PATH)
|
||||
add_library(cmsis_core INTERFACE)
|
||||
pico_add_impl_library(cmsis_core)
|
||||
target_sources(cmsis_core INTERFACE
|
||||
${PICO_CMSIS_CORE_PATH}/CMSIS/Device/${PICO_CMSIS_VENDOR}/${PICO_CMSIS_DEVICE}/Source/system_${PICO_CMSIS_DEVICE}.c
|
||||
)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef _CMSIS_RENAME_EXCEPTIONS_H
|
||||
#define _CMSIS_RENAME_EXCEPTIONS_H
|
||||
|
||||
#if LIB_CMSIS_CORE
|
||||
// PICO_CONFIG: PICO_CMSIS_RENAME_EXCEPTIONS, Whether to rename SDK exceptions such as isr_nmi to their CMSIS equivalent i.e. NMI_Handler, type=bool, default=1, group=cmsis_core
|
||||
|
||||
// Note that since this header is included at the config stage, if you wish to override this you should do so via build compiler define
|
||||
@ -48,4 +49,5 @@
|
||||
#define isr_irq25 RTC_IRQ_Handler
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* _CMSIS_RENAME_EXCEPTIONS_H */
|
||||
|
@ -14,22 +14,13 @@ void hw_claim_unlock(uint32_t save) {
|
||||
spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_HARDWARE_CLAIM), save);
|
||||
}
|
||||
|
||||
bool hw_is_claimed(uint8_t *bits, uint bit_index) {
|
||||
bool rc;
|
||||
uint32_t save = hw_claim_lock();
|
||||
if (bits[bit_index >> 3u] & (1u << (bit_index & 7u))) {
|
||||
rc = false;
|
||||
} else {
|
||||
bits[bit_index >> 3u] |= (uint8_t)(1u << (bit_index & 7u));
|
||||
rc = true;
|
||||
}
|
||||
hw_claim_unlock(save);
|
||||
return rc;
|
||||
inline bool hw_is_claimed(const uint8_t *bits, uint bit_index) {
|
||||
return (bits[bit_index >> 3u] & (1u << (bit_index & 7u)));
|
||||
}
|
||||
|
||||
void hw_claim_or_assert(uint8_t *bits, uint bit_index, const char *message) {
|
||||
uint32_t save = hw_claim_lock();
|
||||
if (bits[bit_index >> 3u] & (1u << (bit_index & 7u))) {
|
||||
if (hw_is_claimed(bits, bit_index)) {
|
||||
panic(message, bit_index);
|
||||
} else {
|
||||
bits[bit_index >> 3u] |= (uint8_t)(1u << (bit_index & 7u));
|
||||
@ -42,7 +33,7 @@ int hw_claim_unused_from_range(uint8_t *bits, bool required, uint bit_lsb, uint
|
||||
uint32_t save = hw_claim_lock();
|
||||
int found_bit = -1;
|
||||
for(uint bit=bit_lsb; bit <= bit_msb; bit++) {
|
||||
if (!(bits[bit >> 3u] & (1u << (bit & 7u)))) {
|
||||
if (!hw_is_claimed(bits, bit)) {
|
||||
bits[bit >> 3u] |= (uint8_t)(1u << (bit & 7u));
|
||||
found_bit = (int)bit;
|
||||
break;
|
||||
@ -57,7 +48,7 @@ int hw_claim_unused_from_range(uint8_t *bits, bool required, uint bit_lsb, uint
|
||||
|
||||
void hw_claim_clear(uint8_t *bits, uint bit_index) {
|
||||
uint32_t save = hw_claim_lock();
|
||||
assert(bits[bit_index >> 3u] & (1u << (bit_index & 7u)));
|
||||
assert(hw_is_claimed(bits, bit_index));
|
||||
bits[bit_index >> 3u] &= (uint8_t) ~(1u << (bit_index & 7u));
|
||||
hw_claim_unlock(save);
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ int hw_claim_unused_from_range(uint8_t *bits, bool required, uint bit_lsb, uint
|
||||
* The resource ownership is indicated by the bit_index bit in an array of bits.
|
||||
*
|
||||
* \param bits pointer to an array of bits (8 bits per byte)
|
||||
* \param bit_index resource to unclaim (bit index into array of bits)
|
||||
* \param bit_index resource to check (bit index into array of bits)
|
||||
* \return true if the resource is claimed
|
||||
*/
|
||||
bool hw_is_claimed(uint8_t *bits, uint bit_index);
|
||||
bool hw_is_claimed(const uint8_t *bits, uint bit_index);
|
||||
|
||||
/*! \brief Atomically unclaim a resource
|
||||
* \ingroup hardware_claim
|
||||
|
@ -112,7 +112,7 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc,
|
||||
clock->div = div;
|
||||
|
||||
// Store the configured frequency
|
||||
configured_freq[clk_index] = freq;
|
||||
configured_freq[clk_index] = (uint32_t)(((uint64_t) src_freq << 8) / div);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ int dma_claim_unused_channel(bool required) {
|
||||
return hw_claim_unused_from_range((uint8_t*)&_claimed, required, 0, NUM_DMA_CHANNELS-1, "No DMA channels are available");
|
||||
}
|
||||
|
||||
bool dma_channel_is_claimed(uint channel) {
|
||||
check_dma_channel_param(channel);
|
||||
return hw_is_claimed((uint8_t *) &_claimed, channel);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
void print_dma_ctrl(dma_channel_hw_t *channel) {
|
||||
|
@ -34,8 +34,12 @@ extern "C" {
|
||||
* * Memory to memory
|
||||
*/
|
||||
|
||||
// this is not defined in generated dreq.h
|
||||
#define DREQ_FORCE 63
|
||||
// these are not defined in generated dreq.h
|
||||
#define DREQ_DMA_TIMER0 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER0
|
||||
#define DREQ_DMA_TIMER1 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER1
|
||||
#define DREQ_DMA_TIMER2 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER2
|
||||
#define DREQ_DMA_TIMER3 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER3
|
||||
#define DREQ_FORCE DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_PERMANENT
|
||||
|
||||
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_DMA, Enable/disable DMA assertions, type=bool, default=0, group=hardware_dma
|
||||
#ifndef PARAM_ASSERTIONS_ENABLED_DMA
|
||||
@ -94,6 +98,16 @@ void dma_channel_unclaim(uint channel);
|
||||
*/
|
||||
int dma_claim_unused_channel(bool required);
|
||||
|
||||
/*! \brief Determine if a dma channel is claimed
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel the dma channel
|
||||
* \return true if the channel is claimed, false otherwise
|
||||
* \see dma_channel_claim
|
||||
* \see dma_channel_claim_mask
|
||||
*/
|
||||
bool dma_channel_is_claimed(uint channel);
|
||||
|
||||
/** \brief DMA channel configuration
|
||||
* \defgroup channel_config channel_config
|
||||
* \ingroup hardware_dma
|
||||
@ -465,7 +479,7 @@ static inline void dma_channel_abort(uint channel) {
|
||||
while (dma_hw->abort & (1ul << channel)) tight_loop_contents();
|
||||
}
|
||||
|
||||
/*! \brief Enable single DMA channel interrupt 0
|
||||
/*! \brief Enable single DMA channel's interrupt via DMA_IRQ_0
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel DMA channel
|
||||
@ -480,7 +494,7 @@ static inline void dma_channel_set_irq0_enabled(uint channel, bool enabled) {
|
||||
hw_clear_bits(&dma_hw->inte0, 1u << channel);
|
||||
}
|
||||
|
||||
/*! \brief Enable multiple DMA channels interrupt 0
|
||||
/*! \brief Enable multiple DMA channels' interrupts via DMA_IRQ_0
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
||||
@ -494,7 +508,7 @@ static inline void dma_set_irq0_channel_mask_enabled(uint32_t channel_mask, bool
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Enable single DMA channel interrupt 1
|
||||
/*! \brief Enable single DMA channel's interrupt via DMA_IRQ_1
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel DMA channel
|
||||
@ -509,7 +523,7 @@ static inline void dma_channel_set_irq1_enabled(uint channel, bool enabled) {
|
||||
hw_clear_bits(&dma_hw->inte1, 1u << channel);
|
||||
}
|
||||
|
||||
/*! \brief Enable multiple DMA channels interrupt 0
|
||||
/*! \brief Enable multiple DMA channels' interrupts via DMA_IRQ_1
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
||||
@ -523,6 +537,105 @@ static inline void dma_set_irq1_channel_mask_enabled(uint32_t channel_mask, bool
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Enable single DMA channel interrupt on either DMA_IRQ_0 or DMA_IRQ_1
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||
* \param channel DMA channel
|
||||
* \param enabled true to enable interrupt via irq_index for specified channel, false to disable.
|
||||
*/
|
||||
static inline void dma_irqn_set_channel_enabled(uint irq_index, uint channel, bool enabled) {
|
||||
invalid_params_if(DMA, irq_index > 1);
|
||||
if (irq_index) {
|
||||
dma_channel_set_irq1_enabled(channel, enabled);
|
||||
} else {
|
||||
dma_channel_set_irq0_enabled(channel, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Enable multiple DMA channels' interrupt via either DMA_IRQ_0 or DMA_IRQ_1
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
||||
* \param enabled true to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask.
|
||||
*/
|
||||
static inline void dma_irqn_set_channel_mask_enabled(uint irq_index, uint32_t channel_mask, bool enabled) {
|
||||
invalid_params_if(DMA, irq_index > 1);
|
||||
if (irq_index) {
|
||||
dma_set_irq1_channel_mask_enabled(channel_mask, enabled);
|
||||
} else {
|
||||
dma_set_irq0_channel_mask_enabled(channel_mask, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Determine if a particular channel is a cause of DMA_IRQ_0
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel DMA channel
|
||||
* \return true if the channel is a cause of DMA_IRQ_0, false otherwise
|
||||
*/
|
||||
static inline bool dma_channel_get_irq0_status(uint channel) {
|
||||
check_dma_channel_param(channel);
|
||||
return dma_hw->ints0 & (1u << channel);
|
||||
}
|
||||
|
||||
/*! \brief Determine if a particular channel is a cause of DMA_IRQ_1
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel DMA channel
|
||||
* \return true if the channel is a cause of DMA_IRQ_1, false otherwise
|
||||
*/
|
||||
static inline bool dma_channel_get_irq1_status(uint channel) {
|
||||
check_dma_channel_param(channel);
|
||||
return dma_hw->ints1 & (1u << channel);
|
||||
}
|
||||
|
||||
/*! \brief Determine if a particular channel is a cause of DMA_IRQ_N
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||
* \param channel DMA channel
|
||||
* \return true if the channel is a cause of the DMA_IRQ_N, false otherwise
|
||||
*/
|
||||
static inline bool dma_irqn_get_channel_status(uint irq_index, uint channel) {
|
||||
invalid_params_if(DMA, irq_index > 1);
|
||||
check_dma_channel_param(channel);
|
||||
return (irq_index ? dma_hw->ints1 : dma_hw->ints0) & (1u << channel);
|
||||
}
|
||||
|
||||
/*! \brief Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_0
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel DMA channel
|
||||
*/
|
||||
static inline void dma_channel_acknowledge_irq0(uint channel) {
|
||||
check_dma_channel_param(channel);
|
||||
hw_set_bits(&dma_hw->ints0, (1u << channel));
|
||||
}
|
||||
|
||||
/*! \brief Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_1
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param channel DMA channel
|
||||
*/
|
||||
static inline void dma_channel_acknowledge_irq1(uint channel) {
|
||||
check_dma_channel_param(channel);
|
||||
hw_set_bits(&dma_hw->ints1, (1u << channel));
|
||||
}
|
||||
|
||||
/*! \brief Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_N
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||
* \param channel DMA channel
|
||||
*/
|
||||
static inline void dma_irqn_acknowledge_channel(uint irq_index, uint channel) {
|
||||
invalid_params_if(DMA, irq_index > 1);
|
||||
check_dma_channel_param(channel);
|
||||
hw_set_bits(irq_index ? &dma_hw->ints1 : &dma_hw->ints0, (1u << channel));
|
||||
}
|
||||
|
||||
/*! \brief Check if DMA channel is busy
|
||||
* \ingroup hardware_dma
|
||||
*
|
||||
|
@ -55,7 +55,7 @@ typedef struct {
|
||||
} interp_config;
|
||||
|
||||
static inline uint interp_index(interp_hw_t *interp) {
|
||||
assert(interp == interp0 || interp == interp1);
|
||||
valid_params_if(INTERP, interp == interp0 || interp == interp1);
|
||||
return interp == interp1 ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -70,6 +70,8 @@ static inline uint interp_index(interp_hw_t *interp) {
|
||||
* \param lane The lane number, 0 or 1.
|
||||
*/
|
||||
void interp_claim_lane(interp_hw_t *interp, uint lane);
|
||||
// The above really should be called this for consistency
|
||||
#define interp_lane_claim interp_claim_lane
|
||||
|
||||
/*! \brief Claim the interpolator lanes specified in the mask
|
||||
* \ingroup hardware_interp
|
||||
@ -86,6 +88,19 @@ void interp_claim_lane_mask(interp_hw_t *interp, uint lane_mask);
|
||||
* \param lane The lane number, 0 or 1
|
||||
*/
|
||||
void interp_unclaim_lane(interp_hw_t *interp, uint lane);
|
||||
// The above really should be called this for consistency
|
||||
#define interp_lane_unclaim interp_unclaim_lane
|
||||
|
||||
/*! \brief Determine if an interpolator lane is claimed
|
||||
* \ingroup hardware_interp
|
||||
*
|
||||
* \param interp Interpolator whose lane to check
|
||||
* \param lane The lane number, 0 or 1
|
||||
* \return true if claimed, false otherwise
|
||||
* \see interp_claim_lane
|
||||
* \see interp_claim_lane_mask
|
||||
*/
|
||||
bool interp_lane_is_claimed(interp_hw_t *interp, uint lane);
|
||||
|
||||
/*! \brief Release previously claimed interpolator lanes \see interp_claim_lane_mask
|
||||
* \ingroup hardware_interp
|
||||
|
@ -16,14 +16,13 @@ static_assert(NUM_DMA_CHANNELS <= 16, "");
|
||||
|
||||
static uint8_t _claimed;
|
||||
|
||||
static inline uint interp_get_bit(interp_hw_t *interp, uint lane) {
|
||||
return 1u << ((interp_index(interp) << 1u) | lane);
|
||||
static inline uint interp_lane_bit(interp_hw_t * interp, uint lane) {
|
||||
return (interp_index(interp) << 1u) | lane;
|
||||
}
|
||||
|
||||
void interp_claim_lane(interp_hw_t *interp, uint lane) {
|
||||
valid_params_if(INTERP, lane < 2);
|
||||
uint bit = interp_get_bit(interp, lane);
|
||||
hw_claim_or_assert((uint8_t *) &_claimed, bit, "Lane is already claimed");
|
||||
hw_claim_or_assert((uint8_t *) &_claimed, interp_lane_bit(interp, lane), "Lane is already claimed");
|
||||
}
|
||||
|
||||
void interp_claim_lane_mask(interp_hw_t *interp, uint lane_mask) {
|
||||
@ -34,12 +33,16 @@ void interp_claim_lane_mask(interp_hw_t *interp, uint lane_mask) {
|
||||
|
||||
void interp_unclaim_lane(interp_hw_t *interp, uint lane) {
|
||||
valid_params_if(INTERP, lane < 2);
|
||||
uint bit = interp_get_bit(interp, lane);
|
||||
hw_claim_clear(&_claimed, bit);
|
||||
hw_claim_clear((uint8_t *) &_claimed, interp_lane_bit(interp, lane));
|
||||
}
|
||||
|
||||
bool interp_lane_is_claimed(interp_hw_t *interp, uint lane) {
|
||||
valid_params_if(INTERP, lane < 2);
|
||||
return hw_is_claimed((uint8_t *) &_claimed, interp_lane_bit(interp, lane));
|
||||
}
|
||||
|
||||
void interp_unclaim_lane_mask(interp_hw_t *interp, uint lane_mask) {
|
||||
valid_params_if(INTERP, lane_mask && lane_mask <= 0x3);
|
||||
valid_params_if(INTERP, lane_mask <= 0x3);
|
||||
if (lane_mask & 1u) interp_unclaim_lane(interp, 0);
|
||||
if (lane_mask & 2u) interp_unclaim_lane(interp, 1);
|
||||
}
|
||||
|
@ -111,6 +111,11 @@ static inline void check_sm_param(__unused uint sm) {
|
||||
valid_params_if(PIO, sm < NUM_PIO_STATE_MACHINES);
|
||||
}
|
||||
|
||||
static inline void check_sm_mask(__unused uint mask) {
|
||||
valid_params_if(PIO, mask < (1u << NUM_PIO_STATE_MACHINES));
|
||||
}
|
||||
|
||||
|
||||
static inline void check_pio_param(__unused PIO pio) {
|
||||
valid_params_if(PIO, pio == pio0 || pio == pio1);
|
||||
}
|
||||
@ -554,6 +559,7 @@ static inline void pio_sm_set_enabled(PIO pio, uint sm, bool enabled) {
|
||||
*/
|
||||
static inline void pio_set_sm_mask_enabled(PIO pio, uint32_t mask, bool enabled) {
|
||||
check_pio_param(pio);
|
||||
check_sm_mask(mask);
|
||||
pio->ctrl = (pio->ctrl & ~mask) | (enabled ? mask : 0u);
|
||||
}
|
||||
|
||||
@ -583,6 +589,7 @@ static inline void pio_sm_restart(PIO pio, uint sm) {
|
||||
*/
|
||||
static inline void pio_restart_sm_mask(PIO pio, uint32_t mask) {
|
||||
check_pio_param(pio);
|
||||
check_sm_mask(mask);
|
||||
pio->ctrl |= (mask << PIO_CTRL_SM_RESTART_LSB) & PIO_CTRL_SM_RESTART_BITS;
|
||||
}
|
||||
|
||||
@ -644,6 +651,7 @@ static inline void pio_sm_clkdiv_restart(PIO pio, uint sm) {
|
||||
*/
|
||||
static inline void pio_clkdiv_restart_sm_mask(PIO pio, uint32_t mask) {
|
||||
check_pio_param(pio);
|
||||
check_sm_mask(mask);
|
||||
pio->ctrl |= (mask << PIO_CTRL_CLKDIV_RESTART_LSB) & PIO_CTRL_CLKDIV_RESTART_BITS;
|
||||
}
|
||||
|
||||
@ -660,10 +668,154 @@ static inline void pio_clkdiv_restart_sm_mask(PIO pio, uint32_t mask) {
|
||||
*/
|
||||
static inline void pio_enable_sm_mask_in_sync(PIO pio, uint32_t mask) {
|
||||
check_pio_param(pio);
|
||||
check_sm_mask(mask);
|
||||
pio->ctrl |= ((mask << PIO_CTRL_CLKDIV_RESTART_LSB) & PIO_CTRL_CLKDIV_RESTART_BITS) |
|
||||
((mask << PIO_CTRL_SM_ENABLE_LSB) & PIO_CTRL_SM_ENABLE_BITS);
|
||||
}
|
||||
|
||||
/*! \brief PIO interrupt source numbers for pio related IRQs
|
||||
* \ingroup hardware_pio
|
||||
*/
|
||||
enum pio_interrupt_source {
|
||||
pis_interrupt0 = PIO_INTR_SM0_LSB,
|
||||
pis_interrupt1 = PIO_INTR_SM1_LSB,
|
||||
pis_interrupt2 = PIO_INTR_SM2_LSB,
|
||||
pis_interrupt3 = PIO_INTR_SM3_LSB,
|
||||
pis_sm0_tx_fifo_not_full = PIO_INTR_SM0_TXNFULL_LSB,
|
||||
pis_sm1_tx_fifo_not_full = PIO_INTR_SM1_TXNFULL_LSB,
|
||||
pis_sm2_tx_fifo_not_full = PIO_INTR_SM2_TXNFULL_LSB,
|
||||
pis_sm3_tx_fifo_not_full = PIO_INTR_SM3_TXNFULL_LSB,
|
||||
pis_sm0_rx_fifo_not_empty = PIO_INTR_SM0_RXNEMPTY_LSB,
|
||||
pis_sm1_rx_fifo_not_empty = PIO_INTR_SM1_RXNEMPTY_LSB,
|
||||
pis_sm2_rx_fifo_not_empty = PIO_INTR_SM2_RXNEMPTY_LSB,
|
||||
pis_sm3_rx_fifo_not_empty = PIO_INTR_SM3_RXNEMPTY_LSB,
|
||||
};
|
||||
|
||||
/*! \brief Enable/Disable a single source on a PIO's IRQ 0
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param source the source number (see \ref pio_interrupt_source)
|
||||
* \param enabled true to enable IRQ 0 for the source, false to disable.
|
||||
*/
|
||||
static inline void pio_set_irq0_source_enabled(PIO pio, enum pio_interrupt_source source, bool enabled) {
|
||||
check_pio_param(pio);
|
||||
invalid_params_if(PIO, source >= 12);
|
||||
if (enabled)
|
||||
hw_set_bits(&pio->inte0, 1u << source);
|
||||
else
|
||||
hw_clear_bits(&pio->inte0, 1u << source);
|
||||
}
|
||||
|
||||
/*! \brief Enable/Disable a single source on a PIO's IRQ 1
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param source the source number (see \ref pio_interrupt_source)
|
||||
* \param enabled true to enable IRQ 0 for the source, false to disable.
|
||||
*/
|
||||
static inline void pio_set_irq1_source_enabled(PIO pio, enum pio_interrupt_source source, bool enabled) {
|
||||
check_pio_param(pio);
|
||||
invalid_params_if(PIO, source >= 12);
|
||||
if (enabled)
|
||||
hw_set_bits(&pio->inte1, 1u << source);
|
||||
else
|
||||
hw_clear_bits(&pio->inte1, 1u << source);
|
||||
}
|
||||
|
||||
/*! \brief Enable/Disable multiple sources on a PIO's IRQ 0
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param source_mask Mask of bits, one for each source number (see \ref pio_interrupt_source) to affect
|
||||
* \param enabled true to enable all the sources specified in the mask on IRQ 0, false to disable all the sources specified in the mask on IRQ 0
|
||||
*/
|
||||
static inline void pio_set_irq0_source_mask_enabled(PIO pio, uint32_t source_mask, bool enabled) {
|
||||
check_pio_param(pio);
|
||||
invalid_params_if(PIO, source_mask > PIO_INTR_BITS);
|
||||
if (enabled) {
|
||||
hw_set_bits(&pio->inte0, source_mask);
|
||||
} else {
|
||||
hw_clear_bits(&pio->inte0, source_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Enable/Disable multiple sources on a PIO's IRQ 1
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param source_mask Mask of bits, one for each source number (see \ref pio_interrupt_source) to affect
|
||||
* \param enabled true to enable all the sources specified in the mask on IRQ 1, false to disable all the source specified in the mask on IRQ 1
|
||||
*/
|
||||
static inline void pio_set_irq1_source_mask_enabled(PIO pio, uint32_t source_mask, bool enabled) {
|
||||
check_pio_param(pio);
|
||||
invalid_params_if(PIO, source_mask > PIO_INTR_BITS);
|
||||
if (enabled) {
|
||||
hw_set_bits(&pio->inte1, source_mask);
|
||||
} else {
|
||||
hw_clear_bits(&pio->inte1, source_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Enable/Disable a single source on a PIO's specified (0/1) IRQ index
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param irq_index the IRQ index; either 0 or 1
|
||||
* \param source the source number (see \ref pio_interrupt_source)
|
||||
* \param enabled true to enable the source on the specified IRQ, false to disable.
|
||||
*/
|
||||
static inline void pio_set_irqn_source_enabled(PIO pio, uint irq_index, enum pio_interrupt_source source, bool enabled) {
|
||||
invalid_params_if(PIO, irq_index > 1);
|
||||
if (irq_index) {
|
||||
pio_set_irq1_source_enabled(pio, source, enabled);
|
||||
} else {
|
||||
pio_set_irq0_source_enabled(pio, source, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Enable/Disable multiple sources on a PIO's specified (0/1) IRQ index
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param irq_index the IRQ index; either 0 or 1
|
||||
* \param source_mask Mask of bits, one for each source number (see \ref pio_interrupt_source) to affect
|
||||
* \param enabled true to enable all the sources specified in the mask on the specified IRQ, false to disable all the sources specified in the mask on the specified IRQ
|
||||
*/
|
||||
static inline void pio_set_irqn_source_mask_enabled(PIO pio, uint irq_index, uint32_t source_mask, bool enabled) {
|
||||
invalid_params_if(PIO, irq_index > 1);
|
||||
if (irq_index) {
|
||||
pio_set_irq0_source_mask_enabled(pio, source_mask, enabled);
|
||||
} else {
|
||||
pio_set_irq1_source_mask_enabled(pio, source_mask, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Determine if a particular PIO interrupt is set
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param pio_interrupt_num the PIO interrupt number 0-7
|
||||
* \return true if corresponding PIO interrupt is currently set
|
||||
*/
|
||||
static inline bool pio_interrupt_get(PIO pio, uint pio_interrupt_num) {
|
||||
check_pio_param(pio);
|
||||
invalid_params_if(PIO, pio_interrupt_num >= 8);
|
||||
return pio->irq & (1u << pio_interrupt_num);
|
||||
}
|
||||
|
||||
/*! \brief Clear a particular PIO interrupt
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param pio_interrupt_num the PIO interrupt number 0-7
|
||||
*/
|
||||
static inline void pio_interrupt_clear(PIO pio, uint pio_interrupt_num) {
|
||||
check_pio_param(pio);
|
||||
invalid_params_if(PIO, pio_interrupt_num >= 8);
|
||||
hw_set_bits(&pio->irq, (1u << pio_interrupt_num));
|
||||
}
|
||||
|
||||
/*! \brief Return the current program counter for a state machine
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
@ -1136,6 +1288,17 @@ void pio_sm_unclaim(PIO pio, uint sm);
|
||||
*/
|
||||
int pio_claim_unused_sm(PIO pio, bool required);
|
||||
|
||||
/*! \brief Determine if a PIO state machine is claimed
|
||||
* \ingroup hardware_pio
|
||||
*
|
||||
* \param pio The PIO instance; either \ref pio0 or \ref pio1
|
||||
* \param sm State machine index (0..3)
|
||||
* \return true if claimed, false otherwise
|
||||
* \see pio_sm_claim
|
||||
* \see pio_claim_sm_mask
|
||||
*/
|
||||
bool pio_sm_is_claimed(PIO pio, uint sm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -35,6 +35,7 @@ void pio_claim_sm_mask(PIO pio, uint sm_mask) {
|
||||
if (sm_mask & 1u) pio_sm_claim(pio, i);
|
||||
}
|
||||
}
|
||||
|
||||
void pio_sm_unclaim(PIO pio, uint sm) {
|
||||
check_sm_param(sm);
|
||||
uint which = pio_get_index(pio);
|
||||
@ -50,6 +51,12 @@ int pio_claim_unused_sm(PIO pio, bool required) {
|
||||
return index >= (int)base ? index - (int)base : -1;
|
||||
}
|
||||
|
||||
bool pio_sm_is_claimed(PIO pio, uint sm) {
|
||||
check_sm_param(sm);
|
||||
uint which = pio_get_index(pio);
|
||||
return hw_is_claimed(&claimed, which * NUM_PIO_STATE_MACHINES + sm);
|
||||
}
|
||||
|
||||
static_assert(PIO_INSTRUCTION_COUNT <= 32, "");
|
||||
static uint32_t _used_instruction_space[2];
|
||||
|
||||
|
@ -384,6 +384,16 @@ void spin_lock_unclaim(uint lock_num);
|
||||
*/
|
||||
int spin_lock_claim_unused(bool required);
|
||||
|
||||
/*! \brief Determine if a spin lock is claimed
|
||||
* \ingroup hardware_sync
|
||||
*
|
||||
* \param lock_num the spin lock number
|
||||
* \return true if claimed, false otherwise
|
||||
* \see spin_lock_claim
|
||||
* \see spin_lock_claim_mask
|
||||
*/
|
||||
bool spin_lock_is_claimed(uint lock_num);
|
||||
|
||||
#define remove_volatile_cast(t, x) ({__mem_fence_acquire(); (t)(x); })
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -57,3 +57,8 @@ int spin_lock_claim_unused(bool required) {
|
||||
return hw_claim_unused_from_range((uint8_t*)&claimed, required, PICO_SPINLOCK_ID_CLAIM_FREE_FIRST, PICO_SPINLOCK_ID_CLAIM_FREE_LAST, "No spinlocks are available");
|
||||
}
|
||||
|
||||
bool spin_lock_is_claimed(uint lock_num) {
|
||||
check_lock_num(lock_num);
|
||||
return hw_is_claimed((uint8_t *) &claimed, lock_num);
|
||||
}
|
||||
|
||||
|
@ -144,6 +144,15 @@ void hardware_alarm_claim(uint alarm_num);
|
||||
*/
|
||||
void hardware_alarm_unclaim(uint alarm_num);
|
||||
|
||||
/*! \brief Determine if a hardware alarm has been claimed
|
||||
* \ingroup hardware_timer
|
||||
*
|
||||
* \param alarm_num the hardware alarm number
|
||||
* \return true if claimed, false otherwise
|
||||
* \see hardware_alarm_claim
|
||||
*/
|
||||
bool hardware_alarm_is_claimed(uint alarm_num);
|
||||
|
||||
/*! \brief Enable/Disable a callback for a hardware timer on this core
|
||||
* \ingroup hardware_timer
|
||||
*
|
||||
|
@ -28,6 +28,11 @@ void hardware_alarm_unclaim(uint alarm_num) {
|
||||
hw_claim_clear(&claimed, alarm_num);
|
||||
}
|
||||
|
||||
bool hardware_alarm_is_claimed(uint alarm_num) {
|
||||
check_hardware_alarm_num_param(alarm_num);
|
||||
return hw_is_claimed(&claimed, alarm_num);
|
||||
}
|
||||
|
||||
/// tag::time_us_64[]
|
||||
uint64_t time_us_64() {
|
||||
// Need to make sure that the upper 32 bits of the timer
|
||||
|
@ -34,6 +34,7 @@ wrapper_func __aeabi_f2iz
|
||||
wrapper_func __aeabi_f2lz
|
||||
wrapper_func __aeabi_f2uiz
|
||||
wrapper_func __aeabi_f2ulz
|
||||
wrapper_func __aeabi_f2d
|
||||
wrapper_func sqrtf
|
||||
wrapper_func cosf
|
||||
wrapper_func sinf
|
||||
|
@ -10,7 +10,11 @@
|
||||
|
||||
#include "pico/asm_helper.S"
|
||||
|
||||
#if PICO_INT64_OPS_IN_RAM
|
||||
.section RAM_SECTION_NAME(__aeabi_lmul)
|
||||
#else
|
||||
.section SECTION_NAME(__aeabi_lmul)
|
||||
#endif
|
||||
wrapper_func __aeabi_lmul
|
||||
muls r1, r2
|
||||
muls r3, r0
|
||||
|
@ -6,7 +6,7 @@ if (NOT TARGET pico_multicore)
|
||||
|
||||
target_include_directories(pico_multicore INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
|
||||
target_link_libraries(pico_multicore INTERFACE pico_sync)
|
||||
target_link_libraries(pico_multicore INTERFACE pico_sync hardware_irq)
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "hardware/irq.h"
|
||||
|
Loading…
Reference in New Issue
Block a user