На какой частоте работает DMA? STM32

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: На какой частоте работает DMA? STM32

Сообщение Аlex »

ПростоНуб писал(а):доступа к памяти
К какой памяти ?
У меня ДМА читает по FMC из SDRAM и кидает по FSMC в дисплей. Где тут оперативка нарисовалась ? :)))
Реклама
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Re: На какой частоте работает DMA? STM32

Сообщение ПростоНуб »

[uquote="Аlex",url="/forum/viewtopic.php?p=3580575#p3580575"]
ПростоНуб писал(а):доступа к памяти
К какой памяти ?
У меня ДМА читает по FMC из SDRAM и кидает по FSMC в дисплей. Где тут оперативка нарисовалась ? :)))[/uquote]
А где-то указано, что bus matrix может пропускать одновременно несколько потоков?
The bus matrix implements round-robin scheduling, thus ensuring at least half of the system bus bandwidth (both to memory and peripheral) for the CPU.
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: На какой частоте работает DMA? STM32

Сообщение Аlex »

Откуда я знаю, где и что указано :) Я вижу то, что я вижу. А вижу я костыльную работу DMA.
Иначе, для чего он вообще нужен, если не умеет нормально отрабатывать что обязан ?
Тут ему освободи, там дай дорогу, ... :facepalm:
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: На какой частоте работает DMA? STM32

Сообщение Reflector »

[uquote="Аlex",url="/forum/viewtopic.php?p=3580566#p3580566"]Да.[/uquote]
Попробуй Burst для SDRAM включить, хотя можно попробовать включить его и для DMA, на 4 непрерывные передачи, т.к. FIFO чтения у SDRAM 6x32-бит. И еще, не знаю как там у тебя сделано, но на F4 DMA может читать по 32 бита и два раза писать по 16, это должно меньше загружать шину.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: На какой частоте работает DMA? STM32

Сообщение Аlex »

Burst для SDRAM включен. FIFO пробовал подрубать - без изменений.

Добавлено after 1 minute 25 seconds:
Reflector писал(а):на F4 DMA может читать по 32 бита и два раза писать по 16, это должно меньше загружать шину.
Хм.. Интересно...
Дома буду - поколупаю на эту тему.
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: На какой частоте работает DMA? STM32

Сообщение Reflector »

[uquote="Аlex",url="/forum/viewtopic.php?p=3580647#p3580647"]Burst для SDRAM включен. FIFO пробовал подрубать - без изменений.[/uquote]
Для самого DMA Burst включал?
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: На какой частоте работает DMA? STM32

Сообщение Аlex »

Сейчас трудно сказать, что я включал, а что нет. Доберусь до дома, гляну код - может вспомню.
Помню что-то с FIFO было.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: На какой частоте работает DMA? STM32

Сообщение Аlex »

Такс... Добрался я до компа, наконец то.
Выкладываю код напоказ :)
DMA:
Спойлер

Код: Выделить всё


static DMA_InitTypeDef       	dma;
static __IO 	int32_t     	dma_cnt;
static __IO		uint8_t   		* p_dist;
static __IO		uint8_t   		* p_sourse;
static __IO 	uint8_t 		inc_dist=0;
static __IO 	uint8_t 		inc_sourse=0;

/*********************************************************************************/
void dma_m2m_init(){
	//-------------------------------------------------
	RCC->AHB1ENR |= RCC_AHB1Periph_DMA2;
	//-------------------------------------------------
	dma.DMA_Channel = DMA_Channel_0;
	//    dma.DMA_PeripheralBaseAddr = (uint32_t)lcd_buf;
//	dma.DMA_Memory0BaseAddr = (uint32_t)FMC_DATA_ADDRR;
	dma.DMA_DIR = DMA_DIR_MemoryToMemory;
	//    dma.DMA_BufferSize = (size);
	dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
	dma.DMA_MemoryInc = DMA_MemoryInc_Disable;
	dma.DMA_PeripheralDataSize = DMA_MemoryDataSize_HalfWord;
	dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	dma.DMA_Mode = DMA_Mode_Normal;
	dma.DMA_Priority = DMA_Priority_VeryHigh;		// DMA_Priority_Low;
	dma.DMA_FIFOMode = DMA_FIFOMode_Enable;			// DMA_FIFOMode_Disable;
	dma.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;	// DMA_FIFOThreshold_1QuarterFull;
	dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	DMA_Init(DMA2_Stream0, &dma);
	NVIC_EnableIRQ(DMA2_Stream0_IRQn);
	DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
}
/*********************************************************************************/

/*********************************************************************************/
void DMA2_Stream0_IRQHandler(void){
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) == SET){
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
    DMA_Out();
}
}
/*********************************************************************************/


/*********************************************************************************/
static void DMA_Out(){
static uint32_t    	dma_size_out=0;

    if(dma_cnt<=0){
      	DMA_End();
      	return;
    }
    if(dma_cnt<=50000)          dma_size_out = dma_cnt;
    else                        dma_size_out = 50000;
    dma_cnt -= dma_size_out;
    //------------------------------------------------------------
    DMA2_Stream0->M0AR =(__IO uint32_t)p_sourse ;
    DMA2_Stream0->PAR =(__IO uint32_t)p_dist ;
    DMA2_Stream0->NDTR = dma_size_out;
    DMA2_Stream0->CR |= DMA_SxCR_EN;
    if(inc_dist)	p_dist+=dma_size_out;
    if(inc_sourse)	p_sourse+=dma_size_out;
}
/*********************************************************************************/

/*********************************************************************************/
void dma_m2m_send(void *dist, uint8_t dist_inc, void *sourse, uint8_t sourse_inc, uint32_t size){
	p_dist = (uint8_t*)dist;
	p_sourse = (uint8_t*)sourse;
	dma_cnt = size;
	inc_dist = dist_inc;
	if(dist_inc)			DMA2_Stream0->CR |= DMA_SxCR_PINC;
	else					DMA2_Stream0->CR &= ~DMA_SxCR_PINC;
	inc_sourse = sourse_inc;
	if(sourse_inc)			DMA2_Stream0->CR |= DMA_SxCR_MINC;
	else					DMA2_Stream0->CR &= ~DMA_SxCR_MINC;
    DMA_Out();
}
/*********************************************************************************/

Инит SDRAM :
Спойлер

Код: Выделить всё

void SDRAM_Init(void)
{
  FMC_SDRAMInitTypeDef  FMC_SDRAMInitStructure;
  FMC_SDRAMTimingInitTypeDef  FMC_SDRAMTimingInitStructure; 
  
  /* GPIO configuration for FMC SDRAM bank */
  SDRAM_GPIOConfig();
  
  /* Enable FMC clock */
  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
 
/* FMC Configuration ---------------------------------------------------------*/
/* FMC SDRAM Bank configuration */   
  /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */
  /* TMRD: 2 Clock cycles */
  FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay    = 2;	//2;
  /* TXSR: min=70ns (7x11.11ns) */
  FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;	//7;
  /* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
  FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime      = 4;
  /* TRC:  min=70 (7x11.11ns) */        
  FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay        = 7;        // 7;
  /* TWR:  min=1+ 7ns (1+1x11.11ns) */
  FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime    = 2;        // 2;
  /* TRP:  20ns => 2x11.11ns */
  FMC_SDRAMTimingInitStructure.FMC_RPDelay              = 2;        // 2;
  /* TRCD: 20ns => 2x11.11ns */
  FMC_SDRAMTimingInitStructure.FMC_RCDDelay             = 2;        // 2;

/* FMC SDRAM control configuration */
  FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank2_SDRAM;
  /* Row addressing: [7:0] */
  FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
  /* Column addressing: [11:0] */
  FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
  FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH;
  FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
  FMC_SDRAMInitStructure.FMC_CASLatency = SDRAM_CAS_LATENCY; 
  FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
  FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDCLOCK_PERIOD;  
  FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Enable;
  FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_0;
  FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
  
  /* FMC SDRAM bank initialization */
  FMC_SDRAMInit(&FMC_SDRAMInitStructure);
  
  /* FMC SDRAM device initialization sequence */
  SDRAM_InitSequence(); 
  
}
Кусок основного кода :
Спойлер

Код: Выделить всё

static uint16_t	SDRAM	buf_sdram[384000];

/*********************************************************************************/
void Main_Task(void *pvParameters) {
    OS_Delay(100 Ms);

 	LCD_SetArea(0,0,799,479);

 	uint16_t rgb = RGB565CONVERT(200, 100, 100);

    while(1){
        OS_Delay(100 Ms);
        //---------------------------------------
        GPIO_SetBits(GPIOG, GPIO_Pin_14);
        //---------------------
        //dma_m2m_send(rgb, 0, buf_sdram, 1, 384000*2);
        //wait_dma();
        for(uint32_t i=0; i<384000;i++)		buf_sdram[i]=rgb;
        //---------------------
        GPIO_ResetBits(GPIOG, GPIO_Pin_14);
        //---------------------------------------
        GPIO_SetBits(GPIOG, GPIO_Pin_13);
        //---------------------
        LCD_MemStart();
        //dma_m2m_send(buf_sdram, 1, (void*)0x60020000, 0, sizeof(buf_sdram));
        //wait_dma();
        for(uint32_t i=0; i<384000;i++)	*(uint16_t*)0x60020000 = buf_sdram[i];
        //---------------------
        GPIO_ResetBits(GPIOG, GPIO_Pin_13);


    }
}
/*********************************************************************************/
Вот, как то так... :roll:

Добавлено after 1 hour 12 minutes 54 seconds:

Вот такие настройки

Код: Выделить всё

	dma.DMA_MemoryBurst = DMA_MemoryBurst_INC8;		//DMA_MemoryBurst_Single ;
	dma.DMA_PeripheralBurst = DMA_PeripheralBurst_INC8;		// DMA_PeripheralBurst_Single;
сделали время обновления = 18 мс. Это потрясающий результат :shock:

Reflector, спасибо большое за наводки. Вы спасли мою надежду :beer:
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: На какой частоте работает DMA? STM32

Сообщение Аlex »

Продолжаю эксперименты.
Подрубил DMA2D, сделал вывод в экран через него. На удивление, он это делает ещё быстрее, порядка 12 ms. Не знаю ка кон это делает, но сдаётся мне периферия уже на пределе.
Это получается ~30 ns на одну итерацию (чтение слова с SDRAM + запись его в дисплей).
Останусь, пожалуй, на этом варианте. Это избавит меня от дополнительного буфера, т.к. он уже имеется в SSD1963, и смысла создавать ещё один нет. Буду рисовать прямиком в него. Тем более, DMA2D имеет ещё бонусом всякие плюшки, типа смешивание цветов с прозрачностью, заливка областей, аппаратное преобразование из ARGB8888 в RGB565, и т.д...
Ответить

Вернуться в «ARM»