Browse Source

Merge pull request #38 from KurtE/T4_Add_more_support

T4 - put inital calls for check pins and set pins...
main
Paul Stoffregen 5 years ago
parent
commit
8037deb8bb
No account linked to committer's email address
2 changed files with 184 additions and 54 deletions
  1. +138
    -27
      SPI.cpp
  2. +46
    -27
      SPI.h

+ 138
- 27
SPI.cpp View File

@@ -1266,7 +1266,7 @@ bool SPIClass::transfer(const void *buf, void *retbuf, size_t count, EventRespon

#elif defined(__arm__) && defined(TEENSYDUINO) && (defined(__IMXRT1052__) || defined(__IMXRT1062__))

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

void SPIClass::begin()
{
@@ -1274,60 +1274,171 @@ void SPIClass::begin()
// CBCMR[LPSPI_CLK_SEL] - PLL2 = 528 MHz
// CBCMR[LPSPI_PODF] - div4 = 132 MHz

CCM_CCGR1 &= ~CCM_CCGR1_LPSPI4(CCM_CCGR_ON);

hardware->clock_gate_register &= ~hardware->clock_gate_mask;

CCM_CBCMR = (CCM_CBCMR & ~(CCM_CBCMR_LPSPI_PODF_MASK | CCM_CBCMR_LPSPI_CLK_SEL_MASK)) |
CCM_CBCMR_LPSPI_PODF(6) | CCM_CBCMR_LPSPI_CLK_SEL(2); // pg 714

uint32_t fastio = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3);
//uint32_t fastio = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3);
IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_01 = fastio;
IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_02 = fastio;
IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = fastio;
Serial.printf("SPI MISO: %d MOSI: %d, SCK: %d\n", hardware->miso_pin[miso_pin_index], hardware->mosi_pin[mosi_pin_index], hardware->sck_pin[sck_pin_index]);
*(portControlRegister(hardware->miso_pin[miso_pin_index])) = fastio;
*(portControlRegister(hardware->mosi_pin[mosi_pin_index])) = fastio;
*(portControlRegister(hardware->sck_pin[sck_pin_index])) = fastio;

//printf("CBCMR = %08lX\n", CCM_CBCMR);
CCM_CCGR1 |= CCM_CCGR1_LPSPI4(CCM_CCGR_ON);
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 = 3 | 0x10; // SDI
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 = 3 | 0x10; // SDO
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 3 | 0x10; // SCK
hardware->clock_gate_register |= hardware->clock_gate_mask;
*(portConfigRegister(hardware->miso_pin[miso_pin_index])) = hardware->miso_mux[miso_pin_index];
*(portConfigRegister(hardware->mosi_pin [mosi_pin_index])) = hardware->mosi_mux[mosi_pin_index];
*(portConfigRegister(hardware->sck_pin [sck_pin_index])) = hardware->sck_mux[sck_pin_index];

//digitalWriteFast(10, HIGH);
//pinMode(10, OUTPUT);
//digitalWriteFast(10, HIGH);
LPSPI4_CR = LPSPI_CR_RST;
port->CR = LPSPI_CR_RST;

// Lets initialize the Transmit FIFO watermark to FIFO size - 1...
// BUGBUG:: I assume queue of 16 for now...
port->FCR = LPSPI_FCR_TXWATER(15);
}

uint8_t SPIClass::pinIsChipSelect(uint8_t pin)
{
return 0;
}

const SPIClass::SPI_Hardware_t SPIClass::lpspi4_hardware = {
CCM_CCGR1,
CCM_CCGR1_LPSPI4(CCM_CCGR_ON)
};
SPIClass SPI(0, (uintptr_t)&SPIClass::lpspi4_hardware);
bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
{
uint8_t pin1_mask, pin2_mask;
if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
//Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
if ((pin1_mask & pin2_mask) != 0) return false;
return true;
}

bool SPIClass::pinIsMOSI(uint8_t pin)
{
for (unsigned int i = 0; i < sizeof(hardware->mosi_pin); i++) {
if (pin == hardware->mosi_pin[i]) return true;
}
return false;
}

bool SPIClass::pinIsMISO(uint8_t pin)
{
for (unsigned int i = 0; i < sizeof(hardware->miso_pin); i++) {
if (pin == hardware->miso_pin[i]) return true;
}
return false;
}

void SPIClass::transfer(const void * buf, void * retbuf, size_t count)
bool SPIClass::pinIsSCK(uint8_t pin)
{
const uint8_t *tx = (const uint8_t *)buf;
uint8_t *rx = (uint8_t *)retbuf;
for (unsigned int i = 0; i < sizeof(hardware->sck_pin); i++) {
if (pin == hardware->sck_pin[i]) return true;
}
return false;
}

// inefficient, but simplest possible way to get started
while (count > 0) {
uint8_t b = 0;
if (tx) b = *tx++;
if (rx) {
*rx++ = transfer(b);
} else {
transfer(b);
// setCS() is not intended for use from normal Arduino programs/sketches.
uint8_t SPIClass::setCS(uint8_t pin)
{
/*
for (unsigned int i = 0; i < sizeof(hardware->cs_pin); i++) {
if (pin == hardware->cs_pin[i]) {
volatile uint32_t *reg = portConfigRegister(pin);
*reg = hardware->cs_mux[i];
return hardware->cs_mask[i];
}
count--;
} */
return 0;
}

void SPIClass::setMOSI(uint8_t pin)
{
// Currently only one defined so just return...
}

void SPIClass::setMISO(uint8_t pin)
{
// Currently only one defined so just return...
}

void SPIClass::setSCK(uint8_t pin)
{
// Currently only one defined so just return...
}


void SPIClass::setBitOrder(uint8_t bitOrder)
{
hardware->clock_gate_register |= hardware->clock_gate_mask;

if (bitOrder == LSBFIRST) {
port->TCR |= LPSPI_TCR_LSBF;
} else {
port->TCR &= ~LPSPI_TCR_LSBF;
}
}

void SPIClass::setDataMode(uint8_t dataMode)
{
hardware->clock_gate_register |= hardware->clock_gate_mask;
//SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
}

const SPIClass::SPI_Hardware_t spiclass_lpspi4_hardware = {
CCM_CCGR1, CCM_CCGR1_LPSPI4(CCM_CCGR_ON),
12,
3 | 0x10,
11,
3 | 0x10,
13,
3 | 0x10,
10,
3 | 0x10,
};
SPIClass SPI(&IMXRT_LPSPI4_S, &spiclass_lpspi4_hardware);


void SPIClass::transfer(const void * buf, void * retbuf, size_t count)
{

if (count == 0) return;
uint8_t *p_write = (uint8_t*)buf;
uint8_t *p_read = (uint8_t*)retbuf;
size_t count_read = count;

// Pass 1 keep it simple and don't try packing 8 bits into 16 yet..
// Lets clear the reader queue
//port->CR = LPSPI_CR_RRF;

while (count > 0) {
// Push out the next byte;
port->TDR = p_write? *p_write++ : _transferWriteFill;
count--; // how many bytes left to output.
// Make sure queue is not full before pushing next byte out
do {
if ((port->RSR & LPSPI_RSR_RXEMPTY) == 0) {
uint8_t b = port->RDR; // Read any pending RX bytes in
if (p_read) *p_read++ = b;
count_read--;
}
} while ((port->SR & LPSPI_SR_TDF) == 0) ;

}

// now lets wait for all of the read bytes to be returned...
while (count_read) {
if ((port->RSR & LPSPI_RSR_RXEMPTY) == 0) {
uint8_t b = port->RDR; // Read any pending RX bytes in
if (p_read) *p_read++ = b;
count_read--;
}
}
}




+ 46
- 27
SPI.h View File

@@ -1051,7 +1051,7 @@ private:
}
void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
__attribute__((__always_inline__)) {
// TODO: make these implement settings - for now, just fixed config
// TODO: Need to check timings as related to chip selects?

uint32_t d, div, clkhz = 528000000/7; // LPSPI peripheral clock
if (clock == 0) clock =1;
@@ -1063,27 +1063,46 @@ private:
} else {
div =0;
}
ccr = LPSPI_CCR_SCKDIV(div);
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;
}
uint32_t ccr; // clock config, pg 2660 (RT1050 ref, rev 2)
uint32_t tcr; // transmit command, pg 2664 (RT1050 ref, rev 2)
friend class SPIClass;
};



class SPIClass { // Teensy 4
public:
static const uint8_t CNT_MISO_PINS = 1;
static const uint8_t CNT_MOSI_PINS = 1;
static const uint8_t CNT_SCK_PINS = 1;
static const uint8_t CNT_CS_PINS = 1;
typedef struct {
volatile uint32_t &clock_gate_register;
uint32_t clock_gate_mask;
const uint32_t clock_gate_mask;
const uint8_t miso_pin[CNT_MISO_PINS];
const uint32_t miso_mux[CNT_MISO_PINS];
const uint8_t mosi_pin[CNT_MOSI_PINS];
const uint32_t mosi_mux[CNT_MOSI_PINS];
const uint8_t sck_pin[CNT_SCK_PINS];
const uint32_t sck_mux[CNT_SCK_PINS];
const uint8_t cs_pin[CNT_CS_PINS];
const uint32_t cs_mux[CNT_CS_PINS];
} SPI_Hardware_t;
static const SPI_Hardware_t lpspi4_hardware;

public:
constexpr SPIClass(uintptr_t myport, uintptr_t myhardware)
: port_addr(myport), hardware_addr(myhardware) {
constexpr SPIClass(IMXRT_LPSPI_t *myport, const SPI_Hardware_t *myhardware)
: port(myport), hardware(myhardware) {
}
// Initialize the SPI library
void begin();
@@ -1147,22 +1166,22 @@ public:
#endif

//printf("trans\n");
LPSPI4_CR = 0;
LPSPI4_CFGR1 = LPSPI_CFGR1_MASTER | LPSPI_CFGR1_SAMPLE;
LPSPI4_CCR = settings.ccr;
LPSPI4_TCR = settings.tcr;
//LPSPI4_CCR = LPSPI_CCR_SCKDIV(4);
//LPSPI4_TCR = LPSPI_TCR_FRAMESZ(7);
LPSPI4_CR = LPSPI_CR_MEN;
port->CR = 0;
port->CFGR1 = LPSPI_CFGR1_MASTER | LPSPI_CFGR1_SAMPLE;
port->CCR = settings.ccr;
port->TCR = settings.tcr;
//port->CCR = LPSPI_CCR_SCKDIV(4);
//port->TCR = LPSPI_TCR_FRAMESZ(7);
port->CR = LPSPI_CR_MEN;
}

// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
uint8_t transfer(uint8_t data) {
// TODO: check for space in fifo?
LPSPI4_TDR = data;
port->TDR = data;
while (1) {
uint32_t fifo = (LPSPI4_FSR >> 16) & 0x1F;
if (fifo > 0) return LPSPI4_RDR;
uint32_t fifo = (port->FSR >> 16) & 0x1F;
if (fifo > 0) return port->RDR;
}
//port().SR = SPI_SR_TCF;
//port().PUSHR = data;
@@ -1170,12 +1189,12 @@ public:
//return port().POPR;
}
uint16_t transfer16(uint16_t data) {
transfer(data >> 8);
transfer(data & 255);
//port().SR = SPI_SR_TCF;
//port().PUSHR = data | SPI_PUSHR_CTAS(1);
//while (!(port().SR & SPI_SR_TCF)) ; // wait
//return port().POPR;
uint32_t tcr = port->TCR;
port->TCR = (tcr & 0xfffff000) | LPSPI_TCR_FRAMESZ(15); // turn on 16 bit mode
port->TDR = data; // output 16 bit data.
while ((port->RSR & LPSPI_RSR_RXEMPTY)) ; // wait while the RSR fifo is empty...
port->TCR = tcr; // restore back
return port->RDR;
}

void inline transfer(void *buf, size_t count) {transfer(buf, buf, count);}
@@ -1270,10 +1289,10 @@ public:

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

void updateCTAR(uint32_t ctar);
uintptr_t port_addr;
uintptr_t hardware_addr;
uint8_t miso_pin_index = 0;
uint8_t mosi_pin_index = 0;
uint8_t sck_pin_index = 0;

Loading…
Cancel
Save