STM32F429IGT6 noname boards (2)
В прошлой части остановились по сборке проекта, в этой части программный код.
И так у нас готовый проект, согласованный с CubeMX
переходим в файл main.c (данный файл сформирован под настройки первой части, это надо для согласования CubeMX и IAR)
находим область в main.c
/* USER CODE BEGIN PV */
"(здесь код пользователя)"
/* USER CODE END PV */
копируем код (ctrl-c):
NAND_IDTypeDef g_nand_id;
volatile HAL_StatusTypeDef g_erase_status = HAL_ERROR;
volatile HAL_StatusTypeDef g_read_status = HAL_ERROR;
volatile HAL_StatusTypeDef g_write_status = HAL_ERROR;
NAND_AddressTypeDef g_erase_addr;
uint8_t g_write_buf[2048];
uint8_t g_read_buf[2048];
/* Адреса областей FMC NAND Bank3 */
const uint32_t g_data_area = 0x80000000u;
const uint32_t g_cmd_area = 0x80000000u | 0x00010000u; /* 0x80010000 */
const uint32_t g_addr_area = 0x80000000u | 0x00020000u; /* 0x80020000 */
вставляем копированный код (ctrl-v) в область
/* USER CODE BEGIN PV */
>>> ctrl-v <<<
/* USER CODE END PV */
ниже в файле main.c находим
/* USER CODE BEGIN 0 */
"(здесь код пользователя)"
/* USER CODE END 0 */
копируем код (ctrl-c):
/* Ожидание готовности NAND по линии R/B# (PB13). */
static HAL_StatusTypeDef NAND_WaitReady(uint32_t timeout_ms)
{
uint32_t start = HAL_GetTick();
while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == GPIO_PIN_RESET)
{
if ((HAL_GetTick() - start) > timeout_ms)
{
return HAL_TIMEOUT;
}
}
return HAL_OK;
}
/* Чтение байта статуса NAND (команда 0x70) */
static uint8_t NAND_ReadStatusByte(void)
{
*(volatile uint8_t *)g_cmd_area = 0x70;
return *(volatile uint8_t *)g_data_area;
}
вставляем копированный код (ctrl-v) в область
/* USER CODE BEGIN 0 */
>>> ctrl-v <<<
/* USER CODE END 0 */
ниже в файле main.c находим
/* USER CODE BEGIN 2 */
"(здесь код пользователя)"
/* USER CODE END 2 */
копируем код (ctrl-c):
/* ================= SDRAM INITIALIZATION SEQUENCE ================= */
FMC_SDRAM_CommandTypeDef Command;
uint32_t tmpmrd = 0;
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
HAL_Delay(1);
Command.CommandMode = FMC_SDRAM_CMD_PALL;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command.AutoRefreshNumber = 1;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command.AutoRefreshNumber = 8;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
tmpmrd = (uint32_t)(0u << 0) | (uint32_t)(0u << 3) |
(uint32_t)(3u << 4) | (uint32_t)(1u << 9);
Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = tmpmrd;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
(void)HAL_SDRAM_ProgramRefreshRate(&hsdram1, 1385);
HAL_Delay(10);
/* ================= SDRAM TEST ================= */
{
volatile uint16_t *sdram_ptr = (volatile uint16_t *)0xD0000000u;
*sdram_ptr = 0xAA55u;
volatile uint16_t sdram_rd = *sdram_ptr;
(void)sdram_rd;
}
/* ================= NAND: инициализация адреса ================= */
g_erase_addr.Plane = 0;
g_erase_addr.Block = 0;
g_erase_addr.Page = 0;
for (int i = 0; i < 2048; i++)
{
g_write_buf[i] = (uint8_t)(i & 0xFF);
}
/* ================= NAND TEST ================= */
HAL_NAND_Reset(&hnand1);
HAL_Delay(10);
HAL_StatusTypeDef nand_status = HAL_NAND_Read_ID(&hnand1, &g_nand_id);
if (nand_status == HAL_OK)
{
volatile uint32_t maker = g_nand_id.Maker_Id;
volatile uint32_t device = g_nand_id.Device_Id;
volatile uint32_t third = g_nand_id.Third_Id;
volatile uint32_t fourth = g_nand_id.Fourth_Id;
(void)maker; (void)device; (void)third; (void)fourth;
}
else
{
volatile uint32_t err = 1;
(void)err;
}
/* ================= NAND: стирание блока 0 ================= */
*(volatile uint8_t *)g_cmd_area = 0x60;
*(volatile uint8_t *)g_addr_area = (uint8_t)((g_erase_addr.Block >> 8) & 0xFF);
*(volatile uint8_t *)g_addr_area = (uint8_t)( g_erase_addr.Block & 0xFF);
*(volatile uint8_t *)g_cmd_area = 0xD0;
/* tWB: NAND должен успеть «дёрнуть» R/B# вниз */
for (volatile int d = 0; d < 1000; d++);
HAL_StatusTypeDef erase_wait = NAND_WaitReady(100);
if (erase_wait != HAL_OK)
{
g_erase_status = HAL_TIMEOUT;
}
else
{
uint8_t st = NAND_ReadStatusByte();
g_erase_status = ((st & 0x01u) == 0u) ? HAL_OK : HAL_ERROR;
}
/* ================= NAND: запись страницы 0 блока 0 ================= */
*(volatile uint8_t *)g_cmd_area = 0x80;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
for (int i = 0; i < 2048; i++)
{
*(volatile uint8_t *)g_data_area = g_write_buf[i];
}
*(volatile uint8_t *)g_cmd_area = 0x10;
for (volatile int d = 0; d < 1000; d++);
HAL_StatusTypeDef prog_wait = NAND_WaitReady(50);
if (prog_wait != HAL_OK)
{
g_write_status = HAL_TIMEOUT;
}
else
{
uint8_t st = NAND_ReadStatusByte();
g_write_status = ((st & 0x01u) == 0u) ? HAL_OK : HAL_ERROR;
}
/* ================= NAND: чтение страницы 0 блока 0 ================= */
*(volatile uint8_t *)g_cmd_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_cmd_area = 0x30;
/* tWB: критически важно, иначе NAND не успеет перевести R/B# в низкий уровень */
for (volatile int d = 0; d < 5000; d++);
/* tR: по даташиту W29N01HV максимум 25 мкс, 1 мс с большим запасом */
HAL_Delay(1);
/* Чтение данных: никакой команды 0x70 здесь быть не должно */
for (int i = 0; i < 2048; i++)
{
g_read_buf[i] = *(volatile uint8_t *)g_data_area;
}
/* Сравнение: только по содержимому, без статусного байта */
uint32_t mismatch = 0;
for (int i = 0; i < 2048; i++)
{
if (g_read_buf[i] != g_write_buf[i])
{
mismatch++;
}
}
g_read_status = (mismatch == 0) ? HAL_OK : HAL_ERROR;
вставляем копированный код (ctrl-v) в область
/* USER CODE BEGIN 2 */
>>> ctrl-v <<<
/* USER CODE END 2 */
Далее собираем проект
В следующей части, запуск и тестирование, что в итоге получилось.

