Changes to CPU_SPI_decl.h …
struct SPI_CONFIGURATION
{
GPIO_PIN DeviceCS;
BOOL CS_Active; // False = LOW active, TRUE = HIGH active
BOOL MSK_IDLE; // False = LOW during idle, TRUE = HIGH during idle
BOOL MSK_SampleEdge; // False = sample falling edge, TRUE = samples on rising
BOOL MD_16bits;
UINT32 Clock_RateKHz;
UINT32 CS_Setup_uSecs;
UINT32 CS_Hold_uSecs;
UINT32 SPI_mod;
GPIO_FLAG BusyPin;
//----------------------------------------------------------------------------
// I added this...
//----------------------------------------------------------------------------
UINT32 BusyPin_BytesPerFrame; // Sensor arrays, etc. require large amounts of data to be read sequentially
// from ADCs, etc. that toggle the busy pin between frames. Manage code can't
// execute fast enough to do this. For example, reading 256 pixels from an
// analog array. Something like an 18bit ADC might be used to read data.
// The ADC would commonly need to send 256 pixels, 18bits each, at 20Mhz.
//----------------------------------------------------------------------------
};
struct SPI_XACTION_16
{
UINT16* Write16;
INT32 WriteCount;
UINT16* Read16;
INT32 ReadCount;
INT32 ReadStartOffset;
UINT32 SPI_mod;
GPIO_FLAG BusyPin;
//----------------------------------------------------------------------------
// I added this...
//----------------------------------------------------------------------------
UINT32 BusyPin_BytesPerFrame;
//----------------------------------------------------------------------------
};
struct SPI_XACTION_8
{
UINT8* Write8;
INT32 WriteCount;
UINT8* Read8;
INT32 ReadCount;
INT32 ReadStartOffset;
UINT32 SPI_mod;
GPIO_FLAG BusyPin;
//----------------------------------------------------------------------------
// I added this...
//----------------------------------------------------------------------------
UINT32 BusyPin_BytesPerFrame;
//----------------------------------------------------------------------------
};
Changes to STM32F4_SPI_functions.cpp …
BOOL CPU_SPI_nWrite16_nRead16( const SPI_CONFIGURATION& Configuration, UINT16* Write16, INT32 WriteCount, UINT16* Read16, INT32 ReadCount, INT32 ReadStartOffset )
{
NATIVE_PROFILE_HAL_PROCESSOR_SPI();
if(!CPU_SPI_Xaction_Start( Configuration )) return FALSE;
SPI_XACTION_16 Transaction;
Transaction.Read16 = Read16;
Transaction.ReadCount = ReadCount;
Transaction.ReadStartOffset = ReadStartOffset;
Transaction.Write16 = Write16;
Transaction.WriteCount = WriteCount;
Transaction.SPI_mod = Configuration.SPI_mod;
//----------------------------------------------------------------------------
// This stuff wasn't being passed before...
//----------------------------------------------------------------------------
Transaction.BusyPin = Configuration.BusyPin;
Transaction.BusyPin_BytesPerFrame = Configuration.BusyPin_BytesPerFrame;
//----------------------------------------------------------------------------
if(!CPU_SPI_Xaction_nWrite16_nRead16( Transaction )) return FALSE;
return CPU_SPI_Xaction_Stop( Configuration );
}
BOOL CPU_SPI_nWrite8_nRead8( const SPI_CONFIGURATION& Configuration, UINT8* Write8, INT32 WriteCount, UINT8* Read8, INT32 ReadCount, INT32 ReadStartOffset )
{
NATIVE_PROFILE_HAL_PROCESSOR_SPI();
if(!CPU_SPI_Xaction_Start( Configuration )) return FALSE;
SPI_XACTION_8 Transaction;
Transaction.Read8 = Read8;
Transaction.ReadCount = ReadCount;
Transaction.ReadStartOffset = ReadStartOffset;
Transaction.Write8 = Write8;
Transaction.WriteCount = WriteCount;
Transaction.SPI_mod = Configuration.SPI_mod;
//----------------------------------------------------------------------------
// This stuff wasn't being passed before...
//----------------------------------------------------------------------------
Transaction.BusyPin = Configuration.BusyPin;
Transaction.BusyPin_BytesPerFrame = Configuration.BusyPin_BytesPerFrame;
//----------------------------------------------------------------------------
if(!CPU_SPI_Xaction_nWrite8_nRead8( Transaction )) return FALSE;
return CPU_SPI_Xaction_Stop( Configuration );
}
And…
BOOL CPU_SPI_Xaction_nWrite16_nRead16( SPI_XACTION_16& Transaction )
{
NATIVE_PROFILE_HAL_PROCESSOR_SPI();
ptr_SPI_TypeDef spi = g_STM32_Spi_Port[Transaction.SPI_mod];
UINT16* outBuf = Transaction.Write16;
UINT16* inBuf = Transaction.Read16;
INT32 outLen = Transaction.WriteCount;
INT32 num, ii, i = 0;
if (Transaction.ReadCount) { // write & read
num = Transaction.ReadCount + Transaction.ReadStartOffset;
ii = -Transaction.ReadStartOffset;
} else { // write only
num = outLen;
ii = 0x80000000; // disable write to inBuf
}
UINT16 out = outBuf[0];
UINT16 in;
spi->DR = out; // write first word
while (++i < num) {
//----------------------------------------------------------------------------
//Wait until the busy pin toggles
//----------------------------------------------------------------------------
if (Transaction.BusyPin.Pin != GPIO_PIN_NONE)
{
while (CPU_GPIO_GetPinState( Transaction.BusyPin.Pin ) != Transaction.BusyPin.ActiveState);
}
//----------------------------------------------------------------------------
if (i < outLen) out = outBuf[i]; // get new output data
while (!(spi->SR & SPI_SR_RXNE)); // wait for Rx buffer full
in = spi->DR; // read input
spi->DR = out; // start output
if (ii >= 0) inBuf[ii] = in; // save input data
ii++;
//----------------------------------------------------------------------------
//When all the bytes in a frame at read, wait until the busy pin toggles back.
//----------------------------------------------------------------------------
if (Transaction.BusyPin.Pin != GPIO_PIN_NONE)
{
if (Transaction.BusyPin_BytesPerFrame > 1)
{
if ((i + 1) % (Transaction.BusyPin_BytesPerFrame / 2) == 0)
{
while (CPU_GPIO_GetPinState( Transaction.BusyPin.Pin ) == Transaction.BusyPin.ActiveState);
}
}
}
//----------------------------------------------------------------------------
}
while (!(spi->SR & SPI_SR_RXNE)); // wait for Rx buffer full
in = spi->DR; // read last input
if (ii >= 0) inBuf[ii] = in; // save last input
return TRUE;
}
BOOL CPU_SPI_Xaction_nWrite8_nRead8( SPI_XACTION_8& Transaction )
{
NATIVE_PROFILE_HAL_PROCESSOR_SPI();
ptr_SPI_TypeDef spi = g_STM32_Spi_Port[Transaction.SPI_mod];
UINT8* outBuf = Transaction.Write8;
UINT8* inBuf = Transaction.Read8;
INT32 outLen = Transaction.WriteCount;
INT32 num, ii, i = 0;
if (Transaction.ReadCount) { // write & read
num = Transaction.ReadCount + Transaction.ReadStartOffset;
ii = -Transaction.ReadStartOffset;
} else { // write only
num = outLen;
ii = 0x80000000; // disable write to inBuf
}
UINT8 out = outBuf[0];
UINT16 in;
spi->DR = out; // write first word
while (++i < num) {
//----------------------------------------------------------------------------
//Wait until the busy pin toggles
//----------------------------------------------------------------------------
if (Transaction.BusyPin.Pin != GPIO_PIN_NONE)
{
while (CPU_GPIO_GetPinState( Transaction.BusyPin.Pin ) != Transaction.BusyPin.ActiveState);
}
//----------------------------------------------------------------------------
if (i < outLen) out = outBuf[i]; // get new output data
while (!(spi->SR & SPI_SR_RXNE)); // wait for Rx buffer full
in = spi->DR; // read input
spi->DR = out; // start output
if (ii >= 0) inBuf[ii] = (UINT8)in; // save input data
//----------------------------------------------------------------------------
//When all the bytes in a frame at read, wait until the busy pin toggles back.
//----------------------------------------------------------------------------
if (Transaction.BusyPin.Pin != GPIO_PIN_NONE)
{
if (Transaction.BusyPin_BytesPerFrame != 0)
{
if ((i + 1) % Transaction.BusyPin_BytesPerFrame == 0)
{
while (CPU_GPIO_GetPinState( Transaction.BusyPin.Pin ) == Transaction.BusyPin.ActiveState);
}
}
}
//----------------------------------------------------------------------------
ii++;
}
while (!(spi->SR & SPI_SR_RXNE)); // wait for Rx buffer full
in = spi->DR; // read last input
if (ii >= 0) inBuf[ii] = (UINT8)in; // save last input
return TRUE;
}
Changes to SPI.cs …
public class Configuration
{
public readonly Cpu.Pin ChipSelect_Port;
public readonly bool ChipSelect_ActiveState;
public readonly uint ChipSelect_SetupTime;
public readonly uint ChipSelect_HoldTime;
public readonly bool Clock_IdleState;
public readonly bool Clock_Edge;
public readonly uint Clock_RateKHz;
public readonly SPI_module SPI_mod;
public readonly Cpu.Pin BusyPin;
public readonly bool BusyPin_ActiveState;
//----------------------------------------------------------------------------
// I added this...
//----------------------------------------------------------------------------
public readonly uint BusyPin_BytesPerFrame;
//----------------------------------------------------------------------------
public Configuration(
Cpu.Pin ChipSelect_Port,
bool ChipSelect_ActiveState,
uint ChipSelect_SetupTime,
uint ChipSelect_HoldTime,
bool Clock_IdleState,
bool Clock_Edge,
uint Clock_RateKHz,
SPI_module SPI_mod
) : this( ChipSelect_Port,
ChipSelect_ActiveState,
ChipSelect_SetupTime,
ChipSelect_HoldTime,
Clock_IdleState,
Clock_Edge,
Clock_RateKHz,
SPI_mod,
Cpu.Pin.GPIO_NONE,
false)
{
}
public Configuration(
Cpu.Pin ChipSelect_Port,
bool ChipSelect_ActiveState,
uint ChipSelect_SetupTime,
uint ChipSelect_HoldTime,
bool Clock_IdleState,
bool Clock_Edge,
uint Clock_RateKHz,
SPI_module SPI_mod,
Cpu.Pin BusyPin,
bool BusyPin_ActiveState,
//----------------------------------------------------------------------------
// I added this... (and the comma above)
//----------------------------------------------------------------------------
uint BusyPin_BytesPerFrame
//----------------------------------------------------------------------------
)
{
this.ChipSelect_Port = ChipSelect_Port;
this.ChipSelect_ActiveState = ChipSelect_ActiveState;
this.ChipSelect_SetupTime = ChipSelect_SetupTime;
this.ChipSelect_HoldTime = ChipSelect_HoldTime;
this.Clock_IdleState = Clock_IdleState;
this.Clock_Edge = Clock_Edge;
this.Clock_RateKHz = Clock_RateKHz;
this.SPI_mod = SPI_mod;
this.BusyPin = BusyPin;
this.BusyPin_ActiveState = BusyPin_ActiveState;
//----------------------------------------------------------------------------
// I added this...
//----------------------------------------------------------------------------
this.BusyPin_BytesPerFrame = BusyPin_BytesPerFrame;
//----------------------------------------------------------------------------
}
}
EDIT: I wasn’t checking to see if the BusyPin was being used. This version I’ve tested and verified.