2019-04-30 17:27:23 +01:00
/**
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ file QSPI / QSPI_ReadWrite_IT / Src / main . c
* @ author MCD Application Team
* @ brief This example describes how to configure and use QuadSPI through
* the STM32F4xx HAL API .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ attention
*
2021-03-03 14:55:52 +01:00
* < h2 > < center > & copy ; Copyright ( c ) 2017 STMicroelectronics .
* All rights reserved . < / center > < / h2 >
2019-04-30 17:27:23 +01:00
*
2021-03-03 14:55:52 +01:00
* 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
2019-04-30 17:27:23 +01:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/* Includes ------------------------------------------------------------------*/
# include "main.h"
/** @addtogroup STM32F4xx_HAL_Examples
* @ {
*/
/** @addtogroup QSPI_ReadWrite_IT
* @ {
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
QSPI_HandleTypeDef QSPIHandle ;
__IO uint8_t CmdCplt , RxCplt , TxCplt , StatusMatch , TimeOut ;
/* Buffer used for transmission */
uint8_t aTxBuffer [ ] = " ****QSPI communication based on IT**** ****QSPI communication based on IT**** ****QSPI communication based on IT**** ****QSPI communication based on IT**** ****QSPI communication based on IT**** ****QSPI communication based on IT**** " ;
/* Buffer used for reception */
uint8_t aRxBuffer [ BUFFERSIZE ] ;
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config ( void ) ;
static void Error_Handler ( void ) ;
static void QSPI_WriteEnable ( QSPI_HandleTypeDef * hqspi ) ;
static void QSPI_AutoPollingMemReady ( QSPI_HandleTypeDef * hqspi ) ;
static void QSPI_DummyCyclesCfg ( QSPI_HandleTypeDef * hqspi ) ;
/* Private functions ---------------------------------------------------------*/
/**
* @ brief Main program
* @ param None
* @ retval None
*/
int main ( void )
{
QSPI_CommandTypeDef sCommand ;
uint32_t address = 0 ;
uint16_t index ;
__IO uint8_t step = 0 ;
/* STM32F4xx HAL library initialization:
- Configure the Flash prefetch
- Systick timer is configured by default as source of time base , but user
can eventually implement his proper time base source ( a general purpose
timer for example or other time source ) , keeping in mind that Time base
duration should be kept 1 ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis .
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init ( ) ;
/* Configure the system clock to 100 MHz */
SystemClock_Config ( ) ;
BSP_LED_Init ( LED3 ) ;
BSP_LED_Init ( LED4 ) ;
/* Initialize QuadSPI ------------------------------------------------------ */
QSPIHandle . Instance = QUADSPI ;
HAL_QSPI_DeInit ( & QSPIHandle ) ;
QSPIHandle . Init . ClockPrescaler = 0 ;
QSPIHandle . Init . FifoThreshold = 4 ;
QSPIHandle . Init . SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE ;
QSPIHandle . Init . FlashSize = QSPI_FLASH_SIZE ;
QSPIHandle . Init . ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE ;
QSPIHandle . Init . ClockMode = QSPI_CLOCK_MODE_0 ;
QSPIHandle . Init . FlashID = QSPI_FLASH_ID_1 ;
QSPIHandle . Init . DualFlash = QSPI_DUALFLASH_DISABLE ;
if ( HAL_QSPI_Init ( & QSPIHandle ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
sCommand . InstructionMode = QSPI_INSTRUCTION_1_LINE ;
sCommand . AddressSize = QSPI_ADDRESS_24_BITS ;
sCommand . AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE ;
sCommand . DdrMode = QSPI_DDR_MODE_DISABLE ;
sCommand . DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY ;
sCommand . SIOOMode = QSPI_SIOO_INST_EVERY_CMD ;
while ( 1 )
{
switch ( step )
{
case 0 :
CmdCplt = 0 ;
/* Initialize Reception buffer --------------------------------------- */
for ( index = 0 ; index < BUFFERSIZE ; index + + )
{
aRxBuffer [ index ] = 0 ;
}
/* Enable write operations ------------------------------------------- */
QSPI_WriteEnable ( & QSPIHandle ) ;
/* Erasing Sequence -------------------------------------------------- */
sCommand . Instruction = SECTOR_ERASE_CMD ;
sCommand . AddressMode = QSPI_ADDRESS_1_LINE ;
sCommand . Address = address ;
sCommand . DataMode = QSPI_DATA_NONE ;
sCommand . DummyCycles = 0 ;
if ( HAL_QSPI_Command_IT ( & QSPIHandle , & sCommand ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
step + + ;
break ;
case 1 :
if ( CmdCplt ! = 0 )
{
CmdCplt = 0 ;
StatusMatch = 0 ;
/* Configure automatic polling mode to wait for end of erase ------- */
QSPI_AutoPollingMemReady ( & QSPIHandle ) ;
step + + ;
}
break ;
case 2 :
if ( StatusMatch ! = 0 )
{
StatusMatch = 0 ;
TxCplt = 0 ;
/* Enable write operations ----------------------------------------- */
QSPI_WriteEnable ( & QSPIHandle ) ;
/* Writing Sequence ------------------------------------------------ */
sCommand . Instruction = EXT_QUAD_IN_FAST_PROG_CMD ;
sCommand . AddressMode = QSPI_ADDRESS_4_LINES ;
sCommand . DataMode = QSPI_DATA_4_LINES ;
sCommand . NbData = BUFFERSIZE ;
if ( HAL_QSPI_Command ( & QSPIHandle , & sCommand , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
if ( HAL_QSPI_Transmit_IT ( & QSPIHandle , aTxBuffer ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
step + + ;
}
break ;
case 3 :
if ( TxCplt ! = 0 )
{
TxCplt = 0 ;
StatusMatch = 0 ;
/* Configure automatic polling mode to wait for end of program ----- */
QSPI_AutoPollingMemReady ( & QSPIHandle ) ;
step + + ;
}
break ;
case 4 :
if ( StatusMatch ! = 0 )
{
StatusMatch = 0 ;
RxCplt = 0 ;
/* Configure Volatile Configuration register (with new dummy cycles) */
QSPI_DummyCyclesCfg ( & QSPIHandle ) ;
/* Reading Sequence ------------------------------------------------ */
sCommand . Instruction = QUAD_INOUT_FAST_READ_CMD ;
sCommand . DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD ;
if ( HAL_QSPI_Command ( & QSPIHandle , & sCommand , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
if ( HAL_QSPI_Receive_IT ( & QSPIHandle , aRxBuffer ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
step + + ;
}
break ;
case 5 :
if ( RxCplt ! = 0 )
{
RxCplt = 0 ;
/* Result comparison ----------------------------------------------- */
for ( index = 0 ; index < BUFFERSIZE ; index + + )
{
if ( aRxBuffer [ index ] ! = aTxBuffer [ index ] )
{
BSP_LED_On ( LED4 ) ;
}
}
BSP_LED_Toggle ( LED3 ) ;
address + = QSPI_PAGE_SIZE ;
if ( address > = QSPI_END_ADDR )
{
address = 0 ;
}
step = 0 ;
}
break ;
default :
Error_Handler ( ) ;
}
}
}
/**
* @ brief Command completed callbacks .
* @ param hqspi : QSPI handle
* @ retval None
*/
void HAL_QSPI_CmdCpltCallback ( QSPI_HandleTypeDef * hqspi )
{
CmdCplt + + ;
}
/**
* @ brief Rx Transfer completed callbacks .
* @ param hqspi : QSPI handle
* @ retval None
*/
void HAL_QSPI_RxCpltCallback ( QSPI_HandleTypeDef * hqspi )
{
RxCplt + + ;
}
/**
* @ brief Tx Transfer completed callbacks .
* @ param hqspi : QSPI handle
* @ retval None
*/
void HAL_QSPI_TxCpltCallback ( QSPI_HandleTypeDef * hqspi )
{
TxCplt + + ;
}
/**
* @ brief Status Match callbacks
* @ param hqspi : QSPI handle
* @ retval None
*/
void HAL_QSPI_StatusMatchCallback ( QSPI_HandleTypeDef * hqspi )
{
StatusMatch + + ;
}
/**
* @ brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL ( HSE )
* SYSCLK ( Hz ) = 100000000
* HCLK ( Hz ) = 100000000
* AHB Prescaler = 1
* APB1 Prescaler = 2
* APB2 Prescaler = 1
* HSE Frequency ( Hz ) = 8000000
* PLL_M = 8
* PLL_N = 200
* PLL_P = 2
* PLL_Q = 7
* PLL_R = 2
* VDD ( V ) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency ( WS ) = 3
* @ param None
* @ retval None
*/
static void SystemClock_Config ( void )
{
RCC_ClkInitTypeDef RCC_ClkInitStruct ;
RCC_OscInitTypeDef RCC_OscInitStruct ;
HAL_StatusTypeDef ret = HAL_OK ;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE ( ) ;
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency , to update the voltage scaling value
regarding system frequency refer to product datasheet . */
__HAL_PWR_VOLTAGESCALING_CONFIG ( PWR_REGULATOR_VOLTAGE_SCALE1 ) ;
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct . OscillatorType = RCC_OSCILLATORTYPE_HSE ;
RCC_OscInitStruct . HSEState = RCC_HSE_BYPASS ;
RCC_OscInitStruct . PLL . PLLState = RCC_PLL_ON ;
RCC_OscInitStruct . PLL . PLLSource = RCC_PLLSOURCE_HSE ;
RCC_OscInitStruct . PLL . PLLM = 8 ;
RCC_OscInitStruct . PLL . PLLN = 200 ;
RCC_OscInitStruct . PLL . PLLP = RCC_PLLP_DIV2 ;
RCC_OscInitStruct . PLL . PLLQ = 7 ;
RCC_OscInitStruct . PLL . PLLR = 2 ;
ret = HAL_RCC_OscConfig ( & RCC_OscInitStruct ) ;
if ( ret ! = HAL_OK )
{
while ( 1 ) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct . ClockType = ( RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 ) ;
RCC_ClkInitStruct . SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK ;
RCC_ClkInitStruct . AHBCLKDivider = RCC_SYSCLK_DIV1 ;
RCC_ClkInitStruct . APB1CLKDivider = RCC_HCLK_DIV2 ;
RCC_ClkInitStruct . APB2CLKDivider = RCC_HCLK_DIV1 ;
ret = HAL_RCC_ClockConfig ( & RCC_ClkInitStruct , FLASH_LATENCY_3 ) ;
if ( ret ! = HAL_OK )
{
while ( 1 ) { ; }
}
}
/**
* @ brief This function send a Write Enable and wait it is effective .
* @ param hqspi : QSPI handle
* @ retval None
*/
static void QSPI_WriteEnable ( QSPI_HandleTypeDef * hqspi )
{
QSPI_CommandTypeDef sCommand ;
QSPI_AutoPollingTypeDef sConfig ;
/* Enable write operations ------------------------------------------ */
sCommand . InstructionMode = QSPI_INSTRUCTION_1_LINE ;
sCommand . Instruction = WRITE_ENABLE_CMD ;
sCommand . AddressMode = QSPI_ADDRESS_NONE ;
sCommand . AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE ;
sCommand . DataMode = QSPI_DATA_NONE ;
sCommand . DummyCycles = 0 ;
sCommand . DdrMode = QSPI_DDR_MODE_DISABLE ;
sCommand . DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY ;
sCommand . SIOOMode = QSPI_SIOO_INST_EVERY_CMD ;
if ( HAL_QSPI_Command ( & QSPIHandle , & sCommand , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
/* Configure automatic polling mode to wait for write enabling ---- */
sConfig . Match = 0x02 ;
sConfig . Mask = 0x02 ;
sConfig . MatchMode = QSPI_MATCH_MODE_AND ;
sConfig . StatusBytesSize = 1 ;
sConfig . Interval = 0x10 ;
sConfig . AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE ;
sCommand . Instruction = READ_STATUS_REG_CMD ;
sCommand . DataMode = QSPI_DATA_1_LINE ;
if ( HAL_QSPI_AutoPolling ( & QSPIHandle , & sCommand , & sConfig , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
}
/**
* @ brief This function read the SR of the memory and wait the EOP .
* @ param hqspi : QSPI handle
* @ retval None
*/
static void QSPI_AutoPollingMemReady ( QSPI_HandleTypeDef * hqspi )
{
QSPI_CommandTypeDef sCommand ;
QSPI_AutoPollingTypeDef sConfig ;
/* Configure automatic polling mode to wait for memory ready ------ */
sCommand . InstructionMode = QSPI_INSTRUCTION_1_LINE ;
sCommand . Instruction = READ_STATUS_REG_CMD ;
sCommand . AddressMode = QSPI_ADDRESS_NONE ;
sCommand . AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE ;
sCommand . DataMode = QSPI_DATA_1_LINE ;
sCommand . DummyCycles = 0 ;
sCommand . DdrMode = QSPI_DDR_MODE_DISABLE ;
sCommand . DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY ;
sCommand . SIOOMode = QSPI_SIOO_INST_EVERY_CMD ;
sConfig . Match = 0x00 ;
sConfig . Mask = 0x01 ;
sConfig . MatchMode = QSPI_MATCH_MODE_AND ;
sConfig . StatusBytesSize = 1 ;
sConfig . Interval = 0x10 ;
sConfig . AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE ;
if ( HAL_QSPI_AutoPolling_IT ( & QSPIHandle , & sCommand , & sConfig ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
}
/**
* @ brief This function configure the dummy cycles on memory side .
* @ param hqspi : QSPI handle
* @ retval None
*/
static void QSPI_DummyCyclesCfg ( QSPI_HandleTypeDef * hqspi )
{
QSPI_CommandTypeDef sCommand ;
uint8_t reg ;
/* Read Volatile Configuration register --------------------------- */
sCommand . InstructionMode = QSPI_INSTRUCTION_1_LINE ;
sCommand . Instruction = READ_VOL_CFG_REG_CMD ;
sCommand . AddressMode = QSPI_ADDRESS_NONE ;
sCommand . AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE ;
sCommand . DataMode = QSPI_DATA_1_LINE ;
sCommand . DummyCycles = 0 ;
sCommand . DdrMode = QSPI_DDR_MODE_DISABLE ;
sCommand . DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY ;
sCommand . SIOOMode = QSPI_SIOO_INST_EVERY_CMD ;
sCommand . NbData = 1 ;
if ( HAL_QSPI_Command ( & QSPIHandle , & sCommand , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
if ( HAL_QSPI_Receive ( & QSPIHandle , & reg , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
/* Enable write operations ---------------------------------------- */
QSPI_WriteEnable ( & QSPIHandle ) ;
/* Write Volatile Configuration register (with new dummy cycles) -- */
sCommand . Instruction = WRITE_VOL_CFG_REG_CMD ;
MODIFY_REG ( reg , 0xF0 , ( DUMMY_CLOCK_CYCLES_READ_QUAD < < POSITION_VAL ( 0xF0 ) ) ) ;
if ( HAL_QSPI_Command ( & QSPIHandle , & sCommand , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
if ( HAL_QSPI_Transmit ( & QSPIHandle , & reg , HAL_QPSI_TIMEOUT_DEFAULT_VALUE ) ! = HAL_OK )
{
Error_Handler ( ) ;
}
}
/**
* @ brief This function is executed in case of error occurrence .
* @ param None
* @ retval None
*/
static void Error_Handler ( void )
{
BSP_LED_On ( LED4 ) ;
/* User may add here some code to deal with this error */
while ( 1 )
{
HAL_Delay ( 100 ) ;
BSP_LED_Toggle ( LED4 ) ;
}
}
# ifdef USE_FULL_ASSERT
/**
* @ brief Reports the name of the source file and the source line number
* where the assert_param error has occurred .
* @ param file : pointer to the source file name
* @ param line : assert_param error line source number
* @ retval None
*/
void assert_failed ( uint8_t * file , uint32_t line )
{
/* User can add his own implementation to report the file name and line number,
ex : printf ( " Wrong parameters value: file %s on line %d \r \n " , file , line ) */
/* Infinite loop */
while ( 1 )
{
}
}
# endif
/**
* @ }
*/
/**
* @ }
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/