有人能帮我弄清楚为什么 uDMA pingpong 操作不能使用这段代码吗?

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

如果您取消注释由 SysTick 计时器触发的通道 30 上的基本软件 DMA 传输,则 DMA 引擎会工作。但是 Timer1A 触发 DMA 到 SSI1-DR 使 DMA 引擎空闲。

我正在尝试将 16 位数据从 RAM 中的缓冲区发送到 SSI1 数据寄存器。我的 DMA 配置有什么地方不对吗?这是我第一次尝试使用 DMA,我无法理解源和目标的控制表配置。我基本上将 Jonathan Valvano 博士的 DMASPI.C 和 DMASoftware.c 重写到一个项目中。

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

博士Valvano的软件DMA代码链接:http://users.ece.utexas.edu/~valvano/arm/DMASoftware.c

博士Valvano 的其他代码,其中 DMASPI.c 在 zip 文件夹中:http://users.ece.utexas.edu/~valvano/arm/index.htm

这是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 控制表设置中的所有内容都设置正确。 DMA_PingpongStart(&DMAPingpong_SourceTest[0], &(SSI1->DR), 10);功能武装一切,甚至定时器中断切换 LED,但 SSI1->DR(SSI1 数据寄存器)中没有任何显示。

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