-
Notifications
You must be signed in to change notification settings - Fork 15
8-Bit NOR devices cause hard fault on Hal_Nor_Init #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
After evaluating some more, i do not see a straightforward solution to this problem. |
Spent the last day looking at this;
I'm currently in the process of modifying the HAL to correctly support both 8-bit and 16-bit data buses for my purposes. Let me know if you need any info. |
Hello @StephenPPEng, Thank you for the report. Regarding the issue, and after a first check in the RM0385, we have a chapter ![]() So, if you may share with us, your ioc File and the version of CubeMX you are using, we can analyze it further. With regards, |
Absolutely, once I am back at my computer I will share the .ioc
For now, I should clarify:
I have my NOR on Bank 1(NOR/SRAM), Sub bank 3 (NE3).
MPU is modified to allow full access to 0x68000000 for 512kB.
The NOR chip is byte-addressed (8 bit) only, but supports CFI in 16-Bit mode.
Best,
Stephen
…________________________________
From: KRASTM ***@***.***>
Sent: Friday, April 11, 2025 10:22:33 AM
To: STMicroelectronics/stm32f7xx-hal-driver ***@***.***>
Cc: Stephen Kercher ***@***.***>; Mention ***@***.***>
Subject: Re: [STMicroelectronics/stm32f7xx-hal-driver] 8-Bit NOR devices cause hard fault on Hal_Nor_Init (Issue #14)
Hello @StephenPPEng<https://github.com/StephenPPEng>,
Thank you for the report.
Regarding the issue, and after a first check in the RM0385, we have a chapter 13.5 External device address mapping at the page 312 describing how the external memory is divided into fixed-size banks of 256 Mbytes each, below an extract of the different banks and the supported memory type for each one (for the bank 3, we have only NAND flash memory):
image.png (view on web)<https://github.com/user-attachments/assets/098dbff1-cb3b-42c7-8938-3970689c1cc4>
So, if you may share with us, your ioc File and the version of CubeMX you are using, we can analyze it further.
With regards,
—
Reply to this email directly, view it on GitHub<#14 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BIOTX3N6QZKY2ZVVSIULN532Y7F2TAVCNFSM6AAAAAB2XAD4I2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDOOJXGA3DEMRUGU>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
[https://avatars.githubusercontent.com/u/156921537?s=20&v=4]KRASTM left a comment (STMicroelectronics/stm32f7xx-hal-driver#14)<#14 (comment)>
Hello @StephenPPEng<https://github.com/StephenPPEng>,
Thank you for the report.
Regarding the issue, and after a first check in the RM0385, we have a chapter 13.5 External device address mapping at the page 312 describing how the external memory is divided into fixed-size banks of 256 Mbytes each, below an extract of the different banks and the supported memory type for each one (for the bank 3, we have only NAND flash memory):
image.png (view on web)<https://github.com/user-attachments/assets/098dbff1-cb3b-42c7-8938-3970689c1cc4>
So, if you may share with us, your ioc File and the version of CubeMX you are using, we can analyze it further.
With regards,
—
Reply to this email directly, view it on GitHub<#14 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BIOTX3N6QZKY2ZVVSIULN532Y7F2TAVCNFSM6AAAAAB2XAD4I2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDOOJXGA3DEMRUGU>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
This email is intended solely for the use of the individual to whom it is addressed and may contain confidential and/or privileged material. Any views or opinions presented are solely those of the author and do not necessarily represent those of Precision Planting. If you are not the intended recipient, be advised that you have received this email in error and that any use, dissemination, forwarding, printing, or copying of this email is strictly prohibited. Neither AGCO nor the sender accepts any responsibility for viruses, and it is your responsibility to scan, and virus check the e-mail and its attachment(s) (if any).
|
@KRASTM
Additionally, here is the final version of how to get the Command Set (notice the 8-bit NOR_WRITE). This can always be 8-bit because the standard incicates that the return value for the command set will be 1 byte. |
TL;DR: //...
else
{
/* Get the value of the command set */
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
{
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI_BYTE),
NOR_CMD_DATA_CFI);
}
else
{
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI);
}
hnor->CommandSet = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_ADDRESS_COMMAND_SET);
status = HAL_NOR_ReturnToReadMode(hnor);
}
//... My suggested change: //...
else
{
/* Get the value of the command set */
NOR_WRITE_8b(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI),
NOR_CMD_DATA_CFI);
hnor->CommandSet = *(__IO uint8_t *)NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_ADDRESS_COMMAND_SET);
status = HAL_NOR_ReturnToReadMode(hnor);
}
//...
/**
* @brief NOR memory write 8-bit data to specified address.
* @param __ADDRESS__ NOR memory address
* @param __DATA__ Data to write
* @retval None
*/
#define NOR_WRITE_8b(__ADDRESS__, __DATA__) do{ \
(*(__IO uint8_t *)((uint32_t)(__ADDRESS__)) = (__DATA__)); \
__DSB(); \
} while(0) And this needs to be done everywhere in the HAL_NOR file.To support different data types, HAL_NOR_Read() and HAL_NOR_Program() must have their signatures changed to the following
and |
Hello @StephenPPEng, Thanks for the details, I will forward your suggestion to our team. With regards, |
ST Internal Reference: 207766 |
For another reference, here is what my HAL_NOR_Program() looks like /**
* @brief Program data to NOR memory
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
* the configuration information for NOR module.
* @param pAddress Device address
* @param data the data to be programmed
* @retval HAL status
*/
HAL_StatusTypeDef HAL_NOR_Program(NOR_HandleTypeDef *hnor, uint8_t *pAddress, uint32_t data)
{
uint32_t deviceaddress;
HAL_StatusTypeDef status = HAL_OK;
/* Check the NOR controller state */
if (hnor->State == HAL_NOR_STATE_BUSY)
{
return HAL_BUSY;
}
else if (hnor->State == HAL_NOR_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hnor);
/* Update the NOR controller state */
hnor->State = HAL_NOR_STATE_BUSY;
/* Select the NOR device address */
if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
{
deviceaddress = NOR_MEMORY_ADRESS1;
}
else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
{
deviceaddress = NOR_MEMORY_ADRESS2;
}
else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
{
deviceaddress = NOR_MEMORY_ADRESS3;
}
else /* FMC_NORSRAM_BANK4 */
{
deviceaddress = NOR_MEMORY_ADRESS4;
}
/* Send program data command */
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
{
uint32_t cycle1Addr = NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST);
uint32_t cycle2Addr = NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND);
uint32_t cycle3Addr = NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD);
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
{
NOR_WRITE_8b(cycle1Addr, NOR_CMD_DATA_FIRST);
NOR_WRITE_8b(cycle2Addr, NOR_CMD_DATA_SECOND);
NOR_WRITE_8b(cycle3Addr, NOR_CMD_DATA_PROGRAM);
}
else
{
NOR_WRITE(cycle1Addr, NOR_CMD_DATA_FIRST);
NOR_WRITE(cycle2Addr, NOR_CMD_DATA_SECOND);
NOR_WRITE(cycle3Addr, NOR_CMD_DATA_PROGRAM);
}
}
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
{
NOR_WRITE(pAddress, NOR_CMD_WORD_PROGRAM);
}
else
{
/* Primary command set not supported by the driver */
status = HAL_ERROR;
}
if (status != HAL_ERROR)
{
/* Write the data */
if(uwNORMemoryDataWidth == NOR_MEMORY_8B)
{
NOR_WRITE_8b(pAddress, data & 0xFF);
}
else
{
pAddress = (uint8_t *)((uint32_t)pAddress & 0xFFFFFFFE); /* Address must be even for 16 bits access */
NOR_WRITE(pAddress, data & 0xFFFF);
}
}
/* Check the NOR controller state */
hnor->State = HAL_NOR_STATE_READY;
/* Process unlocked */
__HAL_UNLOCK(hnor);
}
else
{
return HAL_ERROR;
}
return status;
} And my HAL_NOR_Read() /**
* @brief Read data from NOR memory
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
* the configuration information for NOR module.
* @param pAddress pointer to Device address
* @param pData pointer to read data
* @retval HAL status
*/
HAL_StatusTypeDef HAL_NOR_Read(NOR_HandleTypeDef *hnor, uint8_t *pAddress, void *pData)
{
uint32_t deviceaddress;
HAL_NOR_StateTypeDef state;
HAL_StatusTypeDef status = HAL_OK;
if(pData == NULL)
{
return HAL_ERROR;
}
/* Check the NOR controller state */
state = hnor->State;
if (state == HAL_NOR_STATE_BUSY)
{
return HAL_BUSY;
}
else if (state == HAL_NOR_STATE_PROTECTED)
{
return HAL_ERROR;
}
else if (state == HAL_NOR_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hnor);
/* Update the NOR controller state */
hnor->State = HAL_NOR_STATE_BUSY;
/* Select the NOR device address */
if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
{
deviceaddress = NOR_MEMORY_ADRESS1;
}
else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
{
deviceaddress = NOR_MEMORY_ADRESS2;
}
else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
{
deviceaddress = NOR_MEMORY_ADRESS3;
}
else /* FMC_NORSRAM_BANK4 */
{
deviceaddress = NOR_MEMORY_ADRESS4;
}
/* Send read data command */
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
{
uint32_t cycle1Addr = NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST);
uint32_t cycle2Addr = NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND);
uint32_t cycle3Addr = NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD);
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
{
NOR_WRITE_8b(cycle1Addr, NOR_CMD_DATA_FIRST);
NOR_WRITE_8b(cycle2Addr, NOR_CMD_DATA_SECOND);
NOR_WRITE_8b(cycle3Addr, NOR_CMD_DATA_READ_RESET);
}
else
{
NOR_WRITE(cycle1Addr, NOR_CMD_DATA_FIRST);
NOR_WRITE(cycle2Addr, NOR_CMD_DATA_SECOND);
NOR_WRITE(cycle3Addr, NOR_CMD_DATA_READ_RESET);
}
}
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
{
NOR_WRITE(pAddress, NOR_CMD_READ_ARRAY);
}
else
{
/* Primary command set not supported by the driver */
status = HAL_ERROR;
}
if (status != HAL_ERROR)
{
/* Read the data */
if(uwNORMemoryDataWidth == NOR_MEMORY_8B)
{
*(uint8_t *)pData = (uint8_t)(*(__IO uint8_t *)pAddress);
}
else
{
/* Address must be even for 16 bits access */
pAddress = (uint8_t *)((uint32_t)pAddress & 0xFFFFFFFE);
*(uint16_t *)pData = (uint16_t)(*(__IO uint16_t *)pAddress);
}
}
/* Check the NOR controller state */
hnor->State = state;
/* Process unlocked */
__HAL_UNLOCK(hnor);
}
else
{
return HAL_ERROR;
}
return status;
} Also note: |
I'm putting together a pull request for this issue |
Describe the set-up
Custom STM32F756BG Board.
Macronix MX29LV040CTI (or any other 8-bit NOR flash)
Visual Studio IDE; Code generated from STM32CubeMx.
Describe the bug
in HAL_NOR_Init, the code Hard Faults when setting the Nor ->CommandSet.
Additionally, before this, the NOR_WRITE is writing 16-bit values to a 8-bit device.
How To Reproduce
1- Spin up a project in stm32cubemx that has a NOR flash on NORSRAM_Bank_3 in Write mode (8-bit data)
2-Ensure the MPU is configured correctly
3- Generate Code
4- Run the code on a compatible board/device
The modules that you suspect to be the cause of the problem (Driver, BSP, MW ...)
HAL -> NOR
The use case that generates the problem
When running HAL_NOR_Init in the FMC for a 8-bit parallel NOR flash chip
Additional context
ISSUE1:
NOR_WRITE
casts addresses to a 16-bit pointer. So when 'writing' to a 8-bit Flash, it is writing 2 bytes instead of just 1.ISSUE2:
hnor->CommandSet = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_ADDRESS_COMMAND_SET);
This line also has an explicit 16-bit cast. WHen working with 8-bit flash, this should be an 8-bit cast - THe 16-bit cast is causing a mis-aligned memory access when reading the command set (the address is 0x13... which is odd).
Odd-alligned memory access is prohibited for 16-bit pointers.
ISSUE3:
this sectionis meaningless as written. theNOR_ADDR_SHIFT
already takes theuwNORMemoryDataWidth
into account. There does not need to be 2 separate calls for 2 addresses since theNOR_ADDR_SHIFT
already modifies the address.This was a misunderstanding by me. The shift is indeed necessary.
The issues raised here have implications for the rest of the HAL NOR.
Anywhere that
NOR_WRITE
is used.The text was updated successfully, but these errors were encountered: