cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U585 OSPI hard fault on memory-mapped write

BHamm
Associate II

I'm trying to follow the OSPI_NOR_MemoryMapped STM32CubeIDE example, but for a different device (W25Q128FV). Write Enable, Read Status, and Erase Sector commands behave as expected, as well as memory-mapped reads. This has been confirmed by monitoring the OSPI lines with a logic analyzer, and comparing against the W25Q128FV datasheet.

The one thing that does not work is memory-mapped writes. No activity occurs on the OSPI lines; a fault occurs on the instruction to write to the OSPI1 address. The Cortex-M33 registers show a precise bus fault at address OCTOSPI1_BASE (0x90000000).

Any suggestions are appreciated.

OSPI_HandleTypeDef ospiHandle = {
      .Instance = OCTOSPI1,
      .Init = {
         .FifoThreshold = 1,
         .DualQuad = HAL_OSPI_DUALQUAD_DISABLE,
         .MemoryType = HAL_OSPI_MEMTYPE_MACRONIX,
         .DeviceSize = 24,
         .ChipSelectHighTime = 2,
         .FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE,
         .ClockMode = HAL_OSPI_CLOCK_MODE_0,
         .WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED,
         .ClockPrescaler = 256,
         .SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE,
         .DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE,
         .ChipSelectBoundary = 0,
         .DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED,
         .MaxTran = 0,
         .Refresh = 0,
      },
 
Init(void) {
// Enable clock
_HAL_RCC_OSPI1_CLK_ENABLE();
// Enable pins (CS, CLK, QSPI Data 1-4)  
...
// Initialize
   if (HAL_OSPI_Init(&ospiHandle) != HAL_OK)
   {
      Error_Handler();
   }
 
// Manager config
   OSPIM_CfgTypeDef sOspiManagerCfg = {0};
   sOspiManagerCfg.ClkPort = 1;
   sOspiManagerCfg.DQSPort = 1;
   sOspiManagerCfg.NCSPort = 1;
   sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
   sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
   if (HAL_OSPIM_Config(&ospiHandle, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
   {
      Error_Handler();
   }
   HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};
   HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
   HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
   if (HAL_OSPI_DLYB_SetConfig(&ospiHandle, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
   {
      Error_Handler();
   }
 
// Attempted with both Page Program (CMD_PP = 02h) and Quad Page Program (CMD_QPP = 32h); fault occurs with both
static bool EnableMemoryMappedMode(uint8_t readInstruction, uint8_t writeInstruction)
{
  // Details of Write Enable function excluded since confirmed to work
   SetWriteEnable(self);
 
   OSPI_RegularCmdTypeDef command = {0};
   command.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
   command.FlashId       = HAL_OSPI_FLASH_ID_1;
   command.Instruction   = writeInstruction;
   command.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
   command.NbData        = 1;
 
   switch(writeInstruction)
   {
      case CMD_QPP:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      =  HAL_OSPI_DATA_4_LINES;
         break;
      case CMD_PP:
      default:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      = HAL_OSPI_DATA_1_LINE;
         command.Instruction   = DEFAULT_CMD_PP;
         break;
   }
 
   bool success = true;
 
   if (HAL_OSPI_Command(&ospiHandle, &command, OSPI_READY_TIMEOUT) != HAL_OK)
   {
      success = false;
   }
 
   command.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
   command.Instruction   = readInstruction;
   command.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
 
   switch(readInstruction)
   {
      case CMD_QREAD:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      =  HAL_OSPI_DATA_4_LINES;
         command.DummyCycles    = 8;
         break;
      case CMD_READ:
      default:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      = HAL_OSPI_DATA_1_LINE;
         command.DummyCycles    = 0;
         break;
   }
 
   if (HAL_OSPI_Command(&ospiHandle, &command, OSPI_READY_TIMEOUT) != HAL_OK)
   {
      success = false;
   }
 
   OSPI_MemoryMappedTypeDef memMappedCfg = {0};
   memMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE;
   memMappedCfg.TimeOutPeriod     = 0xFFFF;
   if (HAL_OSPI_MemoryMapped(&ospiHandle, &memMappedCfg) != HAL_OK)
   {
      success = false;
   }
 
   return success;
}
 
test(void)
{
      EraseBlocks(self, 0, 0);
 
      static uint8_t commands[3] = { DEFAULT_CMD_QPP, DEFAULT_CMD_4PP, DEFAULT_CMD_PP };
 
      for(uint32_t i = 0, testW = 0; i < 3 && !found; i++)
      {
         // Tried PP and READ (not-quad commands) as well
         // EnableMemoryMappedMode(CMD_READ, CMD_PP);
         EnableMemoryMappedMode(CMD_QREAD, CMD_QPP);
 
         uint32_t testR = 0xFFFFFFFF;
 
         // Verify erase (overwites 0xAA with expected 0xFF)
         uint8_t value = 0xAA;
         uint8_t * mem_addr = (uint8_t *)(OCTOSPI1_BASE);
         value = *mem_addr;
 
         // Hard fault occurs here
         *mem_addr = 0xAA;
}

1 ACCEPTED SOLUTION

Accepted Solutions
BDoon.1
Associate III

Hey BHamm! I am looking at this currently, and have seen the same issue you were seeing. It turns out this is an issue covered by the Errata, specifically item 2.6.1. "Memory-mapped write error response when DQS output is disabled"

Setting the DQSMode field to HAL_OSPI_DQS_ENABLE in the OSPI_RegularCmdTypeDef for the HAL_OSPI_OPTYPE_WRITE_CFG command fixes the issue. ie:

command.DQSMode = HAL_OSPI_DQS_ENABLE;

View solution in original post

9 REPLIES 9

Not clear how well this responds to, and propagates errors, rather than just ploughing forward.

If the memory mapping fails, it will fault.

Suggest unpacking and reviewing OSPI peripheral content.

Enable asserts() and check error/status reporting.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Asserts are enabled, and all functions return the HAL_OK status.

I've got some QuadSPI Macronix parts running on the NUCLEO-U575ZI-Q

The prescaler here looks very high, and the Winbond's run more like the Micron's, not sure that's the issue here.

Not sure the NOR Flash write mechanics are well suited to memory mapped write, as there are a lot of dependencies, and the device goes out to lunch for a while, in a manner not architected into the STM32

Might try my luck later..

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Check ConfigMPU() settings, make sure the space isn't designated Read-Only

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
static bool EnableMemoryMappedMode(uint8_t readInstruction, uint8_t writeInstruction)
{
   OSPI_RegularCmdTypeDef command = {0};
 
   command.FlashId       = HAL_OSPI_FLASH_ID_1;
 
  command.InstructionSize    = HAL_OSPI_INSTRUCTION_8_BITS;
  command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
  command.AddressSize        = HAL_OSPI_ADDRESS_24_BITS;
  command.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_DISABLE;
  command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
  command.DataDtrMode        = HAL_OSPI_DATA_DTR_DISABLE;
  command.DQSMode            = HAL_OSPI_DQS_DISABLE;
  command.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;
 
 
   command.NbData        = 1;
 
   command.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
   command.Instruction   = writeInstruction;
 
   switch(writeInstruction)
   {
      case CMD_QPP:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      =  HAL_OSPI_DATA_4_LINES;
         break;
      case CMD_PP:
      default:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      = HAL_OSPI_DATA_1_LINE;
         command.Instruction   = DEFAULT_CMD_PP;
         break;
   }
 
 
   if (HAL_OSPI_Command(&ospiHandle, &command, OSPI_READY_TIMEOUT) != HAL_OK)
   {
      return(false);
   }
 
   command.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
   command.Instruction   = readInstruction;
 
   switch(readInstruction)
   {
      case CMD_QREAD:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      =  HAL_OSPI_DATA_4_LINES;
         command.DummyCycles    = 8;
         break;
      case CMD_READ:
      default:
         command.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
         command.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
         command.DataMode      = HAL_OSPI_DATA_1_LINE;
         command.DummyCycles    = 0;
         break;
   }
 
   if (HAL_OSPI_Command(&ospiHandle, &command, OSPI_READY_TIMEOUT) != HAL_OK)
   {
      return(false);
   }
 
   OSPI_MemoryMappedTypeDef memMappedCfg = {0};
   memMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE;
   memMappedCfg.TimeOutPeriod     = 80;
   if (HAL_OSPI_MemoryMapped(&ospiHandle, &memMappedCfg) != HAL_OK)
   {
      return(false);
   }
 
   return(true);
} 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Neither the OSPI_NOR_MemoryMapped example or my app appear to have any settings related to the MPU; they're leaving the defaults.

No difference, unfortunately. (The extra parameters suggested for writes are only the zero-default options, so there's no difference. I had also confirmed all HAL functions returned HAL_OK, so no difference. I've tried various memMappedCfg.TimeOutPeriod, and actually started out with 80, since that is what the OSPI_NOR_MemoryMapped example uses.)

With the prescaler above, or prescaler of 8, memory-mapped reads are successful. I'm unclear if that implies memory-mapped writes should also be successful with those prescaler values.

I tried the Micron configuration, with no change.

The confusing part is that it isn't even attempting communication with the flash device. That implies there is some configuration that is entirely internal to the STM32, and that it may not have anything to do with the chip-specific configuration parameters.

BDoon.1
Associate III

Hey BHamm! I am looking at this currently, and have seen the same issue you were seeing. It turns out this is an issue covered by the Errata, specifically item 2.6.1. "Memory-mapped write error response when DQS output is disabled"

Setting the DQSMode field to HAL_OSPI_DQS_ENABLE in the OSPI_RegularCmdTypeDef for the HAL_OSPI_OPTYPE_WRITE_CFG command fixes the issue. ie:

command.DQSMode = HAL_OSPI_DQS_ENABLE;