From d56f942ae7616e08b8cae7ce411ef75279b60b5f Mon Sep 17 00:00:00 2001 From: Peter B Date: Mon, 26 Oct 2020 16:03:04 +0100 Subject: [PATCH 1/2] Update spi_api.c Modified line 145: previously the fill character has been hard coded to 0x00. However in Mbed OS core SPI_FILL_CHAR is defined in the core to be 0xFF by default (one can change that through mbed_app.json for example). This mod allows us to use the same fill character that is defined for Mbed OS. Also modified spi_master_block_write(): previously it called am_hal_iom_blocking_transfer on line 182, but that prevented succesful SD card writing operations. Now i changed that part to am_hal_iom_spi_blocking_fullduplex and SD functionality seems to be working. --- .../TARGET_Apollo3/device/spi_api.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c index fb44cbd08e..23ff379217 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c @@ -142,7 +142,7 @@ void spi_frequency(spi_t *obj, int hz) int spi_master_write(spi_t *obj, int value) { uint32_t rxval = 0; - spi_master_block_write(obj, (const char *)&value, 1, (char *)&rxval, 1, 0x00); + spi_master_block_write(obj, (const char *)&value, 1, (char *)&rxval, 1, SPI_FILL_CHAR); return rxval; } @@ -167,7 +167,7 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, cha } // handle difference between buffers - if (tx_length != rx_length) { + else if (tx_length != rx_length) { bool Rw = (rx_length >= tx_length); // set up common config @@ -177,9 +177,13 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, cha xfer.pui32TxBuffer = (Rw) ? NULL : (uint32_t *)(tx_buffer + chars_handled); uint32_t status = AM_HAL_STATUS_SUCCESS; - if (!Rw || (write_fill == 0x00)) { + if (!Rw || (write_fill == SPI_FILL_CHAR)) { // when transmitting (w) or reading with a zero fill just use a simplex transfer - status = am_hal_iom_blocking_transfer(obj->spi.iom_obj.iom.handle, &xfer); + uint8_t fill[xfer.ui32NumBytes]; + memset(fill, write_fill, xfer.ui32NumBytes); + xfer.eDirection = AM_HAL_IOM_FULLDUPLEX; + xfer.pui32RxBuffer = (uint32_t *)&fill; + uint32_t status = am_hal_iom_spi_blocking_fullduplex(obj->spi.iom_obj.iom.handle, &xfer); if (AM_HAL_STATUS_SUCCESS != status) { return chars_handled; } From 02a12a8722c8f3624eecb87dbd7edb5e639119ea Mon Sep 17 00:00:00 2001 From: Peter B Date: Wed, 28 Oct 2020 23:28:34 +0100 Subject: [PATCH 2/2] Update spi_api.c Modified the spi_master_block_write() function yet again. SD related examples still read/erase/write the SD cards as expected and with these alterations the power consumption does not remain high after the SPI transaction has been finished. However i still only tested the SD functionality. Please test other SPI scenarios and different sensors as well to find out if this PR introduces unexpected bugs or not. Changes: - deleted the whole if (xfer.ui32NumBytes) condition as i did not find it logical (by that i mean xfer.ui32NumBytes was also true within the following else if (tx_length != rx_length){} block, so basically when the 2 buffers had different lengths an extra transfer has been done for nothing) - removed the bool Rw = (rx_length >= tx_length) as the comparison >= has no sense anymore after if (tx_length == rx_length) on line 159. --- .../TARGET_Apollo3/device/spi_api.c | 71 ++++++++----------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c index 23ff379217..ebfb737a55 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/spi_api.c @@ -151,57 +151,42 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, cha MBED_ASSERT(obj); int chars_handled = 0; + uint32_t status = AM_HAL_STATUS_SUCCESS; - // perform a duplex xfer for the smaller of the two buffers + // always perform a duplex xfer xfer.eDirection = AM_HAL_IOM_FULLDUPLEX; - xfer.ui32NumBytes = (tx_length > rx_length) ? rx_length : tx_length; - xfer.pui32RxBuffer = (uint32_t *)rx_buffer; - xfer.pui32TxBuffer = (uint32_t *)tx_buffer; - if (xfer.ui32NumBytes) { - uint32_t status = am_hal_iom_spi_blocking_fullduplex(obj->spi.iom_obj.iom.handle, &xfer); - if (AM_HAL_STATUS_SUCCESS != status) { - return 0; - } - chars_handled += xfer.ui32NumBytes; + if (tx_length == rx_length) { + xfer.pui32RxBuffer = (uint32_t *)rx_buffer; + xfer.pui32TxBuffer = (uint32_t *)tx_buffer; + xfer.ui32NumBytes = tx_length; + status = am_hal_iom_spi_blocking_fullduplex(obj->spi.iom_obj.iom.handle, &xfer); } // handle difference between buffers - else if (tx_length != rx_length) { - bool Rw = (rx_length >= tx_length); - - // set up common config - xfer.eDirection = (Rw) ? AM_HAL_IOM_RX : AM_HAL_IOM_TX; - xfer.ui32NumBytes = (Rw) ? (rx_length - tx_length) : (tx_length - rx_length); - xfer.pui32RxBuffer = (Rw) ? (uint32_t *)(rx_buffer + chars_handled) : NULL; - xfer.pui32TxBuffer = (Rw) ? NULL : (uint32_t *)(tx_buffer + chars_handled); - - uint32_t status = AM_HAL_STATUS_SUCCESS; - if (!Rw || (write_fill == SPI_FILL_CHAR)) { - // when transmitting (w) or reading with a zero fill just use a simplex transfer - uint8_t fill[xfer.ui32NumBytes]; - memset(fill, write_fill, xfer.ui32NumBytes); - xfer.eDirection = AM_HAL_IOM_FULLDUPLEX; - xfer.pui32RxBuffer = (uint32_t *)&fill; - uint32_t status = am_hal_iom_spi_blocking_fullduplex(obj->spi.iom_obj.iom.handle, &xfer); - if (AM_HAL_STATUS_SUCCESS != status) { - return chars_handled; - } - chars_handled += xfer.ui32NumBytes; - } else { - // when reading with a nonzero fill use a duplex transfer - uint8_t fill[xfer.ui32NumBytes]; - memset(fill, write_fill, xfer.ui32NumBytes); - xfer.eDirection = AM_HAL_IOM_FULLDUPLEX; - xfer.pui32TxBuffer = (uint32_t *)&fill; - uint32_t status = am_hal_iom_spi_blocking_fullduplex(obj->spi.iom_obj.iom.handle, &xfer); - if (AM_HAL_STATUS_SUCCESS != status) { - return chars_handled; - } - chars_handled += xfer.ui32NumBytes; - } + else if (tx_length < rx_length) { + xfer.pui32RxBuffer = (uint32_t *)rx_buffer; + xfer.ui32NumBytes = rx_length - tx_length; + uint8_t fill[xfer.ui32NumBytes]; + memset(fill, write_fill, xfer.ui32NumBytes); + xfer.pui32TxBuffer = (uint32_t *)&fill; + status = am_hal_iom_spi_blocking_fullduplex(obj->spi.iom_obj.iom.handle, &xfer); } + else { + xfer.pui32TxBuffer = (uint32_t *)tx_buffer; + xfer.ui32NumBytes = tx_length - rx_length; + uint8_t fill[xfer.ui32NumBytes]; + memset(fill, write_fill, xfer.ui32NumBytes); + xfer.pui32RxBuffer = (uint32_t *)&fill; + status = am_hal_iom_spi_blocking_fullduplex(obj->spi.iom_obj.iom.handle, &xfer); + } + + if (AM_HAL_STATUS_SUCCESS != status) { + return 0; + } + + chars_handled += xfer.ui32NumBytes; return chars_handled; }