如何在 TI TM4C123GH6PM 微控制器上用 C 语言将 uDMA 配置为 SPI 乒乓模式?

问题描述 投票:0回答:0

如果您在

DMA transfer
取消注释基本软件
channel 30
SysTick
计时器触发,
DMA Engine
工作。

但是

Timer1A

触发
DMA
SSI1-DR
离开
DMA Engine
空闲。

我正在尝试从

SSI1 data register

 中的缓冲区向 
RAM
 发送 16 位数据。

我的 DMA 配置有什么地方不对吗?

这是我第一次尝试使用

DMA

 并且我无法理解源和目标的控制表配置。

我基本上重写了

博士。 Jonathan ValvanoDMASPI.C

DMASoftware.c
 进入一个项目。

我非常感谢对 DMA 控制表设置和索引的解释。

博士。 Valvano的软件DMA代码链接

博士。 Valvano 的其他代码 其中DMASPI.c

 在一个 zip 文件夹中。

这是C文件代码

#include "timer.h" #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <stdbool.h> #define BIT30 0x40000000 #define CH30 (30*4) #define CH30ALT (30*4+128) #define SSI_DR_R *((volatile uint32_t *) 0x40009008) #define BIT18 0x00040000 #define CH18SEL 0x00000200 #define CH18 (18*4) #define CH18ALT (18*4+128) static uint16_t *SourcePt; static volatile uint32_t *DestinationPt; static uint32_t Count; static uint32_t BufferCount; static uint32_t DMA_ControlTable[256]__attribute__ ((aligned(1024))); //uDMA Control Table static uint32_t DMA_PingpongCTLTB[256]__attribute__ ((aligned(1024))); //uDMA Control Table static uint32_t NumberOfBuffersSent=0; uint8_t timerCounts=0xffff; static uint16_t endPT = (131*8)-1 ; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* __ __ _ ___ _ _ ___ ___ _ _ _____ ___ _ _ ___ | \/ | /_\ |_ _| | \| | | _ \ / _ \ | | | | |_ _| |_ _| | \| | | __| | |\/| | / _ \ | | | .` | | / | (_) | | |_| | | | | | | .` | | _| |_| |_| /_/ \_\ |___| |_|\_| |_|_\ \___/ \___/ |_| |___| |_|\_| |___| *//*__________________________________________________________________________________________________________________________________________*/ int main(void) { //main start //timer1A_Init(0xffff); F_init(); SPI1_init(); DMA_SourceStart(); // DMA_SimpleInit(); // DMA_SimpleStart(&DMA_SourceTest[0], &DMA_DestTest[0], 10); // SysTick_INIT(); ////timer1A_Init(0xffff); DMA_PingpongInit(0xFFFF); //Arms Timer but doesn't enable it // DMA_PingpongStart(&DMAPingpong_SourceTest[0], &DMA_DestTest[0], (100)); //enables: timer,timer interrupts, DMA Engine // DMA_PingpongStart(&DMAPingpong_SourceTest[0], (uint32_t *)SSI_DR_R, (100)); //enables: timer,timer interrupts, DMA Engine DMA_PingpongStart(&DMAPingpong_SourceTest[0], &(SSI1->DR), 10); //enables: timer,timer interrupts, DMA Engine while(1) { WaitForInterrupt(); BufferCount = DMA_Status(); } } /* MAIN END*/ /*-------------------------------- PORT F INIT --------------------------------------------*/ void F_init(void) { SYSCTL->RCGCGPIO |= (1<<5); /* Enable clock to GPIOF */ GPIOF->DEN |= (1<<3) | (1<<2)| (1<<1) ; /* Set PF3 pin digital */ GPIOF->DIR |= (1<<3) | (1<<2)| (1<<1) ; /* Set PF3 pin output */ GPIOF->DIR |= (1<<3) | (1<<2)| (1<<1); /* Set PF3 pin output */ GPIOF->DATA |= (1<<3) | (1<<2)| (1<<1); /* PF2 as Reset for OLED */ } static void timer1A_Init(uint16_t period) { SYSCTL->RCGCTIMER |= 0x02; TIMER1->CTL &=!(0x00000001);// Disable Timer for CFG TIMER1->CFG =0x4; //16 BIT TIMER TIMER1->TAMR = 0x02; //PERIODIC MODE //TIMER1->TAILR =(0xFFFF-1); TIMER1->TAPR =255-1; //prescaler (48MHz/(TAPR)) //TIMER1->TAPR =0; TIMER1->TAILR =(period-1); // Releoad Value TIMER1->ICR |=0x01; // Clear Interrupts TIMER1->IMR |=0x01; // Timer1A timeout interrupr Enabled NVIC->IP[TIMER1A_IRQn] |= 0x7; // timer1A priority level // NVIC->ISER[0] |= (1<<21); //timer1A to NVIC // TIMER1->CTL |=(0x00000001); //Enabled by DMA Start } /*_______________________________________________________________________________________________*/ void TIMER1A_Handler(void) { //DisableInterrupts(); // gloabal interrupt disable NumberOfBuffersSent++; GPIOF->DATA ^= (1<<3) | (1<<2)| (1<<1); //toggle LEDs // UDMA->SWREQ |= BIT30; //udma software request if((DMA_PingpongCTLTB[CH18+2]&0x0007)==0){ // regular buffer complete DMA_SetRegular(); // rebuild channel control structure } if((DMA_PingpongCTLTB[CH18ALT+2]&0x0007)==0){ // Alternate buffer complete DMA_SetAlt(); // rebuild channel control structure } TIMER1->ICR =0x01; //ACK timer timeout //EnableInterrupts(); // gloabal interrupt enable } /*_______________________________________________________________________________________________*/ void SysTick_Handler(void) /* SysTick interrupt handler function*/ { GPIOF->DATA ^= (1<<3) | (1<<2)| (1<<1); UDMA->SWREQ |= BIT30; } /*_______________________________________________________________________________________________*/ void static DMA_SimpleInit(void) { for(uint16_t i=0; i<256; i++){ DMA_ControlTable[i] = 0;} // clear control table SYSCTL->RCGCDMA |= 0x01; // DMA clocked Delay_ms(1); UDMA->CFG = 0x01; // enable Configuration UDMA->CTLBASE = (uint32_t) DMA_ControlTable; // control table base UDMA->CHMAP3 |= BIT30; // software DMA UDMA->PRIOCLR |= BIT30; UDMA->ALTCLR |= BIT30; UDMA->USEBURSTCLR |= BIT30; UDMA->REQMASKCLR |= BIT30; } /*_______________________________________________________________________________________________*/ void static DMA_SimpleStart(uint32_t *source, uint32_t *destination, uint32_t count) { /* DMACHCTL Bits Value Description DSTINC 31:30 10 32-bit destination address increment DSTSIZE 29:28 10 32-bit destination data size SRCINC 27:26 10 32-bit source address increment SRCSIZE 25:24 10 32-bit source data size reserved 23:18 0 Reserved ARBSIZE 17:14 0011 Arbitrates after 8 transfers XFERSIZE 13:4 count-1 Transfer count items NXTUSEBURST 3 0 N/A for this transfer type XFERMODE 2:0 010 Use Auto-request transfer mode */ /*__________________________________*/ DMA_ControlTable[CH30] = (uint32_t)source+count*4-1 ; DMA_ControlTable[CH30+1] = (uint32_t )destination+count*4-1 ; //DMA_ControlTable[2] = (uint32_t)((0x00000000)|(0<<28)|(0<<26)|(0<<24)|(1<<14)|(1024<<4)|(0<<3)|(1<<0)); DMA_ControlTable[CH30+2] = 0xAA00C002+((count-1)<<4); UDMA->ENASET |= BIT30; // UDMA->SWREQ |= BIT30; } /*_______________________________________________________________________________________________*/ void static DMA_PingpongInit(uint16_t period) { for(uint16_t i=0; i<256; i++){ DMA_ControlTable[i] = 0;} SYSCTL->RCGCDMA = 0x01; // CLOCK DMA engine Delay_ms(1); UDMA->CFG = 0x01; // enable configuration UDMA->CTLBASE = (uint32_t) DMA_PingpongCTLTB; UDMA->CHMAP2 = CH18SEL; // select channel 18 bit 1 for timer1A DMA Trigger UDMA->PRIOCLR = BIT18; UDMA->ALTCLR = BIT18; UDMA->USEBURSTCLR = BIT18; UDMA->REQMASKCLR = BIT18; timer1A_Init(period); } /*_______________________________________________________________________________________________*/ void static DMA_SetRegular(void) { /* DMACHCTL Bits Value Description DSTINC 31:30 11 no destination address increment DSTSIZE 29:28 01 16-bit destination data size SRCINC 27:26 01 16-bit source address increment SRCSIZE 25:24 01 16-bit source data size reserved 23:18 0 Reserved ARBSIZE 17:14 0 Arbitrates after 1 transfers XFERSIZE 13:4 count-1 Transfer count items NXTUSEBURST 3 0 N/A for this transfer type XFERMODE 2:0 011 Use PINGPONG transfer mode */ DMA_PingpongCTLTB[CH18] = (uint32_t)SourcePt; DMA_PingpongCTLTB[CH18+1] = (uint32_t )DestinationPt; //DMA_PingpongCTLTB[CH18ALT+2] = 0xA500C003+((Count-1)<<4); DMA_PingpongCTLTB[CH18+2] = 0xD5000003+((Count-1)<<4); } /*_______________________________________________________________________________________________*/ void static DMA_SetAlt(void) { /* DMACHCTL Bits Value Description DSTINC 31:30 11 no destination address increment DSTSIZE 29:28 01 16-bit destination data size SRCINC 27:26 01 16-bit source address increment SRCSIZE 25:24 01 16-bit source data size reserved 23:18 0 Reserved ARBSIZE 17:14 0 Arbitrates after 1 transfers XFERSIZE 13:4 count-1 Transfer count items NXTUSEBURST 3 0 N/A for this transfer type XFERMODE 2:0 011 Use PINGPONG transfer mode */ DMA_PingpongCTLTB[CH18ALT] = (uint32_t)SourcePt; DMA_PingpongCTLTB[CH18ALT+1] = (uint32_t )DestinationPt; //DMA_PingpongCTLTB[CH18ALT+2] = 0xA500C003+((Count-1)<<4); DMA_PingpongCTLTB[CH18ALT+2] = 0xD5000003+((Count-1)<<4); } /*_______________________________________________________________________________________________*/ void static DMA_PingpongStart(uint16_t *source,volatile uint32_t*destination, uint32_t count) { SourcePt = (source +count)-1; DestinationPt = destination; Count = count; DMA_SetRegular(); DMA_SetAlt(); NVIC->ISER[0] |= (1<<21); // timer1A to NVIC SSI1->DMACTL |= 0x02; // SSI1 uDMA for Tx FIFO Enabled UDMA->ENASET |= BIT18; // Arm DMA Engine TIMER1->CTL |=(0x00000001); // timer1A ENABLE } /*_______________________________________________________________________________________________*/ void static DMA_SourceStart(void) { int i; uint32_t *sourcePTR; for(i = 0 ; i < (131*8); i++) { sourcePTR = &DMA_SourceTest[i]; *sourcePTR = 0xFF; DMAPingpong_SourceTest[i] = 0x0FFF; } } /*_______________________________________________________________________________________________*/ uint32_t DMA_Status(void){ return NumberOfBuffersSent; }
这是.h文件代码

#include "TM4C123GH6PM.h" void static DMA_SimpleInit(void); void static DMA_PingpongInit(uint16_t period); void SPI1_init(void); void F_init(void); /*init timers */ static void timer1A_Init(uint16_t period); void SysTick_INIT(void); /* timer interrupt handler*/ void TIMER1A_Handler(void); void SysTick_Handler(void); void DisableInterrupts(void); void EnableInterrupts(void); void WaitForInterrupt(void); void Delay_ms(int time_ms); /* uDMA Functions*/ void static DMA_SourceStart(void); void static DMA_SimpleStart(uint32_t *source,uint32_t*destination, uint32_t count); void static DMA_PingpongStart(uint16_t *source,volatile uint32_t*destination, uint32_t count); uint32_t DMA_Status(void); void static DMA_SetRegular(void); void static DMA_SetAlt (void); static uint32_t DMA_SourceTest [131*8]; static uint16_t DMAPingpong_SourceTest [131*8]; static uint32_t DMA_DestTest [131*8]; void Delay_ms(int time_ms) { int i, j; for(i = 0 ; i < time_ms; i++) { for(j = 0; j < 20; j++){} /* excute NOP for 0.5ms */ } } void SysTick_INIT(void) { //SysTick->LOAD = 47999; //SysTick->LOAD = 23999; /* about 500 ns @ 48 MHz */ SysTick->LOAD = 15999999; //SysTick->LOAD = sysVal; //SysTick->LOAD = (7800000); //SysTick->LOAD = (3800000); //SysTick->LOAD = (1500000); //NVIC->IP[SysTick_IRQn] |= (1<<7); /*set portE interrupt priority*/ //NVIC->ISER[0] |= (1<<4); /* Enable portE interrupts*/ //SysTick->LOAD = timer_Val; SysTick->CTRL|= 0x07; SysTick->VAL |= 0x00; } void DisableInterrupts(void) { __asm (" CPSID I\n"); } /*********** EnableInterrupts *************** * * emable interrupts * * inputs: none * outputs: none */ /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ void EnableInterrupts(void) { __asm (" CPSIE I\n"); } /*********** WaitForInterrupt ************************ * * go to low power mode while waiting for the next interrupt * * inputs: none * outputs: none */ void WaitForInterrupt(void) { __asm (" WFI\n"); } void SPI1_init(void) { /*_______________________________________________________________________________________________________________*/ /* Enable clock to SPI1, GPIOD and GPIOF */ SYSCTL->RCGCSSI |= (1<<1); /*set clock enabling bit for SPI1 */ SYSCTL->RCGCGPIO |= (1<<3); /* enable clock to GPIOD for SPI1 */ SYSCTL->RCGCGPIO |= (1<<5); /* enable clock to GPIOF for slave select */ /*_______________________________________________________________________________________________________________*/ /* Initialize PF3 as a digital output as a slave select pin */ /* GPIOF->AMSEL &= 0x00; disable analog functionality Port F */ // GPIOF->AFSEL |= 0x08; /* enable alternate function of PF3 */ // GPIOF->PCTL |= 0x00002000; /* assign PF3 to SPI1 */ GPIOF->DEN |= (1<<3) | (1<<2)| (1<<1) ; /* set PF3 pin digital */ //GPIOF->DR4R |= (1<<3) | (1<<2)| (1<<1); /* set PF[3-1] 4mA */ GPIOF->DIR |= (1<<3) | (1<<2)| (1<<1) ; /* set PF3 pin output */ GPIOF->DATA |= (1<<3); /* keep SS idle high */ /*_______________________________________________________________________________________________________________*/ /*Initialize PD3 and PD0 for SPI1 alternate function*/ /*GPIOD->AMSEL &= 0x00; disable analog functionality PD0 and PD3 */ GPIOD->AFSEL |= 0x09; /* enable alternate function of PD0 and PD3*/ /*GPIOD->PCTL &= 0x0000F00F; assign PD0 and PD3 pins to SPI1 */ GPIOD->PCTL |= 0x00002002; /* assign PD0 and PD3 pins to SPI1 */ GPIOD->DR8R |= (1<<3)|(1<<0); GPIOD->DEN |= 0x09; /* Set PD0 and PD3 as digital pin */ /*GPIOD->DIR |= 0x09; Set PD0 and PD3 as digital OUTPUT pins */ /*_______________________________________________________________________________________________________________*/ /* Select SPI1 as a Master, POL = 0, PHA = 0, clock = 4 MHz, 8 bit data */ /*SSI1->CR1 &= 0x00; disable SPI1 and configure it as a Master */ SSI1->CR1 &= 0x00000000; /* disable SPI1 and configure it as a Master */ SSI1->CC |= 0x00; /* Enable System clock Option */ SSI1->CPSR |= 6; /* Select prescaler .i.e 48MHz/16 = 3MHz | 48MHz/8 = 6~8MHz | 48MHz/4 = 8~12MHz*/ SSI1->CR0 |= 0xF; /* XMHz SPI1 clock, SPI mode, 8 bit data */ //SSI1->DMACTL |= 0x02; // SSI1 uDMA for Tx FIFO Enabled // SSI1->IM |= 0x08; // // NVIC->IP[SSI1_IRQn] |= 0x01 ; // NVIC->ISER[1] |= 0x04; /*________________________________________________________*/ /*Initialize SPI1 uDMA functionality*/ //SSI1->DMACTL->0x2; //EOT interrupt // SSI1->CR1 |= (1<<4)|(1<<1); /* enable SPI1 */ SSI1->CR1 |= (1<<1); /* enable SPI1 */ }
此外,我不确定将

SSI1-DMACTL

部分放在哪里。

我使用

Keil uVision5

 逐步执行代码,并且 
DMA control table
 设置中的所有内容都设置正确。

下面的功能武装一切,甚至定时器中断切换

LEDs

SSI1->DR
SSI1数据寄存器)中没有任何内容出现。

DMA_PingpongStart(&DMAPingpong_SourceTest[0], &(SSI1->DR), 10);
如果发现一些错误:UDMA->CHMAP2 = (1

<<8); // select channel 18 ENCODING 1 for timer1A DMA Trigger instead of the wrong (2<<8)

c embedded dma texas-instruments
© www.soinside.com 2019 - 2024. All rights reserved.