Я пытаюсь выяснить, как создать флэш-память, отображаемую через quadSPI. Я использую микроконтроллер STM32L4S9ZI с памятью Winbond W25Q32JVSSIQ QuadSPI.
MCU поддерживает OctoSPI, а не QuadSPI. Но в справочном руководстве написано, что OctoSPI для этого конкретного MCU можно использовать в режиме QuadSPI.
Я уже пытался использовать тот же MCU с флэш-памятью OctoSPI, и все работало правильно. Но с QuadSPI он вообще не работает. Проблема в том, что каждый раз, когда я посылаю команду, ничего не получается в качестве ответа. Я уже пытался использовать осциллограф, но сигналы выглядят странно (точно периодические импульсы на IO1, IO2, CLK и CS все время малы). Сейчас я просто пытаюсь прочитать идентификатор производителя чипа флэш-памяти, не более того. Я использовал тот же код с OctoSPI Flash, и он работает.
void HAL_OSPI_MspInit(OSPI_HandleTypeDef *hospi)
{
if (hospi->Instance == OCTOSPI1)
{
GPIO_InitTypeDef GPIO_InitStruct;
OSPIM_CfgTypeDef OSPIM_Cfg_Struct;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable the OctoSPI memory interface clocks */
__HAL_RCC_OSPI1_CLK_ENABLE();
__HAL_RCC_OSPIM_CLK_ENABLE();
/* Reset the OctoSPI memory interface */
__HAL_RCC_OSPI1_FORCE_RESET();
__HAL_RCC_OSPI1_RELEASE_RESET();
/* Enable GPIO clocks */
/* IOSV bit MUST be set to access GPIO port G[2:15] */
__HAL_RCC_PWR_CLK_ENABLE();
SET_BIT(PWR->CR2, PWR_CR2_IOSV);
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* OSPI CS GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPIM_P1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* OSPI CLK GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* OSPI D0 GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* OSPI D1 GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_0;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* OSPI D2 GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_7;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* OSPI D3 GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_6;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*##-3- Configure the NVIC for OSPI #########################################*/
/* NVIC configuration for OSPI interrupt */
HAL_NVIC_SetPriority(OCTOSPI1_IRQn, 0x0F, 0);
HAL_NVIC_EnableIRQ(OCTOSPI1_IRQn);
/*##-4- Configure the OctoSPI IO Manager ####################################*/
OSPIM_Cfg_Struct.ClkPort = 1;
OSPIM_Cfg_Struct.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
OSPIM_Cfg_Struct.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
OSPIM_Cfg_Struct.NCSPort = 1;
if (HAL_OSPIM_Config(hospi, &OSPIM_Cfg_Struct, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
/* User may add here some code to deal with this error */
while(1)
{
}
}
}
}
// /* Initialize OctoSPI ----------------------------------------------------- */
OSPIHandle.Instance = OCTOSPI1;
HAL_OSPI_DeInit(&OSPIHandle);
OSPIHandle.Init.FifoThreshold = 1;
OSPIHandle.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
OSPIHandle.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
OSPIHandle.Init.DeviceSize = OSPI_FLASH_SIZE;
OSPIHandle.Init.ChipSelectHighTime = 2;
OSPIHandle.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
OSPIHandle.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
OSPIHandle.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
OSPIHandle.Init.ClockPrescaler = 2; /* OctoSPI clock = 120MHz / ClockPrescaler = 60MHz */
OSPIHandle.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
OSPIHandle.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
OSPIHandle.Init.ChipSelectBoundary = 0;
if (HAL_OSPI_Init(&OSPIHandle) != HAL_OK)
{
printf("%s %d\r\n", __FILE__, __LINE__);
error_handler();
}
//
// printf("%s %d\r\n", __FILE__, __LINE__);
//
// /* Device ID ---- */
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.Instruction = 0x94;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.Address = 0x000000;
sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_4_LINES;
sCommand.AlternateBytes = 0xF;
sCommand.AlternateBytesSize = 1;
sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DummyCycles = 4;
sCommand.NbData = 2;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
uint8_t reg[2];
printf("%s %d\r\n", __FILE__, __LINE__);
if (HAL_OSPI_Command(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
printf("%s %d\r\n", __FILE__, __LINE__);
error_handler();
}
printf("%s %d\r\n", __FILE__, __LINE__);
if (HAL_OSPI_Receive(&OSPIHandle, reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
printf("%s %d error: %d 0x%08x 0x%08x\r\n", __FILE__, __LINE__, OSPIHandle.ErrorCode, reg[0], reg[1]);
error_handler();
}
printf("%s %d\r\n", __FILE__, __LINE__);
Я действительно надеюсь, что смогу выяснить, как инициализируется память QuadSPI на устройстве OctoSPI.
Не могли бы вы помочь с периферийным устройством QuadSPI при инициализации OctoSPI? Есть что-то, что я пропускаю? Спасибо