add dma_timer related methods (#604)

This commit is contained in:
Graham Sanderson 2021-10-12 09:04:59 -05:00 committed by GitHub
parent 9f1c37318b
commit e76d5a9008
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 0 deletions

View File

@ -19,6 +19,7 @@
#define NUM_CORES _u(2) #define NUM_CORES _u(2)
#define NUM_DMA_CHANNELS _u(12) #define NUM_DMA_CHANNELS _u(12)
#define NUM_DMA_TIMERS _u(4)
#define NUM_IRQS _u(32) #define NUM_IRQS _u(32)
#define NUM_PIOS _u(2) #define NUM_PIOS _u(2)
#define NUM_PIO_STATE_MACHINES _u(4) #define NUM_PIO_STATE_MACHINES _u(4)

View File

@ -18,6 +18,7 @@ static_assert(__builtin_offsetof(dma_hw_t, ch[1].ctrl_trig) == DMA_CH1_CTRL_TRIG
static_assert(NUM_DMA_CHANNELS <= 16, ""); static_assert(NUM_DMA_CHANNELS <= 16, "");
static uint16_t _claimed; static uint16_t _claimed;
static uint8_t _timer_claimed;
void dma_channel_claim(uint channel) { void dma_channel_claim(uint channel) {
check_dma_channel_param(channel); check_dma_channel_param(channel);
@ -44,6 +45,25 @@ bool dma_channel_is_claimed(uint channel) {
return hw_is_claimed((uint8_t *) &_claimed, channel); return hw_is_claimed((uint8_t *) &_claimed, channel);
} }
void dma_timer_claim(uint timer) {
check_dma_timer_param(timer);
hw_claim_or_assert(&_timer_claimed, timer, "DMA timer %d is already claimed");
}
void dma_timer_unclaim(uint timer) {
check_dma_timer_param(timer);
hw_claim_clear(&_timer_claimed, timer);
}
int dma_claim_unused_timer(bool required) {
return hw_claim_unused_from_range(&_timer_claimed, required, 0, NUM_DMA_TIMERS-1, "No DMA timers are available");
}
bool dma_timer_is_claimed(uint timer) {
check_dma_timer_param(timer);
return hw_is_claimed(&_timer_claimed, timer);
}
#ifndef NDEBUG #ifndef NDEBUG
void print_dma_ctrl(dma_channel_hw_t *channel) { void print_dma_ctrl(dma_channel_hw_t *channel) {

View File

@ -54,6 +54,10 @@ static inline void check_dma_channel_param(__unused uint channel) {
#endif #endif
} }
static inline void check_dma_timer_param(__unused uint timer_num) {
valid_params_if(DMA, timer_num < NUM_DMA_TIMERS);
}
inline static dma_channel_hw_t *dma_channel_hw_addr(uint channel) { inline static dma_channel_hw_t *dma_channel_hw_addr(uint channel) {
check_dma_channel_param(channel); check_dma_channel_param(channel);
return &dma_hw->ch[channel]; return &dma_hw->ch[channel];
@ -715,6 +719,71 @@ inline static void dma_sniffer_disable(void) {
dma_hw->sniff_ctrl = 0; dma_hw->sniff_ctrl = 0;
} }
/*! \brief Mark a dma timer as used
* \ingroup hardware_dma
*
* Method for cooperative claiming of hardware. Will cause a panic if the timer
* is already claimed. Use of this method by libraries detects accidental
* configurations that would fail in unpredictable ways.
*
* \param timer the dma timer
*/
void dma_timer_claim(uint timer);
/*! \brief Mark a dma timer as no longer used
* \ingroup hardware_dma
*
* Method for cooperative claiming of hardware.
*
* \param timer the dma timer to release
*/
void dma_timer_unclaim(uint timer);
/*! \brief Claim a free dma timer
* \ingroup hardware_dma
*
* \param required if true the function will panic if none are available
* \return the dma timer number or -1 if required was false, and none were free
*/
int dma_claim_unused_timer(bool required);
/*! \brief Determine if a dma timer is claimed
* \ingroup hardware_dma
*
* \param timer the dma timer
* \return true if the timer is claimed, false otherwise
* \see dma_timer_claim
*/
bool dma_timer_is_claimed(uint timer);
/*! \brief Set the divider for the given DMA timer
* \ingroup hardware_dma
*
* The timer will run at the system_clock_freq * numerator / denominator, so this is the speed
* that data elements will be transferred at via a DMA channel using this timer as a DREQ
*
* \param timer the dma timer
* \param numerator the fraction's numerator
* \param denominator the fraction's denominator
*/
static inline void dma_timer_set_fraction(uint timer, uint16_t numerator, uint16_t denominator) {
check_dma_timer_param(timer);
dma_hw->timer[timer] = (((uint32_t)numerator) << DMA_TIMER0_X_LSB) | (((uint32_t)denominator) << DMA_TIMER0_Y_LSB);
}
/*! \brief Return the DREQ number for a given DMA timer
* \ingroup hardware_dma
*
* \param timer DMA timer number 0-3
*/
static inline uint dma_get_timer_dreq(uint timer_num) {
static_assert(DREQ_DMA_TIMER1 == DREQ_DMA_TIMER0 + 1, "");
static_assert(DREQ_DMA_TIMER2 == DREQ_DMA_TIMER0 + 2, "");
static_assert(DREQ_DMA_TIMER3 == DREQ_DMA_TIMER0 + 3, "");
check_dma_timer_param(timer_num);
return DREQ_DMA_TIMER0 + timer_num;
}
#ifndef NDEBUG #ifndef NDEBUG
void print_dma_ctrl(dma_channel_hw_t *channel); void print_dma_ctrl(dma_channel_hw_t *channel);
#endif #endif