打印

有关J-LINK以及DMA的问题

[复制链接]
7924|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lorelia14|  楼主 | 2012-3-20 15:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚刚开始学习使用STM32,针对207的芯片,发现有诸多问题不得其解,特发贴请教。
程序很简单,打算利用DMA方式将内存数据通过GPIO端口传递出去,想测试一下传递速度,下面附上程序代码:
int main(void)
{
  RCC_ClocksTypeDef RCC_Clocks;

  SystemInit();
   
  /* SysTick end of count event each 10ms */
  RCC_GetClocksFreq(&RCC_Clocks);
  SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);

  NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x00);
//  NVIC_SetVectorTable(NVIC_VectTab_RAM,0x00);

  NVIC_Configuration();// NVIC configuration
  GPIO_Init_Configuration();

  /* Initialize LEDs and LCD available on STM322xG-EVAL board *****************/

  STM_EVAL_LEDInit(LED2);
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDInit(LED4);

  /* Turn on LEDs available on STM322xG-EVAL **********************************/
  STM_EVAL_LEDOn(LED2);

  /* Add your application code here
     */

  SDCard_Control();

  /* Infinite loop */
  while (1)
  {
    /* Toggle LD4 */
    STM_EVAL_LEDToggle(LED3);

    /* Insert 50 ms delay */
    Delay(5);

    /* Toggle LD2 */
    STM_EVAL_LEDToggle(LED2);

    /* Insert 50 ms delay */
    Delay(5);
  }
}

void SDCard_Control(void)
{
    uint32_t count=0;
    uint32_t DMA_buffer[32];

    for(count=0;count<32;count++)
       DMA_buffer[count] = count+0x55;

    DMA_Config();
}

void DMA_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  DMA_InitTypeDef  DMA_InitStructure;
  __IO uint32_t    Timeout = TIMEOUT_MAX;
   
  /* Enable DMA clock */
  RCC_AHB1PeriphClockCmd(GPIOB_DMA_CLOCK, ENABLE);
  
  /* Reset DMA Stream registers (for debug purpose) */
  DMA_DeInit(GPIOB_DMA_STREAM);

  /* Check if the DMA Stream is disabled before enabling it.
     Note that this step is useful when the same Stream is used multiple times:
     enabled, then disabled then re-enabled... In this case, the DMA Stream disable
     will be effective only at the end of the ongoing data transfer and it will
     not be possible to re-configure it before making sure that the Enable bit
     has been cleared by hardware. If the Stream is used only once, this step might
     be bypassed. */
  while (DMA_GetCmdStatus(GPIOB_DMA_STREAM) != DISABLE)
  {
  }
  
  /* Configure DMA Stream */
  DMA_InitStructure.DMA_Channel = GPIOB_DMA_CHANNEL;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)GPIOB_DMA_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DMA_buffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = 0xFFFF;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(GPIOB_DMA_STREAM, &DMA_InitStructure);
   
  /* Enable DMA Stream Transfer Complete interrupt */
//  DMA_ITConfig(GPIOB_DMA_STREAM, GPIOB_DMA_TCIF, ENABLE);

  /* DMA Stream enable */
  DMA_Cmd(GPIOB_DMA_STREAM, ENABLE);

  /* Check if the DMA Stream has been effectively enabled.
     The DMA Stream Enable bit is cleared immediately by hardware if there is an
     error in the configuration parameters and the transfer is no started (ie. when
     wrong FIFO threshold is configured ...) */
  Timeout = TIMEOUT_MAX;
  while ((DMA_GetCmdStatus(GPIOB_DMA_STREAM) != ENABLE) && (Timeout-- > 0))
  {
  }
   
  /* Check if a timeout condition occurred */
  if (Timeout == 0)
  {
    /* Manage the error: to simplify the code enter an infinite loop */
    while (1)
    {
    }
  }

  /* Enable the DMA Stream IRQ Channel */
/*
  NVIC_InitStructure.NVIC_IRQChannel = GPIOB_DMA_IRQ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);     
*/

  Timeout = TIMEOUT_MAX;
  while((DMA_GetFlagStatus(GPIOB_DMA_STREAM, GPIOB_DMA_TCIF) != RESET) && (Timeout-- > 0))
    {
  }

  DMA_DeInit(GPIOB_DMA_STREAM);
}
沙发
lorelia14|  楼主 | 2012-3-20 16:10 | 只看该作者
目前遇到的问题现象是:
1.在IAR调试工具下使用J-LINK,进入debug模式进行代码下载时提示“Bad JTAG communication: Write to IR: Expected 0x1, got 0x0 (TAP Command : 10) @ Off 0xA. Wrong AHB ID (15:3). Expected 0x04770001 (Mask 0x0FFFFF0F), Found 0x00000000”,由此终止代码下载,无法进入调试状态。

2.换成ST-LINK进行调试,程序可以成功下载,但当程序执行到
        for(TXCount=0;TXCount<32;TXCount++)
                DMA_buffer[TXCount] = TXCount+0x55;
时,在调试窗口中看到的DMA_buffer[]中的数据是并非我所期待的0x55,0x56,0x57,...,而是0x58575655,0x5C5B5A59,0x605F5E5D,...。

我配置的DMA参数用到以下定义:
#define GPIOB_DMA_ADDRESS              0x40020414  //GPIOB_ODR

#define GPIOB_DMA_CLOCK                RCC_AHB1Periph_DMA1
#define GPIOB_DMA_STREAM               DMA1_Stream4
#define GPIOB_DMA_CHANNEL              DMA_Channel_0
#define GPIOB_DMA_IRQ                  DMA1_Stream4_IRQn
#define GPIOB_DMA_FLAG_TC              DMA_FLAG_TCIF4
#define GPIOB_DMA_FLAG_HT              DMA_FLAG_HTIF4
#define GPIOB_DMA_FLAG_FE              DMA_FLAG_FEIF4
#define GPIOB_DMA_FLAG_TE              DMA_FLAG_TEIF4
#define GPIOB_DMA_FLAG_DME             DMA_FLAG_DMEIF4
#define GPIOB_DMA_PERIPH_DATA_SIZE     DMA_PeripheralDataSize_HalfWord
#define GPIOB_DMA_MEM_DATA_SIZE        DMA_MemoryDataSize_HalfWord
#define DMA_MAX_SZE                    0xFFFF

#define GPIOB_DMA_TCIF                   DMA_IT_TCIF4
#define GPIOB_IRQHandler               DMA1_Stream4_IRQHandler

可监控DMA1的寄存器,DMA1_S4M0AR以及DMA1_S4PAR都不是我所期望的数值。

3.在IAR下改用Simulator进行软件仿真,所有显示数据与我设计的期望值完全一致。

问题是,J-LINK的报错是源于硬件电路板的什么问题吗?采用ST-LINK调试与simulator的结果不一致,问题出在哪里呢?是纯硬件上的问题还是我软件上有bug啊?

希望大家知无不言哦。

使用特权

评论回复
板凳
acgean| | 2012-3-22 12:25 | 只看该作者
J-LINK的报错是源于硬件电路板的什么问题吗?
连接问题,地线连接,噪声干扰

采用调试器与simulator的结果不一致,问题出在哪里呢?
通常是硬件的因素。

使用特权

评论回复
地板
lorelia14|  楼主 | 2012-3-22 13:10 | 只看该作者
谢谢3楼的回复。

已经查出来J-LINK报错是因为设置DMA数据传输时使用了端口GPIOB,占用了JTAG的端口,导致J-LINK不能正常工作。将GPIOB换成GPIOG作为DMA外设数据输出,则上述问题都解决了。

可遇到一个新的问题,用示波器监控GPIOG的端口波形,没有检测到有信号变化。我在memory中预先放置了数据的,如果能够正常输出,应该有波形才对,那是DMA没有正常传递数据到外设吗?怎么知道DMA工作正常不正常呢?

还请赐教!

使用特权

评论回复
5
i55| | 2012-3-22 13:56 | 只看该作者
用SWD模式JLINK只占用PA13和PA14两条腿,GPIOB完全不占用。

使用特权

评论回复
6
lorelia14|  楼主 | 2012-3-22 16:35 | 只看该作者
楼上说的不错,我第一次用J-LINK,还没有注意到可以用SWD模式。
现在直接调用STM32F207的官方例程,进行memory-to-memory的DMA传递,可目标存储空间里的数据仍旧为0,没有发生变化,说明DMA传送的确没有成功,问题存在哪里呢?

下面还是列出程序来,有经验的朋友来指点一下吧:

int main(void)
{
  RCC_ClocksTypeDef RCC_Clocks;
  SystemInit();
       
  RCC_GetClocksFreq(&RCC_Clocks);
  SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);

  NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x00);
  NVIC_Configuration();// NVIC configuration
  GPIO_Init_Configuration();

  /* Initialize LEDs and LCD available on STM322xG-EVAL board *****************/

  STM_EVAL_LEDInit(LED2);
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDInit(LED4);

  /* Turn on LEDs available on STM322xG-EVAL **********************************/
  STM_EVAL_LEDOn(LED2);

  /* Configure and enable the DMA Stream for Memory to Memory transfer */
  DMA_Config_1();

  /* while (DMA_GetCurrentMemoryTarget(DMA_STREAM) != 0) */  /* First method */
  while (DMA_GetCmdStatus(DMA1_Stream0) != DISABLE)            /* Second method */
  {
    /*
       Since this code present a simple example of how to use DMA, it is just
       waiting on the end of transfer.
       But, while DMA Stream is transferring data, the CPU is free to perform
       other tasks in parallel to the DMA transfer.
    */
  }
   
  /* Infinite loop */
  while (1)
  {
    /* Toggle LD2 */
    STM_EVAL_LEDToggle(LED2);

    /* Insert 50 ms delay */
    Delay(5);
  }
}

void DMA_Config_1(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  DMA_InitTypeDef  DMA_InitStructure;
  __IO uint32_t    Timeout = TIMEOUT_MAX;
   
  /* Enable DMA clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  
  /* Reset DMA Stream registers (for debug purpose) */
  DMA_DeInit(DMA1_Stream0);

  /* Check if the DMA Stream is disabled before enabling it.
     Note that this step is useful when the same Stream is used multiple times:
     enabled, then disabled then re-enabled... In this case, the DMA Stream disable
     will be effective only at the end of the ongoing data transfer and it will
     not be possible to re-configure it before making sure that the Enable bit
     has been cleared by hardware. If the Stream is used only once, this step might
     be bypassed. */
  while (DMA_GetCmdStatus(DMA1_Stream0) != DISABLE)
  {
  }
  
  /* Configure DMA Stream */
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)DST_Buffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
  DMA_InitStructure.DMA_BufferSize = (uint32_t)BUFFER_SIZE;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA1_Stream0, &DMA_InitStructure);
   
  /* Enable DMA Stream Transfer Complete interrupt */
  DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);

  /* DMA Stream enable */
  DMA_Cmd(DMA1_Stream0, ENABLE);

  /* Check if the DMA Stream has been effectively enabled.
     The DMA Stream Enable bit is cleared immediately by hardware if there is an
     error in the configuration parameters and the transfer is no started (ie. when
     wrong FIFO threshold is configured ...) */
  Timeout = TIMEOUT_MAX;
  while ((DMA_GetCmdStatus(DMA1_Stream0) != ENABLE) && (Timeout-- > 0))
  {
  }
   
  /* Check if a timeout condition occurred */
  if (Timeout == 0)
  {
    /* Manage the error: to simplify the code enter an infinite loop */
    while (1)
    {
    }
  }

  /* Enable the DMA Stream IRQ Channel */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);     
}

使用特权

评论回复
7
lorelia14|  楼主 | 2012-3-23 09:22 | 只看该作者
终于有了一点进展,还是要仔细看资料才行。发现由软件触发的memory-to-memory的数据传递只支持DMA2,而我原先调用例程时,直接选择了DMA1,所以不能成功。但对于memory-to-peripheral的DMA传递,还要继续查找失败的原因。

使用特权

评论回复
8
lorelia14|  楼主 | 2012-3-23 16:43 | 只看该作者
没人顶,自己再顶!

纠结于memory-to-peripheral的DMA传递,感觉问题在于DMA配置后无法启动DMA传输。从寄存器状态来看,DMA2_S4CR的EN=1,TCIE=1,可DMA2_S4NDTR的数值始终保持为初始值不变。难道需要由外设触发DMA的传递?在memory-to-peripheral的传输模式下,应该在DMA2_S4CR的EN置为1后自动启动嘛,难道我理解的不对?

使用特权

评论回复
9
aozima| | 2012-3-23 17:49 | 只看该作者
“memory-to-peripheral的传输模式下"
DMA只能被peripheral触发(在peripheral中打开DMA请求)。

STM32中,peripheral请求与DMA的通道有对应关系。做与外设相关的DMA操作时,要选择对应的DMA通道。
且多个外设会共用同一个通道,自己处理复用关系(如果有)。

使用特权

评论回复
10
lorelia14|  楼主 | 2012-3-29 16:55 | 只看该作者
谢谢!再请教,我想采用定时器触发DMA,对定时器应该怎样配置呢?看英文文档云里雾里的,而找例程又与我的要求不一致,修改总不成功。
默认用TIM3来触发,采用的是DMA1_Stream4,下面是我的简单配置代码,结果对定时器的配置始终无效,请指点一二吧:
void DMA_Config_1(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  DMA_InitTypeDef  DMA_InitStructure;
  __IO uint32_t    Timeout = TIMEOUT_MAX;
   

  /* Enable DMA clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  /* GPIOA clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  
  /* GPIOA Configuration: PA6(TIM3 CH1) as alternate function push-pull ------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Connect TIM pins to AF1 */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);
  /* Reset DMA Stream registers (for debug purpose) */
  DMA_DeInit(DMA1_Stream4);

  /* Check if the DMA Stream is disabled before enabling it.
     Note that this step is useful when the same Stream is used multiple times:
     enabled, then disabled then re-enabled... In this case, the DMA Stream disable
     will be effective only at the end of the ongoing data transfer and it will
     not be possible to re-configure it before making sure that the Enable bit
     has been cleared by hardware. If the Stream is used only once, this step might
     be bypassed. */
  while (DMA_GetCmdStatus(DMA1_Stream4) != DISABLE)
  {
  }
  
  /* Configure DMA Stream */
  DMA_InitStructure.DMA_Channel = DMA_Channel_5;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)GPIOB_DMA_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SRC_Const_Buffer;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = (uint32_t)BUFFER_SIZE*4;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA1_Stream4, &DMA_InitStructure);
   
  /* Enable DMA Stream Transfer Complete interrupt */
  DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);

  /* DMA Stream enable */
  DMA_Cmd(DMA1_Stream4, ENABLE);

  /* Check if the DMA Stream has been effectively enabled.
     The DMA Stream Enable bit is cleared immediately by hardware if there is an
     error in the configuration parameters and the transfer is no started (ie. when
     wrong FIFO threshold is configured ...) */
  Timeout = TIMEOUT_MAX;
  while ((DMA_GetCmdStatus(DMA1_Stream4) != ENABLE) && (Timeout-- > 0))
  {
  }
   
  /* Check if a timeout condition occurred */
  if (Timeout == 0)
  {
    /* Manage the error: to simplify the code enter an infinite loop */
    while (1)
    {
    }
  }

        TIM_TimeBaseStructure.TIM_Period = 0xFFFF;                                       
        TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 24000000) - 1;                         
        TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;               
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

        TIM_DMACmd(TIM3, TIM_DMA_Trigger, ENABLE);
        TIM_Cmd(TIM3, ENABLE);

  /* Enable the DMA Stream IRQ Channel */
/*
  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);     
*/

  while(DMA_GetITStatus(DMA1_Stream4, DMA_IT_TCIF4)!= RESET)
  {
  }
        /* Clear DMA Stream Transfer Complete interrupt pending bit */
        DMA_ClearITPendingBit(DMA1_Stream4, DMA_IT_TCIF4);       
       
        /* Turn LED3 on: End of Transfer */
//        STM_EVAL_LEDOn(LED3);

}

使用特权

评论回复
11
pluto55| | 2013-1-15 11:25 | 只看该作者
本帖最后由 pluto55 于 2013-1-15 14:55 编辑
lorelia14 发表于 2012-3-22 16:35
楼上说的不错,我第一次用J-LINK,还没有注意到可以用SWD模式。
现在直接调用STM32F207的官方例程,进行mem ...


楼主查出来什么原因了吗,最近也在搞DMA memorytomemory...

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

27

帖子

0

粉丝