AnsweredAssumed Answered

STM32F746, Flash

Question asked by s.boris on Aug 9, 2016
Latest reply on Aug 21, 2017 by Rocco Porcellio
Hello, I try to write/read from external flash memory on STM32F746 - DISCOVERY board. The problem is that when I use RTOS the program didnt run. The program never call: void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi)
This is my code
static void FlashCallback(void const *n) // call on every 10ms, its working
{
    app_ee_test();
}
 
/*****************************************************************************/
/*****************************************************************************/
static void hw_ee_gpio_init()
{
    GPIO_InitTypeDef GPIO_InitStruct;
 
      /* Enable the QuadSPI memory interface clock */
      QSPI_CLK_ENABLE();
 
      /* Reset the QuadSPI memory interface */
      QSPI_FORCE_RESET();
      QSPI_RELEASE_RESET();
 
      /* Enable GPIO clocks */
      QSPI_CS_GPIO_CLK_ENABLE();
      QSPI_CLK_GPIO_CLK_ENABLE();
      QSPI_D0_GPIO_CLK_ENABLE();
      QSPI_D1_GPIO_CLK_ENABLE();
      QSPI_D2_GPIO_CLK_ENABLE();
      QSPI_D3_GPIO_CLK_ENABLE();
 
      /* QSPI CS GPIO pin configuration  */
      GPIO_InitStruct.Pin       = QSPI_CS_PIN;
      GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull      = GPIO_PULLUP;
      GPIO_InitStruct.Speed     = GPIO_SPEED_HIGH;
      GPIO_InitStruct.Alternate = GPIO_AF_CS;
      HAL_GPIO_Init(QSPI_CS_GPIO_PORT, &GPIO_InitStruct);
 
      /* QSPI CLK GPIO pin configuration  */
      GPIO_InitStruct.Pin       = QSPI_CLK_PIN;
      GPIO_InitStruct.Pull      = GPIO_NOPULL;
      GPIO_InitStruct.Alternate = GPIO_AF_CLK;
      HAL_GPIO_Init(QSPI_CLK_GPIO_PORT, &GPIO_InitStruct);
 
      /* QSPI D0 GPIO pin configuration  */
      GPIO_InitStruct.Pin       = QSPI_D0_PIN;
      GPIO_InitStruct.Alternate = GPIO_AF_D0;
      HAL_GPIO_Init(QSPI_D0_GPIO_PORT, &GPIO_InitStruct);
 
      /* QSPI D1 GPIO pin configuration  */
      GPIO_InitStruct.Pin       = QSPI_D1_PIN;
      GPIO_InitStruct.Alternate = GPIO_AF_D1;
      HAL_GPIO_Init(QSPI_D1_GPIO_PORT, &GPIO_InitStruct);
 
      /* QSPI D2 GPIO pin configuration  */
      GPIO_InitStruct.Pin       = QSPI_D2_PIN;
      GPIO_InitStruct.Alternate = GPIO_AF_D2;
      HAL_GPIO_Init(QSPI_D2_GPIO_PORT, &GPIO_InitStruct);
 
      /* QSPI D3 GPIO pin configuration  */
      GPIO_InitStruct.Pin       = QSPI_D3_PIN;
      GPIO_InitStruct.Alternate = GPIO_AF_D3;
      HAL_GPIO_Init(QSPI_D3_GPIO_PORT, &GPIO_InitStruct);
 
      /* NVIC configuration for QSPI interrupt */
      HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x01, 0);
      HAL_NVIC_EnableIRQ(QUADSPI_IRQn);
}
 
/*****************************************************************************/
/*****************************************************************************/
static void hw_ee_auto_polling_mem_ready(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)
  {
    hw_ee_system_error();
  }
}
 
/*****************************************************************************/
/*****************************************************************************/
static void hw_ee_write_enable(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)
  {
    hw_ee_system_error();
  }
 
  /* 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)
  {
    hw_ee_system_error();
  }
}
 
/*****************************************************************************/
/*****************************************************************************/
static void hw_ee_dummy_cycle_connfig(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)
  {
    hw_ee_system_error();
  }
 
  if (HAL_QSPI_Receive(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    hw_ee_system_error();
  }
 
  /* Enable write operations ---------------------------------------- */
  hw_ee_write_enable(&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)
  {
    hw_ee_system_error();
  }
 
  if (HAL_QSPI_Transmit(&QSPIHandle, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    hw_ee_system_error();
  }
}
 
/*****************************************************************************/
/*****************************************************************************/
void hw_ee_init()
{
     QSPIHandle.Instance = QUADSPI;
      /* ClockPrescaler set to 2, so QSPI clock = 216MHz / (2+1) = 72MHz */
      QSPIHandle.Init.ClockPrescaler     = 2;
      QSPIHandle.Init.FifoThreshold      = 4;
      QSPIHandle.Init.SampleShifting     = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
      QSPIHandle.Init.FlashSize          = POSITION_VAL(0x1000000) - 1;
      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)
      {
          hw_ee_system_error();
      }
 
      hw_ee_gpio_init();
}
 
/*****************************************************************************/
/*****************************************************************************/
void QUADSPI_IRQHandler(void)
{
  HAL_QSPI_IRQHandler(&QSPIHandle);
}
 
/*****************************************************************************/
/*****************************************************************************/
void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi)
{
  CmdCplt++;
}
 
/*****************************************************************************/
/*****************************************************************************/
void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi)
{
  RxCplt++;
}
 
/*****************************************************************************/
/*****************************************************************************/
void HAL_QSPI_TxCpltCallback(QSPI_HandleTypeDef *hqspi)
{
  TxCplt++;
}
 
/*****************************************************************************/
/*****************************************************************************/
void HAL_QSPI_StatusMatchCallback(QSPI_HandleTypeDef *hqspi)
{
  StatusMatch++;
}
 
/*****************************************************************************/
/*****************************************************************************/
void app_ee_test()
{
 
      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;
 
        switch(step)
        {
          case 0:
            CmdCplt = 0;
 
            /* Initialize Reception buffer --------------------------------------- */
            for (i = 0; i < BUFFERSIZE; i++)
            {
              aRxBuffer[i] = 0;
            }
 
            /* Enable write operations ------------------------------------------- */
            hw_ee_write_enable(&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)
            {
              hw_ee_system_error();
            }
 
            step++;
            break;
 
          case 1:
            if(CmdCplt != 0)
            {
              CmdCplt = 0;
              StatusMatch = 0;
 
              /* Configure automatic polling mode to wait for end of erase ------- */
              hw_ee_dummy_cycle_connfig(&QSPIHandle);
 
              step++;
            }
            break;
 
          case 2:
            if(StatusMatch != 0)
            {
              StatusMatch = 0;
              TxCplt = 0;
 
              /* Enable write operations ----------------------------------------- */
              hw_ee_write_enable(&QSPIHandle);
 
              /* Writing Sequence ------------------------------------------------ */
              sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;
              sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
              sCommand.DataMode    = QSPI_DATA_4_LINES;
              sCommand.NbData      = BUFFERSIZE;
 
              if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
              {
                  hw_ee_system_error();
              }
 
              if (HAL_QSPI_Transmit_IT(&QSPIHandle, aTxBuffer) != HAL_OK)
              {
                  hw_ee_system_error();
              }
 
              step++;
            }
            break;
 
          case 3:
            if(TxCplt != 0)
            {
              TxCplt = 0;
              StatusMatch = 0;
 
              /* Configure automatic polling mode to wait for end of program ----- */
              hw_ee_auto_polling_mem_ready(&QSPIHandle);
 
              step++;
            }
            break;
 
          case 4:
            if(StatusMatch != 0)
            {
              StatusMatch = 0;
              RxCplt = 0;
 
              /* Configure Volatile Configuration register (with new dummy cycles) */
              hw_ee_dummy_cycle_connfig(&QSPIHandle);
 
              /* Reading Sequence ------------------------------------------------ */
              sCommand.Instruction = QUAD_OUT_FAST_READ_CMD;
              sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD;
 
              if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
              {
                  hw_ee_system_error();
              }
 
              if (HAL_QSPI_Receive_IT(&QSPIHandle, aRxBuffer) != HAL_OK)
              {
                  hw_ee_system_error();
              }
              step++;
            }
            break;
 
          case 5:
            if (RxCplt != 0)
            {
              RxCplt = 0;
 
              /* Result comparison ----------------------------------------------- */
              for (i = 0; i < BUFFERSIZE; i++)
              {
                if (aRxBuffer[i] != aTxBuffer[i])
                {
                  BSP_LED_On(LED1);
                }
              }
              BSP_LED_Toggle(LED1);
 
              address += QSPI_PAGE_SIZE;
              if(address >= QSPI_END_ADDR)
              {
                address = 0;
              }
              step = 0;
            }
            break;
 
          default :
              hw_ee_system_error();
 
}
}

Outcomes