Browse Source

Merge pull request #48 from KurtE/T4_SPISettings_calc

T4 SPISettings - just hold values passed in
main
Paul Stoffregen 5 years ago
parent
commit
ab5b6b29a5
No account linked to committer's email address
1 changed files with 52 additions and 47 deletions
  1. +52
    -47
      SPI.h

+ 52
- 47
SPI.h View File



//#include "debug/printf.h" //#include "debug/printf.h"


// TODO......
//#undef SPI_HAS_TRANSFER_ASYNC


class SPISettings { class SPISettings {
public: public:
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, dataMode);
} else {
init_MightInline(clock, bitOrder, dataMode);
}
SPISettings(uint32_t clockIn, uint8_t bitOrderIn, uint8_t dataModeIn) : _clock(clockIn) {
init_AlwaysInline(bitOrderIn, dataModeIn);
} }
SPISettings() {
init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);

SPISettings() : _clock(4000000) {
init_AlwaysInline(MSBFIRST, SPI_MODE0);
} }
private: private:
void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
init_AlwaysInline(clock, bitOrder, dataMode);
}
void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
void init_AlwaysInline(uint8_t bitOrder, uint8_t dataMode)
__attribute__((__always_inline__)) { __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
tcr = LPSPI_TCR_FRAMESZ(7); // TCR has polarity and bit order too


// handle LSB setup
if (bitOrder == LSBFIRST) tcr |= LPSPI_TCR_LSBF;
// handle LSB setup
if (bitOrder == LSBFIRST) tcr |= LPSPI_TCR_LSBF;


// Handle Data Mode
if (dataMode & 0x08) tcr |= LPSPI_TCR_CPOL;
// 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;
// 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;
} }
uint32_t ccr; // clock config, pg 2660 (RT1050 ref, rev 2)

inline uint32_t clock() {return _clock;}

uint32_t _clock;
uint32_t tcr; // transmit command, pg 2664 (RT1050 ref, rev 2) uint32_t tcr; // transmit command, pg 2664 (RT1050 ref, rev 2)
friend class SPIClass; friend class SPIClass;
}; };
#endif #endif


//printf("trans\n"); //printf("trans\n");
if (settings.clock() != _clock) {
static const uint32_t clk_sel[4] = {664615384, // PLL3 PFD1
720000000, // PLL3 PFD0
528000000, // PLL2
396000000}; // PLL2 PFD2

// First save away the new settings..
_clock = settings.clock();

uint32_t cbcmr = CCM_CBCMR;
uint32_t clkhz = clk_sel[(cbcmr >> 4) & 0x03] / (((cbcmr >> 26 ) & 0x07 ) + 1); // LPSPI peripheral clock
uint32_t d, div;
d = _clock ? clkhz/_clock : clkhz;

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);

}
//Serial.printf("SPI.beginTransaction CCR:%x TCR:%x\n", _ccr, settings.tcr);
port().CR = 0; port().CR = 0;
port().CFGR1 = LPSPI_CFGR1_MASTER | LPSPI_CFGR1_SAMPLE; port().CFGR1 = LPSPI_CFGR1_MASTER | LPSPI_CFGR1_SAMPLE;
port().CCR = settings.ccr;
port().CCR = _ccr;
port().TCR = settings.tcr; port().TCR = settings.tcr;
//port().CCR = LPSPI_CCR_SCKDIV(4);
//port().TCR = LPSPI_TCR_FRAMESZ(7);
port().CR = LPSPI_CR_MEN; port().CR = LPSPI_CR_MEN;

} }


// Write to the SPI bus (MOSI pin) and also receive (MISO pin) // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
if (interruptMasksUsed & 0x08) NVIC_ISER3 = interruptSave[3]; if (interruptMasksUsed & 0x08) NVIC_ISER3 = interruptSave[3];
if (interruptMasksUsed & 0x10) NVIC_ISER4 = interruptSave[4]; if (interruptMasksUsed & 0x10) NVIC_ISER4 = interruptSave[4];
} }
//Serial.printf("SPI.endTransaction CCR:%x TCR:%x\n", port().CCR, port().TCR);
} }


// Disable the SPI bus // Disable the SPI bus
const SPI_Hardware_t & hardware() { return *(const SPI_Hardware_t *)hardware_addr; } const SPI_Hardware_t & hardware() { return *(const SPI_Hardware_t *)hardware_addr; }
uintptr_t port_addr; uintptr_t port_addr;
uintptr_t hardware_addr; uintptr_t hardware_addr;

uint32_t _clock = 0;
uint32_t _ccr = 0;

//KINETISK_SPI_t & port() { return *(KINETISK_SPI_t *)port_addr; } //KINETISK_SPI_t & port() { return *(KINETISK_SPI_t *)port_addr; }
// IMXRT_LPSPI_t * const port; // IMXRT_LPSPI_t * const port;
// const SPI_Hardware_t * const hardware; // const SPI_Hardware_t * const hardware;

void updateCTAR(uint32_t ctar); void updateCTAR(uint32_t ctar);
uint8_t miso_pin_index = 0; uint8_t miso_pin_index = 0;
uint8_t mosi_pin_index = 0; uint8_t mosi_pin_index = 0;

Loading…
Cancel
Save