Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Внешние DMA запросы в STR91
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Thunderbird
Хочу организовать пересылку данных из памяти в SPI через DMA по приходу внешнего DMA запроса
Ничего не выходит... Просветите, в чем косяк

Данные для пересылки храняться в массиве SSP1_Buffer_Tx, запрос приходит на ногу P0.3

Код
// Конфигурим ногу для внешнего DMA запроса

   GPIO_InitStruct.GPIO_Pin =         GPIO_Pin_0;
   GPIO_InitStruct.GPIO_Direction =   GPIO_PinInput;
   //GPIO_InitStruct.GPIO_Type=         GPIO_Type_PushPull;
   GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Enable;
   GPIO_InitStruct.GPIO_Alternate=    GPIO_InputAlt1;
  
   GPIO_Init (GPIO3, &GPIO_InitStruct);
  
  
  
// Конфигурим DMA
  
  DMA_DeInit();
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_Channel_LLstItm= 0;
  DMA_InitStruct.DMA_Channel_SrcAdd= (u32)&SSP1_Buffer_Tx;
  DMA_InitStruct.DMA_Channel_DesAdd=(u32)(&SSP1->DR);
  DMA_InitStruct.DMA_Channel_SrcWidth= DMA_SrcWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesWidth= DMA_DesWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesBstSize = DMA_DesBst_1Data;
  DMA_InitStruct.DMA_Channel_FlowCntrl=  DMA_FlowCntrl1_DMA;
  DMA_InitStruct.DMA_Channel_Des = DMA_SRC_External_Req0;
  DMA_InitStruct.DMA_Channel_TrsfSize = 16;  
  DMA_Init(DMA_Channel0,&DMA_InitStruct);
  DMA_ChannelSRCIncConfig (DMA_Channel0, ENABLE);
  DMA_ChannelDESIncConfig (DMA_Channel0, ENABLE);
  DMA_ITConfig(DMA_Channel0, ENABLE);
  DMA_ITMaskConfig(DMA_Channel0, DMA_ITMask_ITC, ENABLE);
  DMA_ChannelCmd (DMA_Channel0,ENABLE);
  DMA_Cmd(ENABLE);
MALLOY2
насколько я понимаю все работать должно подругому, нужно настроить DMA на совместную работу с SPI, имеется ввиду flow control, соответствующие настройки сделать и в модуле SPI, а по внешнему сигналу за пускать SPI, а SPI запустит DMA.
Thunderbird
У меня ситуация такая: 16 АЦП, соединенных в цепочку, таймер генерит сигнал преобразования, шириной 2мкс и периодом 800мкс, по спаду импульса должен запускаться DMA и опрашивать АЦП. Сделано так: с выхода таймера, через инвертор, импульс подается на вход внешнего запроса DMA. Пока пытаюсь выдавать произвольные данные, чтобы получить клок на считывание АЦП. Нифига DMA не запускается :-( Вариант с программным запуском SPI не катит, проц должен осуществлять опрос АЦП автоматически, не отвлекаясь на запуски SPI и тп геморрой. Неужели такое невозможно? Зачем тогда нужны входы внешнего запроса DMA?
MALLOY2
а вы не думали что DMA будет забирать данные с регистра SPI быстрее чем он их туда положит ? синхронизация толжна быть однозначно. Следовательно если есть синхронизация значит процессом копирования не DMA управляет а в вашем случае SPI. А внешний запуск DMA нужен для запуска копирования в режиме не требующего синхронизации, конечно можно еще много всяких левых вариантов придумать.

В вашем случае невижу никаких проблем.

Если таймер внешний, то выход заведите на внешнеее прерывание, можно даже FIQ. В прерывании запускаете SPI. Естественно DMA должен быть запрограммирован на нужный размер блока данных который вы желаеете получить, надеюсь вы не по 1 байту пересылаете smile.gif. Это в том случае если SPI работает в режиме MASTER. Если SPI работает в режиме SLAVE то тут вобще сказка, ничего запускать не надо, создаете на DMA кольцевой буфер, запускаете ПДП и SPI и все будет автоматом крутится, а по внешнему прерыванию начинаете вашу обработку, примерно так.
Thunderbird
Что-то не совсем понимаю как запустить SPI в режиме DMA. Исходником не поможете?
Согласно даташиту условием запуска DMA является Half FIFO level reached. Это , что получается я должен забить половину FIFO для запуска DMA???
MALLOY2
Цитата
Согласно даташиту условием запуска DMA является Half FIFO level reached. Это , что получается я должен забить половину FIFO для запуска DMA???

точно не помню нет мануала под рукой, все там должно настраиваться

для начала, опишите детальнее схему, кто генерит сигналы, какие АЦП, в каком режиме работает SPI ?
Thunderbird
АЦП AD7687, сигнал на начало преобразования генерится таймером, SPI работает мастером. Сам по себе SPI работает. При попытке вывести произвольные данные через SPI в режиме DMA (для генерации клока для выборки данных из АЦП) - тишина. Должен ли SPI после конфигурации DMA , прописывании адресов источника и приемника и его (DMA) запуска сам начинать выдавать данные, или же нужны какие-то еще манипуляции?
MALLOY2
вот прилагаю файлик может чем поможет.

у меня правда АЦП AD73360, и я работаю в слейв режиме.
Нажмите для просмотра прикрепленного файла
AlexandrY
Хоть я и не пользуюсь этой кривой библиотекой от ST, но тут невооруженым глазом видно, что включен инкремент адреса назначения.
Для SPI это как то не логично мягко говоря.


Цитата(Thunderbird @ Sep 18 2007, 08:51) *
Хочу организовать пересылку данных из памяти в SPI через DMA по приходу внешнего DMA запроса
Ничего не выходит... Просветите, в чем косяк

Данные для пересылки храняться в массиве SSP1_Buffer_Tx, запрос приходит на ногу P0.3

Код
// Конфигурим ногу для внешнего DMA запроса

   GPIO_InitStruct.GPIO_Pin =         GPIO_Pin_0;
   GPIO_InitStruct.GPIO_Direction =   GPIO_PinInput;
   //GPIO_InitStruct.GPIO_Type=         GPIO_Type_PushPull;
   GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Enable;
   GPIO_InitStruct.GPIO_Alternate=    GPIO_InputAlt1;
  
   GPIO_Init (GPIO3, &GPIO_InitStruct);
  
  
  
// Конфигурим DMA
  
  DMA_DeInit();
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_Channel_LLstItm= 0;
  DMA_InitStruct.DMA_Channel_SrcAdd= (u32)&SSP1_Buffer_Tx;
  DMA_InitStruct.DMA_Channel_DesAdd=(u32)(&SSP1->DR);
  DMA_InitStruct.DMA_Channel_SrcWidth= DMA_SrcWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesWidth= DMA_DesWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesBstSize = DMA_DesBst_1Data;
  DMA_InitStruct.DMA_Channel_FlowCntrl=  DMA_FlowCntrl1_DMA;
  DMA_InitStruct.DMA_Channel_Des = DMA_SRC_External_Req0;
  DMA_InitStruct.DMA_Channel_TrsfSize = 16;  
  DMA_Init(DMA_Channel0,&DMA_InitStruct);
  DMA_ChannelSRCIncConfig (DMA_Channel0, ENABLE);
  DMA_ChannelDESIncConfig (DMA_Channel0, ENABLE);
  DMA_ITConfig(DMA_Channel0, ENABLE);
  DMA_ITMaskConfig(DMA_Channel0, DMA_ITMask_ITC, ENABLE);
  DMA_ChannelCmd (DMA_Channel0,ENABLE);
  DMA_Cmd(ENABLE);
Thunderbird
Что с инкрементом, что без - один фиг не работает sad.gif
MALLOY2
Вобщем выложи полностью код инициализации SPI, DMA, а также обслуживающие функции запуска остановки и т.д.
Thunderbird
Цитата(MALLOY2 @ Sep 20 2007, 12:46) *
Вобщем выложи полностью код инициализации SPI, DMA, а также обслуживающие функции запуска остановки и т.д.

Код
/* Includes ------------------------------------------------------------------*/

//#include    "includes.h"
#include    "91x_conf.h"
#include    "91x_lib.h"
#include    "cmath"

#define DMA_Tx DMA_Channel1
#define DMA_Tx_No 1
#define DMA_Tx_ENABLE DMA_Tx->CCNF |= 0x00000001
#define DMA_Tx_DISABLE DMA_Tx->CCNF &= ~0x00000001
#define DMA_Tx_ACTIVE (DMA_Tx->CCNF & 0x00020000)

#define DMA_Tx_End (DMA->TCRISR & (1<#define DMA_Tx_WaitEnd while (! DMA_Tx_End)
#define DMA_Tx_ClrEnd (DMA->TCICR = (1<#define DMA_Tx_ClrErr (DMA->EICR = (1<


volatile u32 DlyCount;

signed short SSP0_Buffer_Tx[32] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                         0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
                         0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
                         0x1C, 0x1D, 0x1E, 0x1F, 0x20};
signed short SSP1_Buffer_Tx[16] = {0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
                         0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60};
signed short SSP0_Buffer_Rx[32], SSP1_Buffer_Rx[32];
u8 Tx_Idx=0, Rx_Idx=0, k=0;

DMA_InitTypeDef  DMA_InitStruct;

/*******************************************************************************
* Function Name  : main
* Description    : Main program
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void InitClock (void)
{
  // Clock
  SCU_MCLKSourceConfig(SCU_MCLK_OSC);       // master clk - OSC clk
  // Flash controller init
  SCU_FMICLKDivisorConfig(SCU_FMICLK_Div1);
  FMI_Config(FMI_READ_WAIT_STATE_2,FMI_WRITE_WAIT_STATE_0, FMI_PWD_ENABLE,\
             FMI_LVD_ENABLE,FMI_FREQ_HIGH);
  // Set clks dividers
  SCU_RCLKDivisorConfig(SCU_RCLK_Div1);
  SCU_HCLKDivisorConfig(SCU_HCLK_Div1);
  SCU_PCLKDivisorConfig(SCU_PCLK_Div2);
  // Init PLL = 96 MHz
  SCU_PLLFactorsConfig(192,25,2);
  // PLL Enabled
  SCU_PLLCmd(ENABLE);
  // Switch clk MCLK = PLL
  SCU_MCLKSourceConfig(SCU_MCLK_PLL);
  
}

void SCU_Configuration(void)
{

  /* Enable the __SSP1 Clock */
  SCU_APBPeriphClockConfig(__SSP1 ,ENABLE);

  /* Enable the __GPIO5 for SSP0 Clock */
  //SCU_APBPeriphClockConfig(__GPIO5 ,ENABLE);

  /* Enable the __GPIO3 for SSP1 Clock */

  SCU_APBPeriphClockConfig(__GPIO3 ,ENABLE);
  
  SCU_APBPeriphClockConfig(__TIM01 ,ENABLE);
  
  SCU_AHBPeriphClockConfig(__VIC, ENABLE);
  
  SCU_AHBPeriphClockConfig(__DMA, ENABLE);


}

void Start_SSP1_TX_DMA(signed short *Bu, u16 Count)
{
  DMA_Tx_DISABLE;
  DMA_Tx->SRC=(u32)Bu;
  DMA_InitStruct.DMA_Channel_SrcWidth= DMA_SrcWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesWidth= DMA_DesWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_TrsfSize = 16;  
  DMA_Tx_ENABLE;

  

}




void Tim0Handler (void)
{

  if (TIM_GetFlagStatus(TIM0,TIM_FLAG_OC1))
    {
      TIM_ClearFlag(TIM0,TIM_FLAG_OC1);
      //SSP_SendData(SSP1, SSP1_Buffer_Tx[Tx_Idx++]);
      //SSP_SendData(SSP1, SSP1_Buffer_Tx[/*Tx_Idx++*/ 0]);
      Start_SSP1_TX_DMA(SSP1_Buffer_Tx,16);
      
    }
  if (TIM_GetFlagStatus(TIM0,TIM_FLAG_OC2))
    {
      TIM_ClearFlag(TIM0,TIM_FLAG_OC2);
      TIM_CounterCmd(TIM0, TIM_CLEAR);
      GPIO_WriteBit(GPIO3, GPIO_Pin_0, Bit_SET);
      GPIO_WriteBit(GPIO3, GPIO_Pin_0, Bit_RESET);
    }
  
}




int main()
{
  #ifdef DEBUG
    debug();
  #endif

  InitClock ();  

  SCU_AHBPeriphClockConfig(__VIC, ENABLE);
  // VIC Deinitialization
  VIC_DeInit();
  
  // __disable_interrupt();  
  SCU_Configuration();
  
//Timer init
  
   TIM_DeInit(TIM0);
  
   TIM_InitTypeDef TimerInitStruct;
  
   TIM_StructInit (&TimerInitStruct);
  
  TimerInitStruct.TIM_Mode = TIM_OCM_CHANNEL_12;
  TimerInitStruct.TIM_OC1_Modes = TIM_TIMING;
  TimerInitStruct.TIM_OC2_Modes = TIM_TIMING;
  TimerInitStruct.TIM_Clock_Source = TIM_CLK_APB;
  TimerInitStruct.TIM_Prescaler = 2-1;
  TimerInitStruct.TIM_Pulse_Length_1=48;
  TimerInitStruct.TIM_Pulse_Length_2=20000;
  TIM_Init (TIM0, &TimerInitStruct);
  TIM_ITConfig (TIM0,TIM_IT_OC1|TIM_IT_OC2,ENABLE);

   //GPIO init
   //--------------------------------------------------------------
   GPIO_DeInit(GPIO3);
  
   GPIO_InitTypeDef GPIO_InitStruct;
  
   GPIO_InitStruct.GPIO_Pin =         GPIO_Pin_0;
   GPIO_InitStruct.GPIO_Direction =   GPIO_PinOutput;
   GPIO_InitStruct.GPIO_Type=         GPIO_Type_PushPull;
   GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Disable;
   GPIO_InitStruct.GPIO_Alternate=    GPIO_OutputAlt1;
  
   GPIO_Init (GPIO3, &GPIO_InitStruct);
  

   GPIO_InitStruct.GPIO_Pin =         GPIO_Pin_5|GPIO_Pin_7;
   GPIO_InitStruct.GPIO_Direction =   GPIO_PinInput;
   GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Enable;
   GPIO_InitStruct.GPIO_Alternate=    GPIO_InputAlt1;
  
   GPIO_Init (GPIO3, &GPIO_InitStruct);
  
  
   GPIO_InitStruct.GPIO_Pin =         GPIO_Pin_4|GPIO_Pin_6;
   GPIO_InitStruct.GPIO_Direction =   GPIO_PinOutput;
   GPIO_InitStruct.GPIO_Type=         GPIO_Type_PushPull;
   GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Enable;
   GPIO_InitStruct.GPIO_Alternate=    GPIO_OutputAlt2;
  
   GPIO_Init (GPIO3, &GPIO_InitStruct);
  
  
  
   GPIO_InitStruct.GPIO_Pin =         GPIO_Pin_1;
   GPIO_InitStruct.GPIO_Direction =   GPIO_PinOutput;
   GPIO_InitStruct.GPIO_Type=         GPIO_Type_PushPull;
   GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Disable;
   GPIO_InitStruct.GPIO_Alternate=    GPIO_OutputAlt1;
  
   GPIO_Init (GPIO3, &GPIO_InitStruct);
  
    
   GPIO_InitStruct.GPIO_Pin =         GPIO_Pin_2;
   GPIO_InitStruct.GPIO_Direction =   GPIO_PinOutput;
   GPIO_InitStruct.GPIO_Type=         GPIO_Type_PushPull;
   GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Disable;
   GPIO_InitStruct.GPIO_Alternate=    GPIO_OutputAlt1;
  
   GPIO_Init (GPIO3, &GPIO_InitStruct);
  
   //--------------------------------------------------------------------------
  
  
//Èíèöèàëèçàöèÿ SPI
  
   SSP_DeInit (SSP1);
  
   SSP_InitTypeDef SSP_InitStructure;
  
   SSP_InitStructure.SSP_FrameFormat=   SSP_FrameFormat_Motorola;
   SSP_InitStructure.SSP_Mode=          SSP_Mode_Master;
   SSP_InitStructure.SSP_CPOL=          SSP_CPOL_High;
   SSP_InitStructure.SSP_CPHA=          SSP_CPHA_2Edge;
   SSP_InitStructure.SSP_DataSize=      SSP_DataSize_16b;
   SSP_InitStructure.SSP_SlaveOutput=   SSP_SlaveOutput_Disable;
   SSP_InitStructure.SSP_ClockRate=     3;
   SSP_InitStructure.SSP_ClockPrescaler=12;
  
   SSP_Init(SSP1, &SSP_InitStructure);
   SSP_DMACmd(SSP1, SSP_DMA_Transmit, ENABLE);
   SSP_Cmd(SSP1, ENABLE);
      
  
// Èíèöèàëèçàöèÿ DMA
  
/*
  DMA_DeInit();
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_Channel_LLstItm= 0;
  DMA_InitStruct.DMA_Channel_SrcAdd= (u32)&SSP1_Buffer_Tx;
  DMA_InitStruct.DMA_Channel_DesAdd=(u32)(&SSP1->DR);
  DMA_InitStruct.DMA_Channel_SrcWidth= DMA_SrcWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesWidth= DMA_DesWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesBstSize = DMA_DesBst_1Data;
  DMA_InitStruct.DMA_Channel_FlowCntrl=  DMA_FlowCntrl1_DMA;
  DMA_InitStruct.DMA_Channel_Src = DMA_SRC_SSP1_TX;
  DMA_InitStruct.DMA_Channel_Des = DMA_DES_SSP1_TX;
  DMA_InitStruct.DMA_Channel_TrsfSize = 16;
  DMA_SyncConfig(DMA_SSP1_TX_Mask, ENABLE);

  DMA_Init(DMA_Channel0,&DMA_InitStruct);
  DMA_ChannelSRCIncConfig (DMA_Channel0, ENABLE);
// DMA_ChannelDESIncConfig (DMA_Channel0, ENABLE);
  DMA_ITConfig(DMA_Channel0, ENABLE);
  DMA_ITMaskConfig(DMA_Channel0, DMA_ITMask_ITC, ENABLE);
  DMA_ChannelCmd (DMA_Channel0,ENABLE);
  DMA_Cmd(ENABLE);  
  */
  
  
// Èíèöèàëèçàöèÿ êîíòðîëëåðà ïðåðûâàíèé
    
  // VIC_DeInit();

// âêëþ÷àåì ïðåðûâàíèÿ ïî òàéìåðó
  
   TIM_CounterCmd(TIM0, TIM_START);
  
   VIC_Config (TIM0_ITLine , VIC_IRQ , 1);
   VIC_Config (DMA_ITLine,   VIC_IRQ , 2);
     VIC_ITCmd(TIM0_ITLine, ENABLE);
   VIC_ITCmd(DMA_ITLine , ENABLE);
  
  // __enable_interrupt();  

    
while(1)
{
  
     // while(SSP_GetFlagStatus(SSP1, SSP_FLAG_RxFifoNotEmpty)==RESET){};
  
      
   }  
  
  
}
MALLOY2
Код
// Èíèöèàëèçàöèÿ DMA
  
/*
  DMA_DeInit();
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_Channel_LLstItm= 0;
  DMA_InitStruct.DMA_Channel_SrcAdd= (u32)&SSP1_Buffer_Tx;
  DMA_InitStruct.DMA_Channel_DesAdd=(u32)(&SSP1->DR);
  DMA_InitStruct.DMA_Channel_SrcWidth= DMA_SrcWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesWidth= DMA_DesWidth_HalfWord;
  DMA_InitStruct.DMA_Channel_DesBstSize = DMA_DesBst_1Data;
  DMA_InitStruct.DMA_Channel_FlowCntrl=  DMA_FlowCntrl1_DMA; <- ОШИБКА  DMA_InitStruct.DMA_Channel_Src = DMA_SRC_SSP1_TX;
  DMA_InitStruct.DMA_Channel_Des = DMA_DES_SSP1_TX;
  DMA_InitStruct.DMA_Channel_TrsfSize = 16;
  DMA_SyncConfig(DMA_SSP1_TX_Mask, ENABLE);


Не помню как зовется дефайн, но там должног быть указана свинхронизация к SPI
Thunderbird
Включено: DMA_SyncConfig(DMA_SSP1_TX_Mask, ENABLE);
Один фиг не работает....
MALLOY2
Незнаю что вам еще посоветовать, я в своей жизни 1 раз работал с этой кривой библиотекой, так как пришлось править чужой код в кроссворксе. Попробуйте уйти от библиотеки и работать на прямую. При данном подходе есть 1 большой + вы как минимум 1 раз просмотрите все биты всех регистров. Я не исключаю глюки в библиотеке.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.