2025-01-29 08:11 AM - edited 2025-01-30 05:29 AM
I'm working with a STM32H723ZG and trying to set up SPI2 communication.
I tracked down the issue where my LL_SPI_SetMode(SPI2, LL_SPI_MODE_MASTER) call does not set the Master bit in SPI2_CFG2 to 1, as intended (see Test #1 below). However, if I call the function twice, the second one does set the Master bit to 1 (see Test #2 below).
Does anyone know how that could happen?
Test #1:
/* Configure SPI2 communication */
LL_SPI_SetBaudRatePrescaler(SPI2, LL_SPI_BAUDRATEPRESCALER_DIV4);
LL_SPI_SetTransferDirection(SPI2,LL_SPI_FULL_DUPLEX);
LL_SPI_SetDataWidth(SPI2, LL_SPI_DATAWIDTH_8BIT);
LL_SPI_SetNSSMode(SPI2, LL_SPI_NSS_SOFT);
LL_SPI_SetMode(SPI2, LL_SPI_MODE_MASTER); //this first call does nothing?
Disassembly block when debugging for the last 2 lines:
1629: MODIFY_REG(SPIx->CFG2, SPI_CFG2_SSM | SPI_CFG2_SSOE, NSS);
0x08001D2E 68C1 LDR r1,[r0,#0x0C]
0x08001D30 F0215110 BIC r1,r1,#0x24000000
0x08001D34 F0416180 ORR r1,r1,#0x4000000
0x08001D38 60C1 STR r1,[r0,#0x0C]
665: MODIFY_REG(SPIx->CFG2, SPI_CFG2_MASTER, Mode);
666: }
667:
668: /**
669: * @brief Get SPI Mode (Master or Slave)
670: * @rmtoll CFG2 MASTER LL_SPI_GetMode
671: * SPIx SPI Instance
672: * @retval Returned value can be one of the following values:
673: * @arg @ref LL_SPI_MODE_MASTER
674: * @arg @ref LL_SPI_MODE_SLAVE
675: */
676: __STATIC_INLINE uint32_t LL_SPI_GetMode(SPI_TypeDef *SPIx)
677: {
0x08001D3A 68C1 LDR r1,[r0,#0x0C]
0x08001D3C F4410180 ORR r1,r1,#0x400000
0x08001D40 60C1 STR r1,[r0,#0x0C]
918: }
0x08001D42 BD70 POP {r4-r6,pc}
SPI2_CFG2 after all of this code finishes executing:
Test #2:
/* Configure SPI2 communication */
LL_SPI_SetBaudRatePrescaler(SPI2, LL_SPI_BAUDRATEPRESCALER_DIV4);
LL_SPI_SetTransferDirection(SPI2,LL_SPI_FULL_DUPLEX);
LL_SPI_SetDataWidth(SPI2, LL_SPI_DATAWIDTH_8BIT);
LL_SPI_SetNSSMode(SPI2, LL_SPI_NSS_SOFT);
LL_SPI_SetMode(SPI2, LL_SPI_MODE_MASTER); //this first call does nothing?
LL_SPI_SetMode(SPI2, LL_SPI_MODE_MASTER); //second call actually works??
Disassembly block when debugging for the last 3 lines:
1629: MODIFY_REG(SPIx->CFG2, SPI_CFG2_SSM | SPI_CFG2_SSOE, NSS);
0x08001D2E 68C1 LDR r1,[r0,#0x0C]
0x08001D30 F0215110 BIC r1,r1,#0x24000000
0x08001D34 F0416180 ORR r1,r1,#0x4000000
0x08001D38 60C1 STR r1,[r0,#0x0C]
665: MODIFY_REG(SPIx->CFG2, SPI_CFG2_MASTER, Mode);
666: }
667:
668: /**
669: * @brief Get SPI Mode (Master or Slave)
670: * @rmtoll CFG2 MASTER LL_SPI_GetMode
671: * SPIx SPI Instance
672: * @retval Returned value can be one of the following values:
673: * @arg @ref LL_SPI_MODE_MASTER
674: * @arg @ref LL_SPI_MODE_SLAVE
675: */
676: __STATIC_INLINE uint32_t LL_SPI_GetMode(SPI_TypeDef *SPIx)
677: {
0x08001D3A 68C1 LDR r1,[r0,#0x0C]
0x08001D3C F4410180 ORR r1,r1,#0x400000
0x08001D40 60C1 STR r1,[r0,#0x0C]
665: MODIFY_REG(SPIx->CFG2, SPI_CFG2_MASTER, Mode);
0x08001D42 68C1 LDR r1,[r0,#0x0C]
0x08001D44 F4410180 ORR r1,r1,#0x400000
0x08001D48 60C1 STR r1,[r0,#0x0C]
918: }
0x08001D4A BD70 POP {r4-r6,pc}
SPI2_CFG2 after all of this code finishes executing:
When stepping through in debug mode with the SPI2_CFG2 view open, I can see that the first SetMode call does not turn the Master bit on and the second SetMode call does. It doesn't make sense to me, since the disassembly code blocks are identical (LDR, ORR, STR sequence with identical arguments).
I've tried both with and without CPU_CACHE_Enable() calls and the result is the same.
Although making the call twice appears to be an effective workaround, this behavior is very unsettling and makes me question whether other configuration commands are "getting through". Any help is appreciated!
Solved! Go to Solution.
2025-01-30 05:41 AM
Thanks, yes the SPI is disabled and IOLOCK is off before making these changes.
This issue appears to be a result of the following 4 conditions:
- SSIOP bit being 0 (low level active for SS)
- SSI bit being 0 (SS input low)
- SSM bit being 1 (software control of SS)
- MASTER bit being 1 (SPI configured as master)
This combination causes an immediate MODF (mode fault) which automatically switches the MASTER bit to 0 (SPI configured as slave). It's intended to work as a feature for resolving multi-master conflicts.
I didn't have this issue with the STM32F7 series or see notes about this in the migration document (STM32F7 to STM32H7), but it seems to be a subtle difference in the SPI feature set.
By setting the SSI bit to 1 before attempting to set MASTER=1, I'm able to avoid this problem.
Thanks!
2025-01-29 10:01 AM
Apparently, there is some issue with the NSS configuration and a MODF (mode fault) is being generated the first time the SPI2 is switched to Master=1. That MODF automatically switches SPI2 to slave mode (Master=0). I guess when the SetMode command is issue a second time, that MODF is not acted on and the change to Master=1 stays...
2025-01-30 01:44 AM
Hello @BPric.557
Please ensure that the SPI peripheral and IOLOCK bit (In SPI CR1 register) are disabled before setting SPI_CFG1 and SPI_CFG2 registers.
Here is an example of how you might structure the configuration code:
// Ensure SPI is disabled before configuration
LL_SPI_Disable(SPI2);
// Configure SPI2 communication
LL_SPI_SetBaudRatePrescaler(SPI2, LL_SPI_BAUDRATEPRESCALER_DIV4);
LL_SPI_SetTransferDirection(SPI2, LL_SPI_FULL_DUPLEX);
LL_SPI_SetDataWidth(SPI2, LL_SPI_DATAWIDTH_8BIT);
LL_SPI_SetNSSMode(SPI2, LL_SPI_NSS_SOFT);
// Set SPI mode to Master
LL_SPI_SetMode(SPI2, LL_SPI_MODE_MASTER);
// Enable SPI after configuration
LL_SPI_Enable(SPI2);
2025-01-30 05:41 AM
Thanks, yes the SPI is disabled and IOLOCK is off before making these changes.
This issue appears to be a result of the following 4 conditions:
- SSIOP bit being 0 (low level active for SS)
- SSI bit being 0 (SS input low)
- SSM bit being 1 (software control of SS)
- MASTER bit being 1 (SPI configured as master)
This combination causes an immediate MODF (mode fault) which automatically switches the MASTER bit to 0 (SPI configured as slave). It's intended to work as a feature for resolving multi-master conflicts.
I didn't have this issue with the STM32F7 series or see notes about this in the migration document (STM32F7 to STM32H7), but it seems to be a subtle difference in the SPI feature set.
By setting the SSI bit to 1 before attempting to set MASTER=1, I'm able to avoid this problem.
Thanks!