140 likes | 563 Views
NuMicro Cortex-M0 PDMA. 议题. 特性 方块图 功能描述 示例. 特性. 九通道 DMA (Peripheral-to-Memory or Memory-to-Peripheral or Memory-to-Memory) 一个内部 word buffer 源和目的地址有 两 种选择 : 增加,固定 传输宽度可以选择: 8/16/32. 方块图. SPI 0. AHB. SPI 1. SPI 2. Master/Slave Wrapper. SPI 3. CH0 Control 1 Word Buffer.
E N D
议题 • 特性 • 方块图 • 功能描述 • 示例
特性 • 九通道DMA (Peripheral-to-Memory or Memory-to-Peripheral or Memory-to-Memory) • 一个内部 word buffer • 源和目的地址有两种选择: 增加,固定 • 传输宽度可以选择:8/16/32
方块图 SPI 0 AHB SPI 1 SPI 2 Master/Slave Wrapper SPI 3 CH0 Control 1 Word Buffer I/O, Decoder Registers UART 0 CH1 Control 1 Word Buffer UART 1 Global Controller USB Bus Master Control ADC CH8 Control 1 Word Buffer I2S
Memory-to-Memory • 从内存到内存搬动数据 PDMA_SARx Source Addr. Source PDMA_DARx Destination Addr. PDMA Controller Channel x Destination PDMA_BCRx Byte Counter Memory
Memory-to-APB IP • 从内存到APB IP SAD_SEL Source Addr. Direction Fixed or Incremental DAD_SEL Dest. Addr. Direction Fixed PDMA Controller Channel x Source Destination APB IP APB_TWS Transfer Width Select 8/16/32-bits Memory
APB IP-to-Memory • 从APB IP到内存搬动数据 DAD_SEL Dest. Addr. Direction Fixed or Incremental SAD_SEL Source Addr. Direction Fixed PDMA Controller Channel x Destination Source APB IP APB_TWS Transfer Width Select 8/16/32-bits Memory
中断 • BLKD: 块传输完成 • TABORT: 读/写 目标 Abort
例子 • 利用PDMA从SPI flash移动数据到内存 • SPI0 作为主模式, 8bits 数据宽
PDMA 驱动示例(1/4) #define TEST_LENGTH 256 uint8_t DestArray[TEST_LENGTH]; volatile uint32_t PDMA0_INT_Flag; void PDMA0_Callback(void); int main(void) { STR_PDMA_T sPDMA; uint32_t SPIPort; /* Unlock the protected registers */ UNLOCKREG(); /* Enable the 12MHz oscillator oscillation */ DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); /* HCLK clock source. 0: external 12MHz; 4:internal 22MHz RC oscillator */ DrvSYS_SetHCLKSource(0); LOCKREG(); /* HCLK clock frequency = HCLK clock source / (HCLK_N + 1) */ DrvSYS_SetClockDivider(E_SYS_HCLK_DIV, 0); Write locked register to initial HCLK
PDMA驱动示例(2/4) /* Configure SPI0 as a master, type-1 waveform, 8-bit transaction */ DrvSPI_Open(eDRVSPI_PORT0, eDRVSPI_MASTER, eDRVSPI_TYPE1, 8); /* MSB First. */ DrvSPI_SetEndian(eDRVSPI_PORT0, eDRVSPI_MSB_FIRST); /* Enable the automatic slave select function of SS0. */ DrvSPI_EnableAutoCS(eDRVSPI_PORT0, eDRVSPI_SS0); /* Set the active level of slave select. */ DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT0, eDRVSPI_ACTIVE_LOW_FALLING); /* enable SPI RX PDMA */ DrvSPI_StartPDMA(eDRVSPI_PORT0, eDRVSPI_RX_DMA, TRUE); /* SPI clock rate 1MHz */ DrvSPI_SetClock(eDRVSPI_PORT0, 1000000, 0); /* PDMA Init */ DrvPDMA_Init(); /* PDMA Setting, channel 0 = SPI0, read APB */ DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_0, eDRVPDMA_SPI0, eDRVPDMA_READ_APB); Initial SPI0 controller Initial and setting PDMA controller
PDMA驱动示例(3/4) /* SPI Port = SPI0 Rx0 */ SPIPort = SPI0_BASE + 0x10; /* PDMA CH0 RX Setting */ sPDMA.sSrcAddr.u32Addr = SPIPort; sPDMA.sDestAddr.u32Addr = (uint32_t)DestArray; sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS; sPDMA.u8Mode = eDRVPDMA_MODE_APB2MEM; sPDMA.sSrcAddr.eAddrDirection = eDRVPDMA_DIRECTION_FIXED; sPDMA.sDestAddr.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED; sPDMA.i32ByteCnt = TEST_LENGTH; DrvPDMA_Open(eDRVPDMA_CHANNEL_0, &sPDMA); /* Enable PDMA INT */ DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD ); /* Install PDMA Callback function */ DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA0_Callback ); /* Trigger PDMA specified Channel */ DrvPDMA_CHEnablelTransfer(eDRVPDMA_CHANNEL_0); 设定并打开PDMA channel 0 使能PDMA channel 0 中断 使能PDMA channel 0
PDMA驱动示例(4/4) PDMA0_INT_Flag = 0; /* SPI0 go */ DrvSPI_SetGo(eDRVSPI_PORT0); /* Wait PDMA transfer done */ while(1) { if(PDMA0_INT_Flag == 1) { PDMA0_INT_Flag = 0; printf("\nSPI0 RX PDMA Transfer Done!!!\n”); break; } } DrvSPI_Close(eDRVSPI_PORT0); DrvPDMA_Close(); return 1; } void PDMA0_Callback(void) { PDMA0_INT_Flag = 1; } 触发SPI0 go 等待PDMA channel 0 传输完成 PDMA channel 0 回调函数