Hello guys
We have a problem with the SPI bus driver on the nRF9160 MCU.
In our project, we use SPI1 and SPI3 instances.
When I send a package in some of these SPI busses I use the following code:
static bool SpiNrf_sOperation(const SpiIdx_t kIdx, uint8_t* const pTx,
const uint16_t kTxSize, uint8_t* const pRx, const uint16_t kRxSize,
const bool kNeedAwait)
{
SPI_XFER oper;
// Prepare an operation structure.
if (pTx && pRx) { // Transmiting and receiving operation.
SPI_XFER txRx = NRFX_SPIM_XFER_TRX(pTx, kTxSize, pRx, kRxSize);
memcpy(&oper, &txRx, sizeof(SPI_XFER));
} else if (pTx) { // Transmiting-only operation.
SPI_XFER tx = NRFX_SPIM_XFER_TX(pTx, kTxSize);
memcpy(&oper, &tx, sizeof(SPI_XFER));
} else { // Receiving-only operation.
SPI_XFER rx = NRFX_SPIM_XFER_RX(pRx, kRxSize);
memcpy(&oper, &rx, sizeof(SPI_XFER));
}
// Select between awaiting or non-awaiting operations.
if (!kNeedAwait) { // Just sent and do not wait until the data is received:
// data receiving will be driven from SPI event
// callback.
return (nrfx_spim_xfer(&sSpi[kIdx].periph, &oper, 0) == NRFX_SUCCESS);
} else { // Run the SPI operation and await until it is finished.
sSpi[kIdx].isBusy = true;
int status = nrfx_spim_xfer(&sSpi[kIdx].periph, &oper, 0);
if (status == NRFX_SUCCESS) {
if (SpiNrf_sWaitUntilReady(kIdx)) {
return true;
}
}
sSpi[kIdx].isBusy = false;
LOG_E("failed to xfer data - %d\n", status);
return false;
}
}
Where the kNeedAwait flag is always true.
Inside of the SpiNrf_sWaitUntilReady function I wait for sSpi[kIdx].isBusy == false condition:
static bool SpiNrf_sWaitUntilReady(const SpiIdx_t kIdx)
{
while (sSpi[kIdx].isBusy == true) {
}
return true;
}
It reaches by catching callbacks from the SPI driver. For example:
static void Spi1_sDfltClbk(nrfx_spim_evt_t const* pEvent, void* pContext)
{
if (pEvent->type == NRFX_SPIM_EVENT_DONE) {
sSpi[kSpi1].isBusy = false;
}
}
The isBusy flag is declared with the volatile specifier:
typedef struct {
bool isInit; // Initialization flag
bool isActive; // Activity flag
volatile bool isBusy; // Business flag.
SPI_INS periph; // Instance object
SPI_CFG config; // Instance configuration object
pSpiClbk pClbk; // Pointer to an external interrupt processing function
} SpiNrf_t;
The problem comes when I try to send two transactions and each one is issued from separate threads.
For example one transaction (from thread #1) to the WIFI chip on the SPI1 bus and another transaction (from thread #2) to the external flash memory on the SPI3 bus. I have looked at the nrfx driver implementation and it looks very good.
As a solution to this problem, I used a mutex to access the nrfx driver. In this case, everything works fine. Could this be a hardware issue for this type of MCU, or should I be using the nrfx driver in some other way?
If you need to clarify the details on this issue, so I am ready to provide them.
Thanks in advance for your reply.