Страницы

Страницы

четверг, 15 июня 2017 г.

SDRAM + LTDC + DMA2D init CMSIS

#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)

// *** Биты контроллера FMC ***
// Программирование контроллера

#define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000)
#define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001)
#define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002)
#define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003)

#define FMC_RowBits_Number_11b ((uint32_t)0x00000000)
#define FMC_RowBits_Number_12b ((uint32_t)0x00000004)
#define FMC_RowBits_Number_13b ((uint32_t)0x00000008)

#define FMC_NORSRAM_MemoryDataWidth_8b ((uint32_t)0x00000000)
#define FMC_NORSRAM_MemoryDataWidth_16b ((uint32_t)0x00000010)
#define FMC_NORSRAM_MemoryDataWidth_32b ((uint32_t)0x00000020)

#define FMC_InternalBank_Number_2 ((uint32_t)0x00000000)
#define FMC_InternalBank_Number_4 ((uint32_t)0x00000040)

#define FMC_CAS_Latency_1 ((uint32_t)0x00000080)
#define FMC_CAS_Latency_2 ((uint32_t)0x00000100)
#define FMC_CAS_Latency_3 ((uint32_t)0x00000180)

#define FMC_Write_Protection_Disable ((uint32_t)0x00000000)
#define FMC_Write_Protection_Enable ((uint32_t)0x00000200)

#define FMC_SDClock_Disable ((uint32_t)0x00000000)
#define FMC_SDClock_Period_2 ((uint32_t)0x00000800)
#define FMC_SDClock_Period_3 ((uint32_t)0x00000C00)

#define FMC_Read_Burst_Disable ((uint32_t)0x00000000)
#define FMC_Read_Burst_Enable ((uint32_t)0x00001000)

#define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000)
#define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000)
#define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000)


// Комманды контроллера
#define FMC_Command_Mode_normal ((uint32_t)0x00000000)
#define FMC_Command_Mode_CLK_Enabled ((uint32_t)0x00000001)
#define FMC_Command_Mode_PALL ((uint32_t)0x00000002)
#define FMC_Command_Mode_AutoRefresh ((uint32_t)0x00000003)
#define FMC_Command_Mode_LoadMode ((uint32_t)0x00000004)
#define FMC_Command_Mode_Selfrefresh ((uint32_t)0x00000005)
#define FMC_Command_Mode_PowerDown ((uint32_t)0x00000006)

#define FMC_Command_Target_bank2 ((uint32_t)0x00000008)
#define FMC_Command_Target_bank1 ((uint32_t)0x00000010)
#define FMC_Command_Target_bank1_2 ((uint32_t)0x00000018)

// управление памятью
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAM ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)



// Инициализация ОЗУ на плате.
void draminit(void)
{
uint32_t tmp = 0;
uint32_t timeout = SDRAM_TIMEOUT;


// Инициализация пинов памяти
PINSDRAM_INIT;
// FMC SDRAM последовательность инициализации устройства

// Шаг 1

// Строки: [9:0]
tmp |= FMC_ColumnBits_Number_9b;
// Столбцы: [13:0]
tmp |= FMC_RowBits_Number_13b;
tmp |= FMC_NORSRAM_MemoryDataWidth_16b;
tmp |= FMC_InternalBank_Number_4;
// CL: Cas Latency = 3 цикла
tmp |= FMC_CAS_Latency_3;
tmp |= FMC_Write_Protection_Disable;
tmp |= FMC_SDClock_Period_2;
tmp |= FMC_Read_Burst_Enable;
tmp |= FMC_ReadPipe_Delay_1;
// FMC SDRAM bank initialization

// FMC SDRAM control configuration. Банк 1.
FMC_Bank5_6->SDCR[0] = tmp;

// Шаг 2

// Тайминги для 90 Mhz на SD. Частота (180Mhz/2)
// TMRD: 2 цикла ожидания
tmp = 2-1;
// TXSR: min=70ns (7x11.11ns)
tmp |= (7-1)<<4;
// TRAS: min=42ns (4x11.11ns) max=120k (ns)
tmp |= (4-1)<<8;
// TRC: min=70 (7x11.11ns)
tmp |= (7-1)<<12;
// TWR: min=1+ 7ns (1+1x11.11ns)
tmp |= (2-1)<<16;
// TRP: 20ns => 2x11.11ns
tmp |= (2-1)<<20;
// TRCD: 20ns => 2x11.11ns
tmp |= (2-1)<<24;

// FMC SDRAM тайминги. Банк 1.
FMC_Bank5_6->SDTR[0] = tmp;

// Шаг 3

// Разрешение команд
tmp = FMC_Command_Mode_CLK_Enabled;
tmp |= FMC_Command_Target_bank1;
// FMC_AutoRefreshNumber
tmp |= (1-1)<<5;
// FMC_ModeRegisterDefinition
tmp |= 0<<9;
// ждать пока SDRAM контроллер будет готов
timeout = SDRAM_TIMEOUT;
while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0))
{
timeout--;
}
// Послать комманду
FMC_Bank5_6->SDCMR = tmp;

// Шаг 4

// Задержка 100мс
hDelay(100);

// Шаг 5

// Сконфигурировать PALL (precharge all)
tmp = FMC_Command_Mode_PALL;
tmp |= FMC_Command_Target_bank1;
// FMC_AutoRefreshNumber
tmp |= (1-1)<<5;
// FMC_ModeRegisterDefinition
tmp |= 0<<9;
// ждать пока SDRAM контроллер будет готов
timeout = SDRAM_TIMEOUT;
while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0))
{
timeout--;
}
// Послать комманду
FMC_Bank5_6->SDCMR = tmp;

// Шаг 6

// Сконфигурировать Auto-Refresh
tmp = FMC_Command_Mode_AutoRefresh;
tmp |= FMC_Command_Target_bank1;
// FMC_AutoRefreshNumber
tmp |= (8-1)<<5;
// FMC_ModeRegisterDefinition
tmp |= 0<<9;
// ждать пока SDRAM контроллер будет готов
timeout = SDRAM_TIMEOUT;
while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0))
{
timeout--;
}
// Послать комманду
FMC_Bank5_6->SDCMR = tmp;

// Шаг 7

// Сконфигурировать load Mode регистр
tmp = FMC_Command_Mode_LoadMode;
tmp |= FMC_Command_Target_bank1;
// FMC_AutoRefreshNumber
tmp |= (8-1)<<5;
// FMC_ModeRegisterDefinition
// Запрограммировать mode register внешней памяти
tmp |= ((uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE)<<9;
// ждать пока SDRAM контроллер будет готов
timeout = SDRAM_TIMEOUT;
while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0))
{
timeout--;
}
// Послать комманду
FMC_Bank5_6->SDCMR = tmp;

// Шаг 8

// Установить счётчик регенерации памяти
// (7.81 us x Freq) - 20
FMC_Bank5_6->SDRTR |= (683<<1);

// ждать пока SDRAM контроллер будет готов
timeout = SDRAM_TIMEOUT;
while((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) && (timeout > 0))
{
timeout--;
}

}


среда, 14 июня 2017 г.

LTDC

/** 
  * @brief  LTDC handle Structure definition
  */
typedef struct
{
  LTDC_TypeDef                                *Instance;                /*!< LTDC Register base address                */

  LTDC_InitTypeDef                            Init;                         /*!< LTDC parameters                           */

  LTDC_LayerCfgTypeDef                  LayerCfg[MAX_LAYER];      /*!< LTDC Layers parameters                    */

  HAL_LockTypeDef                            Lock;                     /*!< LTDC Lock                                 */

  __IO HAL_LTDC_StateTypeDef       State;                    /*!< LTDC state                                */
  
  __IO uint32_t                                    ErrorCode;                /*!< LTDC Error code                           */

} LTDC_HandleTypeDef;

суббота, 10 июня 2017 г.

xPortPendSVHandler & vPortSVCHandler:

xPortPendSVHandler:
vPortSVCHandler:

vPortSVCHandler
используется один раз - для запуска самой первой задачи. На кортексе для прерываний используется отдельный стек. Вот для того, чтобы на него переключиться и используется инструкция SVC.

xPortPendSVHandler
используется для переключения задач во всех остальных случаях, потому что:
1) этому прерыванию можно назначить самый низкий приоритет - переключение задач не вызовет блокировку обработки важных событий
2) это прерывание асинхронно - можно взвести битик, доделать текущие дела, обработать более приоритетные прерывания и т.д. Не нужно где-то запоминать флажок "надо переключить задачу", выполнять какие-то вызовы, учитывать что требование переключить задачу может проистекать из нескольких источников и т.д.
3) это прерывание можно вызвать программно откуда угодно (из задачи или из обработчика другого прерывания) - переключение контекста в одном месте кода ОС, меньше глюков, проще отладка.
4) это прерывание имеется на любом Кортексе-М - не нужно писать вариации под каждый новый камень

Почему задача не может сама вызвать планировщик? Если ей уже делать нечего?

Чтобы не делать несколько разных точек входа в планировщик (одна для входа из задачи, другая для входа из прерывания, третья из таймера systick).



пятница, 9 июня 2017 г.

STM32 STemWin and Interrupt Problem

 I'm using STM32F407ZGT6 with SSD1963 LCD controller and 800x480 TFT panel. I'm not using OS. It's working with STemWin. 
 But when I used any interrupt, code execution stops at somewhere in emWin. 
 I moved WM_Exec() (GUI refresh function) to a timer interrupt routine and I disabled the interrupt before and enabled 
 the interrupt after emWin functions.
 The code is working in this form.
 
 //Main loop
     while(1)
     {
                _Disable_Timer_Interrupt
          GUI_EndDialog(hWin, 0);               //Delete GUI DIALOG
                _Enable_Timer_Interrupt


          HAL_Delay(500);
          
                _Disable_Timer_Interrupt
          hWin = CreateFramewin();          //Draw GUI DIALOG
                _Enable_Timer_Interrupt


          HAL_Delay(500);
     }
          
 //Timer Interrupt Routine          
 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
     {     
          if(htim->Instance == TIM13)     
          {
               HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_8);
               WM_Exec();
          }     
     }


 I added EXTI and the code didn't work again. enable-disable interrupt before-after didn't work in this time.
 I added FREETOS and problem didn't change. 
 When I used any interrupt, code execution stops at somewhere in emWin. 

I solved the problem. Problem caused by GUI_Delay() function.
I replaced GUI_X_GetTime(void) and GUI_X_Delay(int ms) functions in GUI_X.c with HAL tick timer functions.

Old form;
GUI_TIMER_TIME GUI_X_GetTime(void) { return OS_TimeMS; }
void GUI_X_Delay(int ms) { 
      int tEnd = OS_TimeMS + ms;
     while ((tEnd - OS_TimeMS) > 0);
}

The new form;
GUI_TIMER_TIME GUI_X_GetTime(void) { return HAL_GetTick();}
void GUI_X_Delay(int ms) { HAL_Delay(ms);}

Now I'm using Interrupts.