@frank B an @Paul and @mjs513 and @defragster and ...
SPI, (SPI1, SPI2), FlexSPI and SPISettings -
I know that I mentioned this earlier, but thought I would revisit, especially since looking at SPI1/SPI2, plus FlexIO-SPI...
History:
With T.x and earlier with T4... when the user did something like: SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
The compiler would take the SPISettings stuff and reduce all of this down to simply doing a few sets of the SPI Port register (in particular for T4, the CCR and TCR registers0, with constants. This was because since everythng was know at compile time the compiler coudl do all of the calculations and simply fill in with constants.
But then the change went in to allow the underlying clock to be changed and have the code understand that and calculate base don that...
In particular to the change:
Code:
-
uint32_t d, div;
uint32_t clkhz = 528000000u / (((CCM_CBCMR >> 26 ) & 0x07 ) + 1); // LPSPI peripheral clock
const uint32_t clk_sel[4] = {664615384, // PLL3 PFD1
720000000, // PLL3 PFD0
528000000, // PLL2
396000000}; // PLL2 PFD2
uint32_t cbcmr = CCM_CBCMR;
uint32_t clkhz = clk_sel[(cbcmr >> 4) & 0x03] / (((cbcmr >> 26 ) & 0x07 ) + 1); // LPSPI peripheral clock
uint32_t d, div;
The problem is, since now the clode depends on variables like CCM_CBCMR - it can no longer be computed at compile time, so there is a lot more code that happens at each of the places that use SPISettings.
So both grows code and slows it down.
Also I have not yet verified that the clock selected for SPI is valid for SPI1 and SPi2...
There are several things to look at:
Code:
void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
__attribute__((__always_inline__)) {
// TODO: Need to check timings as related to chip selects?
const uint32_t clk_sel[4] = {664615384, // PLL3 PFD1
720000000, // PLL3 PFD0
528000000, // PLL2
396000000}; // PLL2 PFD2
uint32_t cbcmr = CCM_CBCMR;
uint32_t clkhz = clk_sel[(cbcmr >> 4) & 0x03] / (((cbcmr >> 26 ) & 0x07 ) + 1); // LPSPI peripheral clock
uint32_t d, div;
if (clock == 0) clock =1;
d= clkhz/clock;
if (d && clkhz/d > clock) d++;
if (d > 257) d= 257; // max div
if (d > 2) {
div = d-2;
} else {
div =0;
}
ccr = LPSPI_CCR_SCKDIV(div) | LPSPI_CCR_DBT(div/2);
tcr = LPSPI_TCR_FRAMESZ(7); // TCR has polarity and bit order too
// handle LSB setup
if (bitOrder == LSBFIRST) tcr |= LPSPI_TCR_LSBF;
// Handle Data Mode
if (dataMode & 0x08) tcr |= LPSPI_TCR_CPOL;
// Note: On T3.2 when we set CPHA it also updated the timing. It moved the
// PCS to SCK Delay Prescaler into the After SCK Delay Prescaler
if (dataMode & 0x04) tcr |= LPSPI_TCR_CPHA;
}
The question is do all three SPI boejcts share the same Clock Setting? And do you mind if everything has to be recomputed each time?
That is we are computing everything depending on the values of the register CCM_CBCMR
Is this the same for SPI versus SPI1 versus SPI2?
That is for example suppose you crate an SPI object with speed 2000000
something like mysettings = SPISettings(200000, MSBFIRST, SPI_MODE0);
Then if you use this on a beginTransaction for SPi as well as SPi2 and SPi2, do you expect that iw till work properly on all 3?
Likewise do you expect us to be able to pass in the SPISettings into a flexIO version of SPI, which has a different set of registers?
For the fun of it I should experiment and see if we notice any differences in speed with, some cases. As for using the SPISettings with FlexIO. By default it is
sort of not able to be used here as registers defiend and used are different