/** \brief configure the DMA peripheral \param[in] none \param[out] none \retval none */ void dma_config(void) { dma_parameter_struct dma_init_struct; /* enable DMA clock */ rcu_periph_clock_enable(RCU_DMA); /* initialize DMA channel4 */ dma_deinit(DMA_CH4); /* DMA channel4 initialize */ dma_deinit(DMA_CH4); dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERA; dma_init_struct.memory_addr = (uint32_t)buffer; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT; dma_init_struct.number = 8; dma_init_struct.periph_addr = (uint32_t)TIMER0_DMATB; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA_CH4,dma_init_struct); /* configure DMA mode */ dma_circulation_enable(DMA_CH4); dma_memory_to_memory_disable(DMA_CH4); /* enable DMA channel4 */ dma_channel_enable(DMA_CH4); }
mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { // check that src pointer is aligned on a 4-byte boundary if (((uint32_t)src & 3) != 0) { return SD_ERROR; } // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; if (query_irq() == IRQ_STATE_ENABLED) { dma_init(&sd_tx_dma, DMA_STREAM_SDIO_TX, &dma_init_struct_sdio, DMA_CHANNEL_SDIO_TX, DMA_MEMORY_TO_PERIPH, &sd_handle); sd_handle.hdmatx = &sd_tx_dma; err = HAL_SD_WriteBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckWriteOperation(&sd_handle, 100000000); } dma_deinit(sd_handle.hdmatx); sd_handle.hdmatx = NULL; } else { err = HAL_SD_WriteBlocks_BlockNumber(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks); } return err; }
mp_uint_t sdcard_read_blocks(uint8_t *buff, uint32_t sector, uint32_t count) { HAL_SD_ErrorTypedef err; // If buffer is unaligned or located in CCM don't use DMA. if (CCM_BUFFER(buff) || UNALIGNED_BUFFER(buff)) { if (UNALIGNED_BUFFER(buff)) { printf("unaligned read buf:%p count%lu \n", buff, count); } // This transfer has to be done in an atomic section. mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); err = HAL_SD_ReadBlocks(&SDHandle, (uint32_t*)buff, sector * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE, count); MICROPY_END_ATOMIC_SECTION(atomic_state); } else { // Disable USB IRQ to prevent FatFS/MSC contention HAL_NVIC_DisableIRQ(OTG_FS_IRQn); __DSB(); __ISB(); dma_init(SDIO_TXRX_STREAM, SDIO_TXRX_CHANNEL, DMA_PERIPH_TO_MEMORY); err = HAL_SD_ReadBlocks_DMA(&SDHandle, (uint32_t*)buff, sector * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE, count); if (err == SD_OK) { err = HAL_SD_CheckReadOperation(&SDHandle, SDIO_TIMEOUT); } if (err != SD_OK) { printf("read buf:%p addr:%lu count%lu error:%d\n", buff, sector, count, err); } dma_deinit(); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); } return (err != SD_OK); }
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; // check that dest pointer is aligned on a 4-byte boundary uint8_t *orig_dest = NULL; uint32_t saved_word; if (((uint32_t)dest & 3) != 0) { // Pointer is not aligned so it needs fixing. // We could allocate a temporary block of RAM (as sdcard_write_blocks // does) but instead we are going to use the dest buffer inplace. We // are going to align the pointer, save the initial word at the aligned // location, read into the aligned memory, move the memory back to the // unaligned location, then restore the initial bytes at the aligned // location. We should have no trouble doing this as those initial // bytes at the aligned location should be able to be changed for the // duration of this function call. orig_dest = dest; dest = (uint8_t*)((uint32_t)dest & ~3); saved_word = *(uint32_t*)dest; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); dma_init(&sd_rx_dma, &SDMMC_RX_DMA, &sd_handle); sd_handle.hdmarx = &sd_rx_dma; // make sure cache is flushed and invalidated so when DMA updates the RAM // from reading the peripheral the CPU then reads the new data MP_HAL_CLEANINVALIDATE_DCACHE(dest, num_blocks * SDCARD_BLOCK_SIZE); err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckReadOperation(&sd_handle, 100000000); } dma_deinit(&SDMMC_RX_DMA); sd_handle.hdmarx = NULL; restore_irq_pri(basepri); } else { err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); } if (orig_dest != NULL) { // move the read data to the non-aligned position, and restore the initial bytes memmove(orig_dest, dest, num_blocks * SDCARD_BLOCK_SIZE); memcpy(dest, &saved_word, orig_dest - dest); } return err; }
mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (sd_handle.Instance == NULL) { return HAL_ERROR; } HAL_StatusTypeDef err = HAL_OK; // check that src pointer is aligned on a 4-byte boundary if (((uint32_t)src & 3) != 0) { // pointer is not aligned, so allocate a temporary block to do the write uint8_t *src_aligned = m_new_maybe(uint8_t, SDCARD_BLOCK_SIZE); if (src_aligned == NULL) { return HAL_ERROR; } for (size_t i = 0; i < num_blocks; ++i) { memcpy(src_aligned, src + i * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE); err = sdcard_write_blocks(src_aligned, block_num + i, 1); if (err != HAL_OK) { break; } } m_del(uint8_t, src_aligned, SDCARD_BLOCK_SIZE); return err; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); #if SDIO_USE_GPDMA dma_init(&sd_tx_dma, &SDMMC_TX_DMA, &sd_handle); sd_handle.hdmatx = &sd_tx_dma; #endif // make sure cache is flushed to RAM so the DMA can read the correct data MP_HAL_CLEAN_DCACHE(src, num_blocks * SDCARD_BLOCK_SIZE); err = HAL_SD_WriteBlocks_DMA(&sd_handle, (uint8_t*)src, block_num, num_blocks); if (err == HAL_OK) { err = sdcard_wait_finished(&sd_handle, 60000); } #if SDIO_USE_GPDMA dma_deinit(&SDMMC_TX_DMA); sd_handle.hdmatx = NULL; #endif restore_irq_pri(basepri); } else { err = HAL_SD_WriteBlocks(&sd_handle, (uint8_t*)src, block_num, num_blocks, 60000); if (err == HAL_OK) { err = sdcard_wait_finished(&sd_handle, 60000); } } return err; }
// Called from the SysTick handler // We use LSB of tick to select which controller to process void dma_idle_handler(uint32_t tick) { int controller = tick & 1; if (controller != 0) { return; } if (dma_idle.bmChnEn[controller] == 0) { if (++dma_idle.counter[controller] > 200) { dma_deinit(controller, 0); // use a dummy channel index } } }
mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; // check that src pointer is aligned on a 4-byte boundary if (((uint32_t)src & 3) != 0) { // pointer is not aligned, so allocate a temporary block to do the write uint8_t *src_aligned = m_new_maybe(uint8_t, SDCARD_BLOCK_SIZE); if (src_aligned == NULL) { return SD_ERROR; } for (size_t i = 0; i < num_blocks; ++i) { memcpy(src_aligned, src + i * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE); err = sdcard_write_blocks(src_aligned, block_num + i, 1); if (err != SD_OK) { break; } } m_del(uint8_t, src_aligned, SDCARD_BLOCK_SIZE); return err; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); dma_init(&sd_tx_dma, &dma_SDIO_0_TX, &sd_handle); sd_handle.hdmatx = &sd_tx_dma; err = HAL_SD_WriteBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckWriteOperation(&sd_handle, 100000000); } dma_deinit(&dma_SDIO_0_TX); sd_handle.hdmatx = NULL; restore_irq_pri(basepri); } else { err = HAL_SD_WriteBlocks_BlockNumber(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks); } return err; }
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that dest pointer is aligned on a 4-byte boundary if (((uint32_t)dest & 3) != 0) { return SD_ERROR; } // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); dma_init(&sd_rx_dma, DMA_STREAM_SDIO_RX, &dma_init_struct_sdio, DMA_CHANNEL_SDIO_RX, DMA_PERIPH_TO_MEMORY, &sd_handle); sd_handle.hdmarx = &sd_rx_dma; err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckReadOperation(&sd_handle, 100000000); } dma_deinit(sd_handle.hdmarx); sd_handle.hdmarx = NULL; restore_irq_pri(basepri); } else { err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); } return err; }
int gmac_mac_init(struct eth_device *dev) { struct eth_info *eth = (struct eth_info *)(dev->priv); struct eth_dma *dma = &(eth->dma); uint32_t tmp; uint32_t cmdcfg; int chipid; debug("%s enter\n", __func__); /* Always use GMAC0 */ printf("Using GMAC%d\n", 0); /* Reset AMAC0 core */ writel(0, AMAC0_IDM_RESET_ADDR); tmp = readl(AMAC0_IO_CTRL_DIRECT_ADDR); /* Set clock */ tmp &= ~(1 << AMAC0_IO_CTRL_CLK_250_SEL_SHIFT); tmp |= (1 << AMAC0_IO_CTRL_GMII_MODE_SHIFT); /* Set Tx clock */ tmp &= ~(1 << AMAC0_IO_CTRL_DEST_SYNC_MODE_EN_SHIFT); writel(tmp, AMAC0_IO_CTRL_DIRECT_ADDR); /* reset gmac */ /* * As AMAC is just reset, NO need? * set eth_data into loopback mode to ensure no rx traffic * gmac_loopback(eth_data, TRUE); * ET_TRACE(("%s gmac loopback\n", __func__)); * udelay(1); */ cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML | CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | CC_PAD_EN | CC_PF); cmdcfg |= (CC_PROM | CC_NLC | CC_CFE); /* put mac in reset */ gmac_init_reset(); writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); gmac_clear_reset(); /* enable clear MIB on read */ reg32_set_bits(GMAC0_DEV_CTRL_ADDR, DC_MROR); /* PHY: set smi_master to drive mdc_clk */ reg32_set_bits(GMAC0_PHY_CTRL_ADDR, PC_MTE); /* clear persistent sw intstatus */ writel(0, GMAC0_INT_STATUS_ADDR); if (dma_init(dma) < 0) { pr_err("%s: GMAC dma_init failed\n", __func__); goto err_exit; } chipid = CHIPID; printf("%s: Chip ID: 0x%x\n", __func__, chipid); /* set switch bypass mode */ tmp = readl(SWITCH_GLOBAL_CONFIG_ADDR); tmp |= (1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT); /* Switch mode */ /* tmp &= ~(1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT); */ writel(tmp, SWITCH_GLOBAL_CONFIG_ADDR); tmp = readl(CRMU_CHIP_IO_PAD_CONTROL_ADDR); tmp &= ~(1 << CDRU_IOMUX_FORCE_PAD_IN_SHIFT); writel(tmp, CRMU_CHIP_IO_PAD_CONTROL_ADDR); /* Set MDIO to internal GPHY */ tmp = readl(GMAC_MII_CTRL_ADDR); /* Select internal MDC/MDIO bus*/ tmp &= ~(1 << GMAC_MII_CTRL_BYP_SHIFT); /* select MDC/MDIO connecting to on-chip internal PHYs */ tmp &= ~(1 << GMAC_MII_CTRL_EXT_SHIFT); /* * give bit[6:0](MDCDIV) with required divisor to set * the MDC clock frequency, 66MHZ/0x1A=2.5MHZ */ tmp |= 0x1A; writel(tmp, GMAC_MII_CTRL_ADDR); if (gmac_mii_busywait(1000)) { pr_err("%s: Configure MDIO: MII/MDIO busy\n", __func__); goto err_exit; } /* Configure GMAC0 */ /* enable one rx interrupt per received frame */ writel(1 << GMAC0_IRL_FRAMECOUNT_SHIFT, GMAC0_INTR_RECV_LAZY_ADDR); /* read command config reg */ cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); /* enable 802.3x tx flow control (honor received PAUSE frames) */ cmdcfg &= ~CC_RPI; /* enable promiscuous mode */ cmdcfg |= CC_PROM; /* Disable loopback mode */ cmdcfg &= ~CC_ML; /* set the speed */ cmdcfg &= ~(CC_ES_MASK | CC_HD); /* Set to 1Gbps and full duplex by default */ cmdcfg |= (2 << CC_ES_SHIFT); /* put mac in reset */ gmac_init_reset(); /* write register */ writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); /* bring mac out of reset */ gmac_clear_reset(); /* set max frame lengths; account for possible vlan tag */ writel(PKTSIZE + 32, UNIMAC0_FRM_LENGTH_ADDR); return 0; err_exit: dma_deinit(dma); return -1; }
/*! \brief main function \param[in] none \param[out] none \retval none */ int main(void) { int i = 0; dma_parameter_struct dma_init_struct; /* enable DMA clock */ rcu_periph_clock_enable(RCU_DMA); /* initialize LED */ led_config(); /* all LED off */ gd_eval_ledoff(LED1); gd_eval_ledoff(LED3); gd_eval_ledoff(LED2); gd_eval_ledoff(LED4); /* initialize DMA channel1 */ dma_deinit(DMA_CH1); dma_init_struct.direction = DMA_PERIPHERA_TO_MEMORY; dma_init_struct.memory_addr = (uint32_t)destination_address1; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = DATANUM; dma_init_struct.periph_addr = (uint32_t)source_address; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_ENABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; dma_init(DMA_CH1,dma_init_struct); /* configure DMA mode */ dma_circulation_disable(DMA_CH1); dma_memory_to_memory_enable(DMA_CH1); /* initialize DMA channel2 */ dma_deinit(DMA_CH2); dma_init_struct.memory_addr = (uint32_t)destination_address2; dma_init(DMA_CH2,dma_init_struct); /* configure DMA mode */ dma_circulation_disable(DMA_CH2); dma_memory_to_memory_enable(DMA_CH2); /* initialize DMA channel3 */ dma_deinit(DMA_CH3); dma_init_struct.memory_addr = (uint32_t)destination_address3; dma_init(DMA_CH3,dma_init_struct); /* configure DMA mode */ dma_circulation_disable(DMA_CH3); dma_memory_to_memory_enable(DMA_CH3); /* initialize DMA channel4 */ dma_deinit(DMA_CH4); dma_init_struct.memory_addr = (uint32_t)destination_address4; dma_init(DMA_CH4,dma_init_struct); /* configure DMA mode */ dma_circulation_disable(DMA_CH4); dma_memory_to_memory_enable(DMA_CH4); /* enable DMA channel1~channel4 */ dma_channel_enable(DMA_CH1); dma_channel_enable(DMA_CH2); dma_channel_enable(DMA_CH3); dma_channel_enable(DMA_CH4); /* wait for DMA transfer complete */ for(i = 0; i < 200; i++); /* compare the data of source_address with data of destination_address */ transferflag1 = memory_compare(source_address, destination_address1, DATANUM); transferflag2 = memory_compare(source_address, destination_address2, DATANUM); transferflag3 = memory_compare(source_address, destination_address3, DATANUM); transferflag4 = memory_compare(source_address, destination_address4, DATANUM); /* if DMA channel1 transfer success,light LED1 */ if(SUCCESS == transferflag1){ gd_eval_ledon(LED1); } /* if DMA channel2 transfer success,light LED2 */ if(SUCCESS == transferflag2){ gd_eval_ledon(LED2); } /* if DMA channel3 transfer success,light LED3 */ if(SUCCESS == transferflag3){ gd_eval_ledon(LED3); } /* if DMA channel4 transfer success,light LED4 */ if(SUCCESS == transferflag4){ gd_eval_ledon(LED4); } while (1); }