/** ****************************************************************************** * @file s70kl1281.c * @modify MCD Application Team * @brief This file provides the S70KL1281 OSPI drivers. ****************************************************************************** * @attention * *

© Copyright (c) 2020 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "s70kl1281.h" /** @addtogroup BSP * @{ */ /** @addtogroup Components * @{ */ /** @defgroup S70KL1281 S70KL1281 * @{ */ /** @defgroup S70KL1281_Exported_Functions S70KL1281 Exported Functions * @{ */ /* Read/Write Array Commands *********************/ /** * @brief Reads an amount of data from the OSPI memory. * @param Ctx Component object pointer * @param pData Pointer to data to be read * @param ReadAddr Read start address * @param Size Size of data to read * @retval OSPI memory status */ int32_t S70KL1281_Read(OSPI_HandleTypeDef *Ctx, uint8_t *pData, uint32_t ReadAddr, uint32_t Size) { OSPI_HyperbusCmdTypeDef sCommand; /* Initialize the read command */ sCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = ReadAddr; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = Size; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive(Ctx, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @brief Reads an amount of data in DMA mode from the OSPI memory. * @param Ctx Component object pointer * @param pData Pointer to data to be read * @param ReadAddr Read start address * @param Size Size of data to read * @retval OSPI memory status */ int32_t S70KL1281_Read_DMA(OSPI_HandleTypeDef *Ctx, uint8_t *pData, uint32_t ReadAddr, uint32_t Size) { OSPI_HyperbusCmdTypeDef sCommand; /* Initialize the read command */ sCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = ReadAddr; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = Size; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive_DMA(Ctx, pData) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @brief Writes an amount of data to the OSPI memory. * @param Ctx Component object pointer * @param pData Pointer to data to be written * @param WriteAddr Write start address * @param Size Size of data to write * @retval OSPI memory status */ int32_t S70KL1281_Write(OSPI_HandleTypeDef *Ctx, uint8_t *pData, uint32_t WriteAddr, uint32_t Size) { OSPI_HyperbusCmdTypeDef sCommand; /* Initialize the write command */ sCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = WriteAddr; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = Size; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Transmission of the data */ if (HAL_OSPI_Transmit(Ctx, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @brief Writes an amount of data in DMA mode to the OSPI memory. * @param Ctx Component object pointer * @param pData Pointer to data to be written * @param WriteAddr Write start address * @param Size Size of data to write * @retval OSPI memory status */ int32_t S70KL1281_Write_DMA(OSPI_HandleTypeDef *Ctx, uint8_t *pData, uint32_t WriteAddr, uint32_t Size) { OSPI_HyperbusCmdTypeDef sCommand; /* Initialize the write command */ sCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = WriteAddr; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = Size; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Transmission of the data */ if (HAL_OSPI_Transmit_DMA(Ctx, pData) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @brief Enable memory mapped mode for the OSPI memory. * @param Ctx Component object pointer * @retval OSPI memory status */ int32_t S70KL1281_EnableMemoryMappedMode(OSPI_HandleTypeDef *Ctx) { OSPI_HyperbusCmdTypeDef sCommand; OSPI_MemoryMappedTypeDef sMemMappedCfg; /* OctoSPI Hyperbus command configuration */ sCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = 0; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = 1; if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* OctoSPI activation of memory-mapped mode */ sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE; if (HAL_OSPI_MemoryMapped(Ctx, &sMemMappedCfg) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /* Register/Setting Commands **************************************************/ /** * @brief Read configuration register 0 value * @param Ctx Component object pointer * @param Value Register value pointer * @retval error status */ int32_t S70KL1281_ReadCfgReg0(OSPI_HandleTypeDef *Ctx, uint16_t *Value) { OSPI_HyperbusCmdTypeDef sCommand; /* Initialize the read command */ sCommand.AddressSpace = HAL_OSPI_REGISTER_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = S70KL1281_CR0_ADDRESS; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = 2U; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive(Ctx, (uint8_t *)Value, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @brief Write configuration register 0 * @param Ctx Component object pointer * @param Value Value to write to register * @retval error status */ int32_t S70KL1281_WriteCfgReg0(OSPI_HandleTypeDef *Ctx, uint16_t Value, uint32_t LatencyMode, uint32_t InitialLatency) { OSPI_HyperbusCfgTypeDef sHyperbusCfg; OSPI_HyperbusCmdTypeDef sCommand; /* Reconfigure peripheral as no write latency to write in registers */ sHyperbusCfg.RWRecoveryTime = RW_RECOVERY_TIME; sHyperbusCfg.AccessTime = InitialLatency; sHyperbusCfg.WriteZeroLatency = HAL_OSPI_NO_LATENCY_ON_WRITE; sHyperbusCfg.LatencyMode = LatencyMode; if (HAL_OSPI_HyperbusCfg(Ctx, &sHyperbusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Initialize the write command */ sCommand.AddressSpace = HAL_OSPI_REGISTER_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = S70KL1281_CR0_ADDRESS; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = 2U; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Transmission of the data */ if (HAL_OSPI_Transmit(Ctx, (uint8_t *)(&Value), HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reconfigure peripheral for correct write access */ sHyperbusCfg.WriteZeroLatency = HAL_OSPI_LATENCY_ON_WRITE; if (HAL_OSPI_HyperbusCfg(Ctx, &sHyperbusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @brief Read configuration register 1 value * @param Ctx Component object pointer * @param Value Register value pointer * @retval error status */ int32_t S70KL1281_ReadCfgReg1(OSPI_HandleTypeDef *Ctx, uint16_t *Value) { OSPI_HyperbusCmdTypeDef sCommand; /* Initialize the read command */ sCommand.AddressSpace = HAL_OSPI_REGISTER_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = S70KL1281_CR1_ADDRESS; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = 2U; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive(Ctx, (uint8_t *)Value, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @brief Write configuration register 1 * @param Ctx Component object pointer * @param Value Value to write to register * @retval error status */ int32_t S70KL1281_WriteCfgReg1(OSPI_HandleTypeDef *Ctx, uint16_t Value, uint32_t LatencyMode, uint32_t InitialLatency) { OSPI_HyperbusCfgTypeDef sHyperbusCfg; OSPI_HyperbusCmdTypeDef sCommand; /* Reconfigure peripheral as no write latency to write in registers */ sHyperbusCfg.RWRecoveryTime = RW_RECOVERY_TIME; sHyperbusCfg.AccessTime = InitialLatency; sHyperbusCfg.WriteZeroLatency = HAL_OSPI_NO_LATENCY_ON_WRITE; sHyperbusCfg.LatencyMode = LatencyMode; if (HAL_OSPI_HyperbusCfg(Ctx, &sHyperbusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Initialize the write command */ sCommand.AddressSpace = HAL_OSPI_REGISTER_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = S70KL1281_CR1_ADDRESS; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = 2U; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Transmission of the data */ if (HAL_OSPI_Transmit(Ctx, (uint8_t *)(&Value), HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reconfigure peripheral for correct write access */ sHyperbusCfg.WriteZeroLatency = HAL_OSPI_LATENCY_ON_WRITE; if (HAL_OSPI_HyperbusCfg(Ctx, &sHyperbusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /* ID Commands ****************************************************************/ /** * @brief Read Flash IDs. * Manufacturer ID, Memory type, Memory density * @param Ctx Component object pointer * @param ID IDs pointer (2 * 16-bits value) * @retval error status */ int32_t S70KL1281_ReadID(OSPI_HandleTypeDef *Ctx, uint16_t *ID) { OSPI_HyperbusCmdTypeDef sCommand; uint16_t *data = ID; /* Initialize the write command */ sCommand.AddressSpace = HAL_OSPI_REGISTER_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = S70KL1281_DIR0_ADDRESS; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = 2U; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive(Ctx, (uint8_t *)data, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } data++; sCommand.Address = S70KL1281_DIR1_ADDRESS; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive(Ctx, (uint8_t *)data, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /* Power down Commands ********************************************************/ /** * @brief Flash enter deep power-down command * @param Ctx Component object pointer * @retval error status */ int32_t S70KL1281_EnterPowerDown(OSPI_HandleTypeDef *Ctx, uint32_t LatencyMode, uint32_t InitialLatency) { uint16_t reg; /* Read the value of the CR0 register */ if (S70KL1281_ReadCfgReg0(Ctx, ®) != S70KL1281_OK) { return S70KL1281_ERROR; } /* Update the deep power down value of the CR0 register */ SET_BIT(reg, S70KL1281_CR0_DPDE); if (S70KL1281_WriteCfgReg0(Ctx, reg, LatencyMode, InitialLatency) != S70KL1281_OK) { return S70KL1281_ERROR; } /* --- Memory takes 10us min to enter deep power down --- */ /* --- At least 30us should be respected before leaving deep power down --- */ return S70KL1281_OK; } /** * @brief Flash leave deep power-down command * @param Ctx Component object pointer * @retval error status */ int32_t S70KL1281_LeavePowerDown(OSPI_HandleTypeDef *Ctx) { /* --- A dummy command is sent to the memory, as the nCS should be low for at least 200 ns --- */ /* --- Memory takes 150us max to leave deep power down --- */ OSPI_HyperbusCmdTypeDef sCommand; uint32_t data; /* Initialize the read command */ sCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE; sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS; sCommand.Address = 0; sCommand.DQSMode = HAL_OSPI_DQS_ENABLE; sCommand.NbData = 4; /* Configure the command */ if (HAL_OSPI_HyperbusCmd(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } /* Reception of the data */ if (HAL_OSPI_Receive(Ctx, (uint8_t*)(&data), HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return S70KL1281_ERROR; } return S70KL1281_OK; } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/