@@ -939,6 +939,33 @@ static inline int datasize_to_transfer_bitshift(uint32_t DataSize)
939939 }
940940}
941941
942+ static inline int spi_get_word_from_buffer (const void * buffer , int bitshift )
943+ {
944+ if (bitshift == 1 ) {
945+ return * ((uint16_t * )buffer );
946+ #ifdef HAS_32BIT_SPI_TRANSFERS
947+ } else if (bitshift == 2 ) {
948+ return * ((uint32_t * )buffer );
949+ #endif /* HAS_32BIT_SPI_TRANSFERS */
950+ } else {
951+ return * ((uint8_t * )buffer );
952+ }
953+ }
954+
955+ static inline void spi_put_word_to_buffer (void * buffer , int bitshift , int data )
956+ {
957+ if (bitshift == 1 ) {
958+ * ((uint16_t * )buffer ) = data ;
959+ #ifdef HAS_32BIT_SPI_TRANSFERS
960+ } else if (bitshift == 2 ) {
961+ * ((uint32_t * )buffer ) = data ;
962+ #endif /* HAS_32BIT_SPI_TRANSFERS */
963+ } else {
964+ * ((uint8_t * )buffer ) = data ;
965+ }
966+ }
967+
968+
942969/**
943970 * Check if SPI master interface is writable.
944971 *
@@ -1057,6 +1084,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10571084 SPI_HandleTypeDef * handle = & (spiobj -> handle );
10581085 const int bitshift = datasize_to_transfer_bitshift (handle -> Init .DataSize );
10591086 MBED_ASSERT (bitshift >= 0 );
1087+ const int word_size = 0x01 << bitshift ;
10601088
10611089 /* Ensure that spi is disabled */
10621090 LL_SPI_Disable (SPI_INST (obj ));
@@ -1066,17 +1094,17 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10661094 LL_SPI_SetTransferDirection (SPI_INST (obj ), LL_SPI_HALF_DUPLEX_TX );
10671095#if defined(SPI_IP_VERSION_V2 )
10681096 /* Set transaction size */
1069- LL_SPI_SetTransferSize (SPI_INST (obj ), tx_length );
1097+ LL_SPI_SetTransferSize (SPI_INST (obj ), tx_length >> bitshift );
10701098#endif /* SPI_IP_VERSION_V2 */
10711099 LL_SPI_Enable (SPI_INST (obj ));
10721100#if defined(SPI_IP_VERSION_V2 )
10731101 /* Master transfer start */
10741102 LL_SPI_StartMasterTransfer (SPI_INST (obj ));
10751103#endif /* SPI_IP_VERSION_V2 */
10761104
1077- for (int i = 0 ; i < tx_length ; i ++ ) {
1105+ for (int i = 0 ; i < tx_length ; i += word_size ) {
10781106 msp_wait_writable (obj );
1079- msp_write_data (obj , tx_buffer [ i ] , bitshift );
1107+ msp_write_data (obj , spi_get_word_from_buffer ( tx_buffer + i , bitshift ) , bitshift );
10801108 }
10811109
10821110 /* Wait end of transaction */
@@ -1098,14 +1126,14 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
10981126 LL_SPI_SetTransferDirection (SPI_INST (obj ), LL_SPI_HALF_DUPLEX_RX );
10991127#if defined(SPI_IP_VERSION_V2 )
11001128 /* Set transaction size and run SPI */
1101- LL_SPI_SetTransferSize (SPI_INST (obj ), rx_length );
1129+ LL_SPI_SetTransferSize (SPI_INST (obj ), rx_length >> bitshift );
11021130 LL_SPI_Enable (SPI_INST (obj ));
11031131 LL_SPI_StartMasterTransfer (SPI_INST (obj ));
11041132
11051133 /* Receive data */
1106- for (int i = 0 ; i < rx_length ; i ++ ) {
1134+ for (int i = 0 ; i < rx_length ; i += word_size ) {
11071135 msp_wait_readable (obj );
1108- rx_buffer [ i ] = msp_read_data (obj , bitshift );
1136+ spi_put_word_to_buffer ( rx_buffer + i , bitshift , msp_read_data (obj , bitshift ) );
11091137 }
11101138
11111139 /* Stop SPI */
@@ -1134,7 +1162,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
11341162 /* get estimation about one SPI clock cycle */
11351163 uint32_t baudrate_period_ns = 1000000000 / spi_get_baudrate (obj );
11361164
1137- for (int i = 0 ; i < rx_length ; i ++ ) {
1165+ for (int i = 0 ; i < rx_length ; i += word_size ) {
11381166 core_util_critical_section_enter ();
11391167 LL_SPI_Enable (SPI_INST (obj ));
11401168 /* Wait single SPI clock cycle. */
@@ -1143,7 +1171,7 @@ static int spi_master_one_wire_transfer(spi_t *obj, const char *tx_buffer, int t
11431171 core_util_critical_section_exit ();
11441172
11451173 msp_wait_readable (obj );
1146- rx_buffer [ i ] = msp_read_data (obj , bitshift );
1174+ spi_put_word_to_buffer ( rx_buffer + i , bitshift , msp_read_data (obj , bitshift ) );
11471175 }
11481176
11491177#endif /* SPI_IP_VERSION_V2 */
@@ -1198,13 +1226,25 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
11981226{
11991227 struct spi_s * spiobj = SPI_S (obj );
12001228 SPI_HandleTypeDef * handle = & (spiobj -> handle );
1229+ const int bitshift = datasize_to_transfer_bitshift (handle -> Init .DataSize );
1230+ /* check buffer sizes are multiple of spi word size */
1231+ MBED_ASSERT (tx_length >> bitshift << bitshift == tx_length );
1232+ MBED_ASSERT (rx_length >> bitshift << bitshift == rx_length );
12011233 int total = (tx_length > rx_length ) ? tx_length : rx_length ;
1234+
12021235 if (handle -> Init .Direction == SPI_DIRECTION_2LINES ) {
1203- for (int i = 0 ; i < total ; i ++ ) {
1204- char out = (i < tx_length ) ? tx_buffer [i ] : write_fill ;
1205- char in = spi_master_write (obj , out );
1236+ int write_fill_frame = write_fill ;
1237+ /* extend fill symbols for 16/32 bit modes */
1238+ for (int i = 0 ; i < bitshift ; i ++ ) {
1239+ write_fill_frame = (write_fill_frame << 8 ) | write_fill ;
1240+ }
1241+
1242+ const int word_size = 0x01 << bitshift ;
1243+ for (int i = 0 ; i < total ; i += word_size ) {
1244+ int out = (i < tx_length ) ? spi_get_word_from_buffer (tx_buffer + i , bitshift ) : write_fill_frame ;
1245+ int in = spi_master_write (obj , out );
12061246 if (i < rx_length ) {
1207- rx_buffer [ i ] = in ;
1247+ spi_put_word_to_buffer ( rx_buffer + i , bitshift , in ) ;
12081248 }
12091249 }
12101250 } else {
@@ -1349,6 +1389,11 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer
13491389
13501390 // enable the right hal transfer
13511391 int rc = 0 ;
1392+ #if defined(SPI_IP_VERSION_V2 )
1393+ // HAL SPI API assumes that SPI disabled between transfers and
1394+ // doesn't work properly if SPI is enabled.
1395+ LL_SPI_Disable (SPI_INST (obj ));
1396+ #endif
13521397 switch (transfer_type ) {
13531398 case SPI_TRANSFER_TYPE_TXRX :
13541399 rc = HAL_SPI_TransmitReceive_IT (handle , (uint8_t * )tx , (uint8_t * )rx , words );
@@ -1367,6 +1412,12 @@ static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer
13671412 }
13681413
13691414 if (rc ) {
1415+ #if defined(SPI_IP_VERSION_V2 )
1416+ // enable SPI back in case of error
1417+ if (handle -> Init .Direction != SPI_DIRECTION_1LINE ) {
1418+ LL_SPI_Enable (SPI_INST (obj ));
1419+ }
1420+ #endif
13701421 DEBUG_PRINTF ("SPI: RC=%u\n" , rc );
13711422 length = 0 ;
13721423 }
@@ -1466,6 +1517,16 @@ inline uint32_t spi_irq_handler_asynch(spi_t *obj)
14661517 */
14671518 spi_flush_rx (obj );
14681519 }
1520+ #else
1521+ // reset transfer size
1522+ LL_SPI_SetTransferSize (SPI_INST (obj ), 0 );
1523+
1524+ // HAL_SPI_TransmitReceive_IT/HAL_SPI_Transmit_IT/HAL_SPI_Receive_IT
1525+ // function disable SPI after transfer. So we need enabled it back,
1526+ // otherwise spi_master_block_write/spi_master_write won't work in 4-wire mode.
1527+ if (handle -> Init .Direction != SPI_DIRECTION_1LINE ) {
1528+ LL_SPI_Enable (SPI_INST (obj ));
1529+ }
14691530#endif /* SPI_IP_VERSION_V2 */
14701531 }
14711532
0 commit comments