summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/hatch_fp/gpio.inc9
-rw-r--r--chip/stm32/spi_master.c51
2 files changed, 57 insertions, 3 deletions
diff --git a/board/hatch_fp/gpio.inc b/board/hatch_fp/gpio.inc
index 807a76ae47..7a9dfd152f 100644
--- a/board/hatch_fp/gpio.inc
+++ b/board/hatch_fp/gpio.inc
@@ -27,5 +27,10 @@ UNIMPLEMENTED(ENTERING_RW)
ALTERNATE(PIN_MASK(A, 0x0600), GPIO_ALT_USART, MODULE_UART, GPIO_PULL_UP)
/* SPI1 slave from the AP: PA4/5/6/7 */
ALTERNATE(PIN_MASK(A, 0x00f0), GPIO_ALT_SPI, MODULE_SPI, 0)
-/* SPI2 master to sensor: PB12/13/14/15 */
-ALTERNATE(PIN_MASK(B, 0xf000), GPIO_ALT_SPI, MODULE_SPI_MASTER, 0)
+/*
+ * SPI2 master to sensor: PB13/14/15
+ * Note that we're not configuring NSS (PB12) here because we have already
+ * configured it as a GPIO above and the SPI_MASTER module expects to use it
+ * in software NSS management mode, not hardware management mode.
+ */
+ALTERNATE(PIN_MASK(B, 0xE000), GPIO_ALT_SPI, MODULE_SPI_MASTER, 0)
diff --git a/chip/stm32/spi_master.c b/chip/stm32/spi_master.c
index 76677423f2..446013a9d9 100644
--- a/chip/stm32/spi_master.c
+++ b/chip/stm32/spi_master.c
@@ -161,6 +161,48 @@ static int spi_master_initialize(int port)
if ((spi_devices[i].port == port) &&
(div < spi_devices[i].div))
div = spi_devices[i].div;
+
+ /*
+ * STM32F412
+ * Section 26.3.5 Slave select (NSS) pin management and Figure 276
+ * https://www.st.com/resource/en/reference_manual/dm00180369.pdf#page=817
+ *
+ * The documentation in this section is a bit confusing, so here's a
+ * summary based on discussion with ST:
+ *
+ * Software NSS management (SSM = 1):
+ * - In master mode, the NSS output is deactivated. You need to use a
+ * GPIO in output mode for slave select. This is generally used for
+ * multi-slave operation, but you can also use it for single slave
+ * operation. In this case, you should make sure to configure a GPIO
+ * for NSS, but *not* activate the SPI alternate function on that
+ * same pin since that will enable hardware NSS management (see
+ * below).
+ * - In slave mode, the NSS input level is equal to the SSI bit value.
+ *
+ * Hardware NSS management (SSM = 0):
+ * - In slave mode, when NSS pin is detected low the slave (MCU) is
+ * selected.
+ * - In master mode, there are two configurations, depending on the
+ * SSOE bit in register SPIx_CR1.
+ * - NSS output enable (SSM=0, SSOE=1):
+ * The MCU (master) drives NSS low as soon as SPI is enabled
+ * (SPE=1) and releases it when SPI is disabled (SPE=0).
+ *
+ * - NSS output disable (SSM=0, SSOE=0):
+ * Allows multimaster capability. The MCU (master) drives NSS
+ * low. If another master tries to takes control of the bus and
+ * NSS is pulled low, a mode fault is generated and the MCU
+ * changes to slave mode.
+ *
+ * - NSS output disable (SSM=0, SSOE=0): if the MCU is acting as
+ * master on the bus, this config allows multimaster capability. If
+ * the NSS pin is pulled low in this mode, the SPI enters master
+ * mode fault state and the device is automatically reconfigured in
+ * slave mode. In slave mode, the NSS pin works as a standard "chip
+ * select" input and the slave is selected while NSS lin is at low
+ * level.
+ */
spi->cr1 = STM32_SPI_CR1_MSTR | STM32_SPI_CR1_SSM | STM32_SPI_CR1_SSI |
(div << 3);
@@ -170,7 +212,14 @@ static int spi_master_initialize(int port)
#endif
/*
* Configure 8-bit datasize, set FRXTH, enable DMA,
- * and enable NSS output
+ * and set data size (applies to STM32F0 only).
+ *
+ * STM32F412:
+ * https://www.st.com/resource/en/reference_manual/dm00180369.pdf#page=852
+ *
+ *
+ * STM32F0:
+ * https://www.st.com/resource/en/reference_manual/dm00031936.pdf#page=803
*/
spi->cr2 = STM32_SPI_CR2_TXDMAEN | STM32_SPI_CR2_RXDMAEN |
STM32_SPI_CR2_FRXTH | STM32_SPI_CR2_DATASIZE(8);