2015-01-27 05:10 AM
I'm new to STM32 board.
Working with F103C8, currently I could use TIM2 (24M) as trigger source to start DMA1 to transfer data from GPIOB->IDR(15:0) to RAM. However I found the speed is no more than 8MHz during the DMA transfer process, and info-loss occurs sometimes.Is it possible to achieve a 12MHz or higher speed(cause input data in GPIO pins vary in 12MHz or higher speed) data-transfer from GPIO pins to RAM using DMA on F103C8 ? If not, is there any other ways to achieve it(with or without DMA) on F103C8 ? #gpio #dma #speed2015-01-27 05:53 AM
What Clock frequncy do you have? Is your timer running at highest possible frequency? DMA events need synchronisation clock cycles and with higher clock less time is needed for that synchronisation.
2015-01-27 06:03 AM
Would DMA2 clock quicker?
2015-01-28 04:12 AM
My trigger clock frequency is 24MHz, and I connect PA6 with PB0 on my board to change GPIOB->IDR data in a 1MHz frequency, and monitor GPIOB->IDR data using GPIO_DATA[] array.
Below is my test code:#include ''stm32f10x.h''
#define BufferSize 1600
uint16_t GPIO_DATA[BufferSize];
void RCC_Configuration(void)
{
// clock for DMA
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// clock for TIM2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);
// clock for GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Init PB0-PB15 for DMA source */
GPIO_InitStructure.GPIO_Pin = 0xFFFF; //Pin0 .. Pin15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
/* Configure TIM3 Channel1 PWM output */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void PWM_Configuration(void){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Time Base configuration */
TIM_DeInit(TIM3);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 71;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
/* Channel1 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 36;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_Cmd(TIM3, ENABLE);
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOB->IDR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)GPIO_DATA;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel2, ENABLE);
}
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = 3; // 24M
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 1;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
PWM_Configuration();
DMA_Configuration();
TIM2_Configuration();
while(1){
};
}
2015-01-28 04:26 AM
Clive,thanks for your advice, I've modify my test code to enable DMA2, but it doesn't work. I'm using F103C8 whose flash is 64K, I'm not sure whether it has DMA2 module.
Below is my test code, I don't know why it doesn't work:#include ''stm32f10x.h''
#define BufferSize 1600
uint16_t GPIO_DATA[BufferSize];
void RCC_Configuration(void)
{
// clock for DMA
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5 | RCC_APB1Periph_TIM3, ENABLE);
// clock for GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//Init PB0-PB7 for DMA source
GPIO_InitStructure.GPIO_Pin = 0xFFFF; //Pin0 .. Pin15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
/* Configure TIM3 Channel1 PWM output */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void PWM_Configuration(void){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Time Base configuration */
TIM_DeInit(TIM3);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 71;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
/* Channel1 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 36;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_Cmd(TIM3, ENABLE);
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA2_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOB->IDR; // Source
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)GPIO_DATA; // Destination
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // So we can pace via trigger
DMA_Init(DMA2_Channel2, &DMA_InitStructure);
DMA_ITConfig(DMA2_Channel2, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Channel2, ENABLE);
}
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = 2; // 24M
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 1;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
// ''connecting'' DMA and TIM5
TIM_DMACmd(TIM5, TIM_DMA_Update, ENABLE);
// turning on TIM5
TIM_Cmd(TIM5, ENABLE);
}
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
PWM_Configuration();
DMA_Configuration();
TIM_Configuration();
while(1){
};
}
2015-01-28 04:50 AM
Ok.
You caught theTIM_TimeBaseStructure.TIM_Period = 3-1; // 24M
So you enabled a TC interrupt, but I don't see any service code. If you toggle a GPIO at TC what frequency do you observe? What data are you observing for the looped back 1 MHz?
24 MHz be a bit aggressive, I'd think the saturation point of the bus is going to be somewhat lower than that. I haven't actively used F1 parts in years. On other parts the DCMI offers quite a fast parallel capture, but not at 16-bit. Other examples with fast capture could use an external FIFO, like the ones stuck on CMOS Cameras.
2015-01-28 05:48 AM
Sorry for my unclear description. No TC interrupt are used, in fact, I'm using a F103 develop board, and I init a 1MHz PWM using TIM3 and output it in PA6. Then I connect PA6 with PB0 using a DuPont line, so the content of GPIOB->IDR varies in 1MHz frequency. At last I use DMA which trigged by TIM5(24MHz clock) to store GPIOB->IDR into GPIO_DATA[] array. So I could check DMA speed by observe GPIO_DATA[], it should be in a period of 12 low data then 12 high data if 24M speed DMA is available for my dev board.
BTW: 24MHz is just a test, my requirement is 12MHz while the result after my experiment shows only 7MHz.2015-01-28 06:16 AM
What is the system clock and how is the system bus and the DMA controller loaded (i.e. what other ''processes'' do you expect to run simultaneously)?
How do you expect to process the captured data? Also, the 'F1 line is slightly obsolete and has certain limitations, e.g. GPIO is on APB, i.e. behind a bridge. You might want to consider 'F2 perhaps, or even 'F4, which would allow also higher system clocks. JW