/** * \brief DMAC driver configuration. */ static void configure_dmac(void) { uint32_t ul_cfg; /* Initialize and enable DMA controller. */ pmc_enable_periph_clk(ID_DMAC); dmac_init(DMAC); dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN); dmac_enable(DMAC); /* Configure DMA RX channel. */ ul_cfg = 0; ul_cfg |= DMAC_CFG_SRC_PER(AES_DMA_RX_IDX) | DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG; dmac_channel_set_configuration(DMAC, AES_DMA_RX_CH, ul_cfg); /* Configure DMA TX channel. */ ul_cfg = 0; ul_cfg |= DMAC_CFG_DST_PER(AES_DMA_TX_IDX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG; dmac_channel_set_configuration(DMAC, AES_DMA_TX_CH, ul_cfg); /* Enable receive channel interrupt for DMAC. */ NVIC_EnableIRQ(DMAC_IRQn); dmac_enable_interrupt(DMAC, (DMAC_EBCIER_BTC0 << AES_DMA_RX_CH)); }
/** * \brief DMAC tx channel configuration. */ static void configure_dmac_tx(void) { uint32_t ul_cfg; dma_transfer_descriptor_t dmac_trans; ul_cfg = 0; ul_cfg |= DMAC_CFG_DST_PER(USART_TX_IDX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD_ENABLE | DMAC_CFG_FIFOCFG_ALAP_CFG; dmac_channel_set_configuration(DMAC, BOARD_USART_DMAC_TX_CH, ul_cfg); dmac_channel_disable(DMAC, BOARD_USART_DMAC_TX_CH); dmac_trans.ul_source_addr = (uint32_t) gs_puc_buffer; dmac_trans.ul_destination_addr = (uint32_t) & BOARD_USART->US_THR; dmac_trans.ul_ctrlA = DMAC_CTRLA_BTSIZE(BUFFER_SIZE) | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE; dmac_trans.ul_ctrlB = DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING | DMAC_CTRLB_DST_INCR_FIXED; dmac_trans.ul_descriptor_addr = 0; dmac_channel_single_buf_transfer_init(DMAC, BOARD_USART_DMAC_TX_CH, &dmac_trans); dmac_channel_enable(DMAC, BOARD_USART_DMAC_TX_CH); }
/** * \brief DMA driver configuration */ static void init_dma(void) { uint32_t cfg; /* Enable DMA controller */ dmac_enable(DMAC); /* Initialize and enable DMA controller */ pmc_enable_periph_clk(ID_DMAC); dmac_init(DMAC); dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN); dmac_enable(DMAC); /* Disable the DMA channel for SSC */ dmac_channel_disable(DMAC, DMA_CH); /* Set channel configuration register */ cfg = DMAC_CFG_SOD_ENABLE | /* Enable stop on done */ DMAC_CFG_DST_H2SEL | /* Hardware Selection for the Destination */ DMAC_CFG_DST_PER(3) | /* Destination with Peripheral identifier */ DMAC_CFG_AHB_PROT(1) | /* Set AHB Protection */ DMAC_CFG_FIFOCFG_ALAP_CFG; /* FIFO Configuration */ dmac_channel_set_configuration(DMAC, DMA_CH, cfg); /* Set interrupt */ NVIC_EnableIRQ(DMAC_IRQn); dmac_enable_interrupt(DMAC, (DMAC_EBCIER_CBTC0 << DMA_CH)); }
/** * \brief Configure the DMA Channels. * Channels are disabled after configure. * \returns 0 if the dma channel configuration successfully; otherwise returns * NandCommon_ERROR_XXX. */ uint8_t NandFlashConfigureDmaChannels( sDmad *pDmad ) { uint32_t dwCfg; /* Configure the allocated DMA channel. */ dwCfg = 0 | DMAC_CFG_SRC_PER( 0 ) | DMAC_CFG_DST_PER( 0 ) | DMAC_CFG_FIFOCFG_HALF_CFG; /* Allocate a DMA channel for NAND RX. */ nandDmaRxChannel = DMAD_AllocateChannel( pDmad, DMAD_TRANSFER_MEMORY, DMAD_TRANSFER_MEMORY); { if ( nandDmaRxChannel == DMAD_ALLOC_FAILED ) { return NandCommon_ERROR_DMA; } } if (DMAD_PrepareChannel( pDmad, nandDmaRxChannel, dwCfg )) return NandCommon_ERROR_DMA; dmaNandRxDesc.dwSrcAddr = 0; dmaNandRxDesc.dwDstAddr = 0; dmaNandRxDesc.dwCtrlA = 0; dmaNandRxDesc.dwCtrlB = DMAC_CTRLB_SIF_AHB_IF1 | DMAC_CTRLB_DIF_AHB_IF0 | DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2MEM_DMA_FC | DMAC_CTRLB_SRC_INCR_FIXED | DMAC_CTRLB_DST_INCR_INCREMENTING; if (DMAD_PrepareSingleTransfer( pDmad, nandDmaRxChannel, &dmaNandRxDesc )) return NandCommon_ERROR_DMA; /* Allocate a DMA channel for NAND TX. */ nandDmaTxChannel = DMAD_AllocateChannel( pDmad, DMAD_TRANSFER_MEMORY, DMAD_TRANSFER_MEMORY); { if ( nandDmaTxChannel == DMAD_ALLOC_FAILED ) { return NandCommon_ERROR_DMA; } } if (DMAD_PrepareChannel( pDmad, nandDmaTxChannel, dwCfg )) return NandCommon_ERROR_DMA; dmaNandTxDesc.dwSrcAddr = 0; dmaNandTxDesc.dwDstAddr = 0; dmaNandTxDesc.dwCtrlA = 0; dmaNandTxDesc.dwCtrlB = DMAC_CTRLB_SIF_AHB_IF1 | DMAC_CTRLB_DIF_AHB_IF0 | DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2MEM_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING | DMAC_CTRLB_DST_INCR_FIXED; if (DMAD_PrepareSingleTransfer( pDmad, nandDmaTxChannel, &dmaNandTxDesc )) return NandCommon_ERROR_DMA; pCurrentDma = pDmad; return 0; }
void spi_start_transmit_dma(Dmac *p_dmac, Spi *p_spi, uint32_t ul_num, const void *src, uint32_t nb_bytes) { static uint8_t ff = 0xFF; uint32_t cfg, src_incr = DMAC_CTRLB_SRC_INCR_INCREMENTING; dma_transfer_descriptor_t desc; // Send 0xFF repeatedly if src is NULL if (!src) { src = &ff; src_incr = DMAC_CTRLB_SRC_INCR_FIXED; } // Disable the DMA channel prior to configuring dmac_enable(p_dmac); dmac_channel_disable(p_dmac, ul_num); cfg = DMAC_CFG_SOD | DMAC_CFG_DST_H2SEL | DMAC_CFG_DST_PER(SPI_TX_IDX) | DMAC_CFG_FIFOCFG_ALAP_CFG; dmac_channel_set_configuration(p_dmac, ul_num, cfg); // Prepare DMA transfer desc.ul_source_addr = (uint32_t)src; desc.ul_destination_addr = (uint32_t)&(p_spi->SPI_TDR); desc.ul_ctrlA = DMAC_CTRLA_BTSIZE(nb_bytes) | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE; desc.ul_ctrlB = DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC | src_incr | DMAC_CTRLB_DST_INCR_FIXED; // Next field is ignored, but set it anyway desc.ul_descriptor_addr = (uint32_t)NULL; // Finish configuring the transfer dmac_channel_single_buf_transfer_init(p_dmac, ul_num, &desc); // And now start the DMA transfer dmac_channel_enable(p_dmac, ul_num); }
void ledUpdate(void){ volatile uint16_t* row_data; unsigned i; gpioSetVal(blanks[row], 1); if(++row == NUM_ROWS) row = 0; row_data = led_buffer + XFERS_PER_ROW * row; DMAC->DMAC_CH_NUM[DMA_CHANNEL_LEDS].DMAC_SADDR = (uint32_t)row_data; DMAC->DMAC_CH_NUM[DMA_CHANNEL_LEDS].DMAC_DADDR = (uint32_t)&SPI0->SPI_TDR; DMAC->DMAC_CH_NUM[DMA_CHANNEL_LEDS].DMAC_DSCR = 0; DMAC->DMAC_CH_NUM[DMA_CHANNEL_LEDS].DMAC_CTRLA = DMAC_CTRLA_BTSIZE(XFERS_PER_ROW) | DMAC_CTRLA_SCSIZE_CHK_16 | DMAC_CTRLA_DCSIZE_CHK_1 | DMAC_CTRLA_SRC_WIDTH_HALF_WORD | DMAC_CTRLA_DST_WIDTH_HALF_WORD; DMAC->DMAC_CH_NUM[DMA_CHANNEL_LEDS].DMAC_CTRLB = DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING | DMAC_CTRLB_DST_INCR_FIXED; DMAC->DMAC_CH_NUM[DMA_CHANNEL_LEDS].DMAC_CFG = DMAC_CFG_DST_PER(1) | DMAC_CFG_SRC_PER(1) | DMAC_CFG_DST_H2SEL_HW | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG; DMAC->DMAC_CHER = (1 << DMA_CHANNEL_LEDS); //wait for transfer to start while(SPI0->SPI_SR & SPI_SR_TXEMPTY); SPI0->SPI_IER = SPI_IER_TXEMPTY; }
//------------------------------------------------------------------------------ // start TX DMA static void spiDmaTX(const uint8_t* src, uint16_t count) { static uint8_t ff = 0XFF; uint32_t src_incr = DMAC_CTRLB_SRC_INCR_INCREMENTING; if (!src) { src = &ff; src_incr = DMAC_CTRLB_SRC_INCR_FIXED; } dmac_channel_disable(SPI_DMAC_TX_CH); DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_SADDR = (uint32_t)src; DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DADDR = (uint32_t)&SPI0->SPI_TDR; DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DSCR = 0; DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLA = count | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE; DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC | src_incr | DMAC_CTRLB_DST_INCR_FIXED; DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CFG = DMAC_CFG_DST_PER(SPI_TX_IDX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG; dmac_channel_enable(SPI_DMAC_TX_CH); }
/* * Configure the SPI hardware, including SPI clock speed, mode, delays, chip select pins * It uses values listed in */ void AJ_WSL_SPI_InitializeSPIController(void) { uint32_t config; /* Initialize and enable DMA controller. */ pmc_enable_periph_clk(ID_DMAC); dmac_init(DMAC); dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN); dmac_enable(DMAC); /* Configure DMA TX channel. */ config = 0; config |= DMAC_CFG_DST_PER(AJ_SPI_TX_INDEX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG; dmac_channel_set_configuration(DMAC, AJ_DMA_TX_CHANNEL, config); /* Configure DMA RX channel. */ config = 0; config |= DMAC_CFG_SRC_PER(AJ_SPI_RX_INDEX) | DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG; dmac_channel_set_configuration(DMAC, AJ_DMA_RX_CHANNEL, config); /* Enable receive channel interrupt for DMAC. */ uint8_t* interruptEnableAddress = AJ_SPI_ISER1_IEN_ADDR; *interruptEnableAddress = AJ_SPI_DMAC_IEN_BIT; dmac_enable_interrupt(DMAC, (1 << AJ_DMA_RX_CHANNEL)); dmac_enable_interrupt(DMAC, (1 << AJ_DMA_TX_CHANNEL)); //AJ_WSL_DMA_Setup(); dmac_channel_disable(DMAC, AJ_DMA_TX_CHANNEL); dmac_channel_disable(DMAC, AJ_DMA_RX_CHANNEL); /* * Configure the hardware to enable SPI and some output pins */ { pmc_enable_periph_clk(ID_PIOA); pmc_enable_periph_clk(ID_PIOB); pmc_enable_periph_clk(ID_PIOC); pmc_enable_periph_clk(ID_PIOD); // make all of these pins controlled by the right I/O controller pio_configure_pin_group(PIOA, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_A); pio_configure_pin_group(PIOB, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_B); pio_configure_pin_group(PIOC, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_C); pio_configure_pin_group(PIOD, 0xFFFFFFFF, PIO_TYPE_PIO_PERIPH_D); /* * Reset the device by toggling the CHIP_POWER */ ioport_set_pin_dir(AJ_WSL_SPI_CHIP_POWER_PIN, IOPORT_DIR_OUTPUT); ioport_set_pin_level(AJ_WSL_SPI_CHIP_POWER_PIN, IOPORT_PIN_LEVEL_LOW); AJ_Sleep(10); ioport_set_pin_level(AJ_WSL_SPI_CHIP_POWER_PIN, IOPORT_PIN_LEVEL_HIGH); /* * Reset the device by toggling the CHIP_PWD# signal */ ioport_set_pin_dir(AJ_WSL_SPI_CHIP_PWD_PIN, IOPORT_DIR_OUTPUT); ioport_set_pin_level(AJ_WSL_SPI_CHIP_PWD_PIN, IOPORT_PIN_LEVEL_LOW); AJ_Sleep(10); ioport_set_pin_level(AJ_WSL_SPI_CHIP_PWD_PIN, IOPORT_PIN_LEVEL_HIGH); /* configure the pin that detects SPI data ready from the target chip */ ioport_set_pin_dir(AJ_WSL_SPI_CHIP_SPI_INT_PIN, IOPORT_DIR_INPUT); ioport_set_pin_sense_mode(AJ_WSL_SPI_CHIP_SPI_INT_PIN, IOPORT_SENSE_LEVEL_LOW); pio_handler_set(PIOC, ID_PIOC, AJ_WSL_SPI_CHIP_SPI_INT_BIT, (PIO_PULLUP | PIO_IT_FALL_EDGE), &AJ_WSL_SPI_CHIP_SPI_ISR); pio_handler_set_priority(PIOD, (IRQn_Type) ID_PIOC, 0xB); pio_enable_interrupt(PIOC, AJ_WSL_SPI_CHIP_SPI_INT_BIT); } spi_enable_clock(AJ_WSL_SPI_DEVICE); spi_reset(AJ_WSL_SPI_DEVICE); spi_set_lastxfer(AJ_WSL_SPI_DEVICE); spi_set_master_mode(AJ_WSL_SPI_DEVICE); spi_disable_mode_fault_detect(AJ_WSL_SPI_DEVICE); spi_set_peripheral_chip_select_value(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS); spi_set_clock_polarity(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, AJ_WSL_SPI_CLOCK_POLARITY); spi_set_clock_phase(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, AJ_WSL_SPI_CLOCK_PHASE); spi_set_bits_per_transfer(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, SPI_CSR_BITS_8_BIT); spi_set_baudrate_div(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, (sysclk_get_cpu_hz() / AJ_WSL_SPI_CLOCK_RATE)); spi_set_transfer_delay(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, AJ_WSL_SPI_DELAY_BEFORE_CLOCK, AJ_WSL_SPI_DELAY_BETWEEN_TRANSFERS); spi_set_fixed_peripheral_select(AJ_WSL_SPI_DEVICE); spi_configure_cs_behavior(AJ_WSL_SPI_DEVICE, AJ_WSL_SPI_DEVICE_NPCS, SPI_CS_RISE_FORCED); spi_enable_interrupt(AJ_WSL_SPI_DEVICE, SPI_IER_TDRE | SPI_IER_RDRF); spi_enable(AJ_WSL_SPI_DEVICE); }