add dma_timer related methods (#604)
This commit is contained in:
		@ -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)
 | 
				
			||||||
 | 
				
			|||||||
@ -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) {
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user