void loop(void) { toggleLED(); delay(100); dma_channel_reg_map *ch_regs = dma_channel_regs(USART_DMA_DEV, USART_RX_DMA_CHANNEL); if (irq_fired) { USART_HWSER.println("** IRQ **"); while (true) ; } USART_HWSER.print("["); USART_HWSER.print(millis()); USART_HWSER.print("]\tISR bits: 0x"); uint8 isr_bits = dma_get_isr_bits(USART_DMA_DEV, USART_RX_DMA_CHANNEL); USART_HWSER.print((int32)isr_bits, HEX); USART_HWSER.print("\tCCR: 0x"); USART_HWSER.print((int64)ch_regs->CCR, HEX); USART_HWSER.print("\tCNDTR: 0x"); USART_HWSER.print((int64)ch_regs->CNDTR, HEX); USART_HWSER.print("\tBuffer contents: "); for (int i = 0; i < BUF_SIZE; i++) { USART_HWSER.print('\''); USART_HWSER.print(rx_buf[i]); USART_HWSER.print('\''); if (i < BUF_SIZE - 1) USART_HWSER.print(", "); } USART_HWSER.println(); if (isr_bits == 0x7) { USART_HWSER.println("** Clearing ISR bits."); dma_clear_isr_bits(USART_DMA_DEV, USART_RX_DMA_CHANNEL); } irq_fired = 0; }
void dma_set_per_addr(dma_dev *dev, dma_channel channel, volatile void *addr) { dma_channel_reg_map *chan_regs; ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); chan_regs = dma_channel_regs(dev, channel); chan_regs->CPAR = (uint32)addr; }
/** * @brief Set the base memory address where data will be read from or * written to. * * You must not call this function while the channel is enabled. * * If the DMA memory size is 16 bits, the address is automatically * aligned to a half-word. If the DMA memory size is 32 bits, the * address is aligned to a word. * * @param dev DMA Device * @param channel Channel whose base memory address to set. * @param addr Memory base address to use. */ void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) { dma_channel_reg_map *chan_regs; ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); chan_regs = dma_channel_regs(dev, channel); chan_regs->CMAR = (uint32)addr; }
void dma_set_num_transfers(dma_dev *dev, dma_channel channel, uint16 num_transfers) { dma_channel_reg_map *channel_regs; ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); channel_regs = dma_channel_regs(dev, channel); channel_regs->CNDTR = num_transfers; }
void dma_set_priority(dma_dev *dev, dma_channel channel, dma_priority priority) { dma_channel_reg_map *channel_regs; uint32 ccr; ASSERT_FAULT(!dma_is_channel_enabled(dev, channel)); channel_regs = dma_channel_regs(dev, channel); ccr = channel_regs->CCR; ccr &= ~DMA_CCR_PL; ccr |= (priority << 12); channel_regs->CCR = ccr; }
/** * @brief Set up a DMA transfer. * * The channel will be disabled before being reconfigured. The * transfer will have low priority by default. You may choose another * priority before the transfer begins using dma_set_priority(), as * well as performing any other configuration you desire. When the * channel is configured to your liking, enable it using dma_enable(). * * @param dev DMA device. * @param channel DMA channel. * @param peripheral_address Base address of peripheral data register * involved in the transfer. * @param peripheral_size Peripheral data transfer size. * @param memory_address Base memory address involved in the transfer. * @param memory_size Memory data transfer size. * @param mode Logical OR of dma_mode_flags * @sideeffect Disables the given DMA channel. * @see dma_xfer_size * @see dma_mode_flags * @see dma_set_num_transfers() * @see dma_set_priority() * @see dma_attach_interrupt() * @see dma_enable() */ void dma_setup_transfer(dma_dev *dev, dma_channel channel, __io void *peripheral_address, dma_xfer_size peripheral_size, __io void *memory_address, dma_xfer_size memory_size, uint32 mode) { dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel); dma_disable(dev, channel); /* can't write to CMAR/CPAR otherwise */ channel_regs->CCR = (memory_size << 10) | (peripheral_size << 8) | mode; channel_regs->CMAR = (uint32)memory_address; channel_regs->CPAR = (uint32)peripheral_address; }
void dma_disable(dma_dev *dev, dma_channel channel) { dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel); bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0); }
void dma_detach_interrupt(dma_dev *dev, dma_channel channel) { /* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */ dma_channel_regs(dev, channel)->CCR &= ~0xF; DMA_GET_HANDLER(dev, channel) = NULL; }
/** * @brief Detach a DMA transfer interrupt handler. * * After calling this function, the given channel's interrupts will be * disabled. * * @param dev DMA device * @param channel Channel whose handler to detach * @sideeffect Clears interrupt enable bits in the channel's CCR register. * @see dma_attach_interrupt() */ void dma_detach_interrupt(dma_dev *dev, dma_channel channel) { /* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */ dma_channel_regs(dev, channel)->CCR &= ~0xF; dev->handlers[channel - 1].handler = NULL; }