STM Урок 62. FMC SDRAM. Часть 4



 

Урок 62

 

Часть 4

 

FMC SDRAM

 

В прошлой части урока мы научились передавать команды микросхеме памяти SDRAM через контроллер FMC, используя только функции библиотеки HAL.

Также мы уже передали две команды, и, мало того, проверили, что они успешно передались.

 

Следующая команда

 

  HAL_Delay(1);

  command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;

  command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;

  command.AutoRefreshNumber = 8;

  command.ModeRegisterDefinition = 0;

  hal_stat = HAL_SDRAM_SendCommand(hsdram, &command, SDRAM_TIMEOUT);

  HAL_Delay(1);

 

Здесь мы задаём режим автоорегенерации, необходимый для нормального функционирования SDRAM.

Следующая команда

 

  tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |

                     SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |

                     SDRAM_MODEREG_CAS_LATENCY_2           |

                     SDRAM_MODEREG_OPERATING_MODE_STANDARD |

                     SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

  command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;

  command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;

  command.AutoRefreshNumber = 1;

  command.ModeRegisterDefinition = tmpmrd;

  hal_stat = HAL_SDRAM_SendCommand(hsdram, &command, SDRAM_TIMEOUT);

 

Здесь включаем размер пакета, последовательный режим передачи, латентность 2 такта, стандартный режим, одиночный режим записи пакета.

И в конце инициализации мы вручную в в регистр FMC SDRTR, отвечающий за время авторегенерации отправим определенное число (разъяснено в комментарии к коду)

 

   /* Step 8: Set the refresh rate counter */

  /* (15.62 us x Freq) — 20 */

  /* Set the device refresh counter */

  hsdram->Instance->SDRTR |= ((uint32_t)((1292)<< 1));

}

 

Вот. собственно и вся инициализация.

Также мы знаем, что FMC отображает адреса SDRAM по определённым адресам. Откроем страницу 307 в Reference Manual на контроллер

 

image22

 

 

Так ка мы подключали именно Bank 1, то напишем ещё один макрос в файл MT48LC4M32B2.h, чтобы нам было удобнее и нагляднее обращаться к SDRAM из программы

 

//————————————————

#define SDRAM_BANK_ADDR                 ((uint32_t)0xC0000000)

 

А также напишем несколько макросов и глобальных переменных в файле main.c

 

/* USER CODE BEGIN PV */

/* Private variables ———————————————————*/

#define BUFFER_SIZE         ((uint32_t)0x0100)

#define WRITE_READ_ADDR     ((uint32_t)0x0800)

uint32_t aTxBuffer[BUFFER_SIZE];

uint32_t aRxBuffer[BUFFER_SIZE];

uint32_t uwIndex = 0;

/* USER CODE END PV */

 

Здесь макросы для размера буфера, то есть это количество байт, которые мы будем писать в память SDRAM и затем оттуда читать, смещение от начала SDRAM в FMC, буфер для записи, буфер для чтения и порядковый номер в массиве.

Также добавим функцию в файл main.c для заполнения буфера определёнными данными для последующего его использования для записи в SDRAM. Функция была взята из примера с репозитория Cube MX и в изменениях не нуждается

 

/* USER CODE BEGIN 0 */

static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset)

{

  uint32_t tmpIndex = 0;

  /* Put in global buffer different values */

  for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ )

  {

    pBuffer[tmpIndex] = tmpIndex + uwOffset;

  }

}

/* USER CODE END 0 */

 

Во входящих параметрах у нас указатель на буфер, который мы будем заполнять данными , количество байтов заполнения, а также значение начального байта. Дальше значения байтов будут увеличиваться на 1.

 

 

Воспользовавшись данной функцией и вызвав её в main(), заполним наш буфер, начав с любого значения

 

 /* USER CODE BEGIN 2 */

 MT48LC4M32B2_Init(&hsdram1);

 Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0x37BA0F68);

 

Теперь запишем в SDRAM содержимое буфера

 

 Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0x37BA0F68);

 //запишем данные из буфера в память SDRAM с адреса 0xC0000800

  for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)

  {

    *(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex) = aTxBuffer[uwIndex];

  }

 

После этого попытаемся их из SDRAM прочитать в другой буфер

 

  }

  //прочитаем в другой буфер данные из памяти SDRAM с адреса 0xC0000800

  for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)

  {

    aRxBuffer[uwIndex] = *(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex);

  }

 

 

Затем отправим байты в текстовом виде в USART

 

  }

 //отправим байты в USART

  for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)

  {

  sprintf(str1,»%03ld: 0x%08lXrn»,(unsigned long) uwIndex,(unsigned long)aRxBuffer[uwIndex]);

  HAL_UART_Transmit(&huart1, (uint8_t*)str1,strlen(str1),0x1000);

  HAL_Delay(100);  

  }

 

Задержка здесь оптимальная, так как если меньше, виснет терминальная программа, другие не виснут, но они не такие наглядные.

По окончании передачи зажжем зелёный светодиод

 

  }

 HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_SET);

 

Из бесконечного цикла всё удалим

 

  while (1)

  {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

 }

 

Соберём код, откроем терминальную программу, нажмём там Connect, выбрав порт и прошьём контроллер.

Мы должны в терминале увидеть следующую картину

 

image23  image24

 

Ну вот! У нас всё считалось из памяти SDRAM, так как все байты пришли в USART.

Я думаю, к теме FMC и SDRAM мы ещё вернёмся, когда будем программировать дисплей, а также в других случаях.

 

 

Предыдущая часть Программирование МК STM32 Следующий урок

 

Исходный код

 

Техническая документация на микросхему SDRAM MT48LC4M32B2

 

 

Отладочную плату можно приобрести здесь 32F746G-DISCOVERY

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM32 FMC SDRAM

7 комментариев на “STM Урок 62. FMC SDRAM. Часть 4
  1. Сергей:

    у меня STM32F429 cсобрал проект, но почему-то микроконтроллер зависает на выполнении процедуры *(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex) = aTxBuffer[uwIndex]; Подскажите пожалуйста, что не так.

  2. Владимир:

    Доброго времени суток.
    Сдублирую вопрос в двух темах, может кто откликнется.
    Разбираюсь с отладкой STM32F4-disco на 429 камне. Вроде разобрался с записью и чтением с sdram, но при подключении дисплея возникла странная проблемка. После записи в SDRAM буфера для экрана (просто заливаю зеленым), после нескольких чтений экран из зеленого перетекает в белый. Где я мог накосячить в работе с памятью?

  3. BlokNot:

    Из какого урока по Си можно научиться понимать смысл подобных конструкций *(__IO uint32_t*)?

    • Даниил:

      Да из обычных учебников, если глянуть через definition в IDE, то увидишь запись #define volatile __IO. Просто переименовали ключевое слово, дабы компилятор ее не оптимизировал.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*