/*
* ppsys_bsp_spi.c
*
* Created on: June 10, 2019
* Author: Mike Spenard // PP Systems
*
* -We're using LPSPI1 which required SD Card to be moved to USDHC2
* -ATWINC1500 requires 0x00 dummy data
*
*
*/
/* Standard C Included Files */
#include <stdio.h>
#include <string.h>
#include "fsl_common.h"
#include "fsl_lpspi.h"
#include "fsl_debug_console.h"
#include "ppsys_globals.h"
#include "ppsys_util.h"
#include "ppsys_bsp_spi.h"
#include "ewrte.h"
#define LPSPI1_CLOCK_SOURCE_DIVIDER (7U) // Clock divider for master lpspi clock source; see also board.c's mux setup
#define TRANSFER_BAUDRATE 100000000U // Breadboard board rate: 1 000 000U
#define SPI_MASTER_TRANSMIT_TIMEOUT 10
#define SPI_MASTER_RECEIVE_TIMEOUT 100
static lpspi_master_handle_t handle;
volatile bool g_SPI_MasterCompletionFlag = false;
volatile bool g_SPI_MasterTransferError = false;
t_SPI_data SPI_Data;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
/*
uint8_t sendSPI1(unsigned char *buffer, int length) {
status_t reVal = kStatus_Fail;
lpspi_transfer_t transfer;
uint16_t transferTimeout = SPI_MASTER_TRANSMIT_TIMEOUT;
uint16_t lastTick;
transfer.dataSize=length;
transfer.txData=buffer;
transfer.rxData=NULL;
transfer.configFlags=kLPSPI_MasterPcsContinuous;
// hold off doing TX if bus is busy; ADD A TIMEOUT
while (LPSPI_GetStatusFlags(LPSPI1) & kLPSPI_ModuleBusyFlag)
{
}
reVal = LPSPI_MasterTransferNonBlocking(LPSPI1, &handle, &transfer);
if (reVal != kStatus_Success)
{
return 0; return 0;
}
g_SPI_MasterCompletionFlag = false; // Reset master completion flag to false
g_SPI_MasterTransferError = false; // clear errors
lastTick = EwGetTicks();
while (!g_SPI_MasterCompletionFlag && !g_SPI_MasterTransferError) // && transferTimeout) // Wait for transfer completed or error or timeout
{
//transferTimeout = transferTimeout - (EwGetTicks() - lastTick);
//lastTick = EwGetTicks();
}
g_SPI_MasterCompletionFlag = false;
for(int i=0; i< length; i++)
PRINTF("tx:0x%02X\n\r", buffer[i]);
return 1;
}
*/
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
uint8_t sendCharSPI1(unsigned char data) {
status_t reVal = kStatus_Fail;
lpspi_transfer_t transfer;
uint16_t transferTimeout = SPI_MASTER_TRANSMIT_TIMEOUT;
uint16_t lastTick;
transfer.dataSize=1;
transfer.txData=&data;
transfer.rxData=NULL;
transfer.configFlags=kLPSPI_MasterPcsContinuous;
// hold off doing TX if bus is busy; ADD A TIMEOUT
while (LPSPI_GetStatusFlags(LPSPI1) & kLPSPI_ModuleBusyFlag)
{
}
g_SPI_MasterCompletionFlag = false; // Reset master completion flag to false
g_SPI_MasterTransferError = false; // clear errors
reVal = LPSPI_MasterTransferNonBlocking(LPSPI1, &handle, &transfer);
if (reVal != kStatus_Success)
{
return 0; return 0;
}
lastTick = EwGetTicks();
while (!g_SPI_MasterCompletionFlag && !g_SPI_MasterTransferError && transferTimeout) // Wait for transfer completed or error or timeout
{
transferTimeout = transferTimeout - (EwGetTicks() - lastTick);
lastTick = EwGetTicks();
}
g_SPI_MasterCompletionFlag = false;
if(g_SPI_MasterTransferError) // if we picked up an error from the ISR then exit
{
PRINTF("SPI_TX TRANSFER ERROR\n\r");
SPI_Data.TXtransferErrors++; // book-keeping var
return 0;
}
if(transferTimeout == 0) // if we timed out something went wrong so reset the bus
{
PRINTF("SPI_TX TIMEOUT\n\r");
SPI_Data.TXtimeouts++; // book-keeping var
//ppsys_bsp_spi_reinit();
return 0;
}
return 1;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
/*
uint8_t receiveSPI1(unsigned char *buffer, int length) {
status_t reVal = kStatus_Fail;
lpspi_transfer_t transfer;
uint16_t transferTimeout = SPI_MASTER_RECEIVE_TIMEOUT;
uint16_t lastTick;
transfer.dataSize=length;
transfer.txData=NULL;
transfer.rxData=buffer;
transfer.configFlags=kLPSPI_MasterPcsContinuous;
reVal = LPSPI_MasterTransferNonBlocking(LPSPI1, &handle, &transfer);
if (reVal != kStatus_Success)
{
return 0; return 0;
}
g_SPI_MasterCompletionFlag = false; // Reset master completion flag to false
g_SPI_MasterTransferError = false; // clear errors
lastTick = EwGetTicks();
while (!g_SPI_MasterCompletionFlag && !g_SPI_MasterTransferError && transferTimeout) // Wait for transfer completed or error or timeout
{
transferTimeout = transferTimeout - (EwGetTicks() - lastTick);
lastTick = EwGetTicks();
}
g_SPI_MasterCompletionFlag = false;
for(int i=0; i< length; i++)
PRINTF("rx: 0x%02X\n\r", buffer[i]);
return 1;
}
*/
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
unsigned char receiveCharSPI1(void) {
status_t reVal = kStatus_Fail;
unsigned char rx;
lpspi_transfer_t transfer;
uint16_t transferTimeout = SPI_MASTER_RECEIVE_TIMEOUT;
uint16_t lastTick;
transfer.dataSize=1;
transfer.txData=NULL;
transfer.rxData=℞
transfer.configFlags=kLPSPI_MasterPcsContinuous;
g_SPI_MasterCompletionFlag = false; // Reset master completion flag to false
g_SPI_MasterTransferError = false; // clear errors
reVal = LPSPI_MasterTransferNonBlocking(LPSPI1, &handle, &transfer);
if (reVal != kStatus_Success)
{
return 0; return 0;
}
lastTick = EwGetTicks();
while (!g_SPI_MasterCompletionFlag && !g_SPI_MasterTransferError && transferTimeout) // Wait for transfer completed or error or timeout
{
transferTimeout = transferTimeout - (EwGetTicks() - lastTick);
lastTick = EwGetTicks();
}
g_SPI_MasterCompletionFlag = false;
if(g_SPI_MasterTransferError) // if we picked up an error from the ISR then exit
{
PRINTF("SPI_RX TRANSFER ERROR\n\r");
SPI_Data.RXtransferErrors++; // book-keeping var
return 0;
}
if(transferTimeout == 0) // if we timed out something went wrong so reset the bus
{
PRINTF("SPI_RX TIMEOUT\n\r");
SPI_Data.RXtimeouts++; // book-keeping var
//ppsys_bsp_spi_reinit();
return 0;
}
return rx;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
static void ppsys_bsp_spi1_handler(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData) {
switch(status) // see fsl_lpi2c.h for all status flags 2600 to 2610
{
case kStatus_Success: // Signal transfer success when received success status.
g_SPI_MasterCompletionFlag = true;
break;
default: // anything other than 0 is probably an error
PRINTF("SPI1 ERROR Unknown: %u\n\r", status);
g_SPI_MasterTransferError = true;
break;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void ppsys_bsp_spi1_init(void) {
uint32_t srcClock_Hz;
lpspi_master_config_t masterConfig;
/*Master config*/
masterConfig.baudRate = TRANSFER_BAUDRATE;
masterConfig.bitsPerFrame = 8;
masterConfig.cpol = kLPSPI_ClockPolarityActiveHigh;
masterConfig.cpha = kLPSPI_ClockPhaseFirstEdge;
masterConfig.direction = kLPSPI_MsbFirst;
masterConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.baudRate;
masterConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.baudRate;
masterConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.baudRate;
// masterConfig.whichPcs = kLPSPI_Pcs0;
// masterConfig.pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
masterConfig.pinCfg = kLPSPI_SdiInSdoOut;
masterConfig.dataOutConfig = kLpspiDataOutTristate; // NXP default =kLpspiDataOutRetained
srcClock_Hz = CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (LPSPI1_CLOCK_SOURCE_DIVIDER + 1U);
LPSPI_MasterInit(LPSPI1, &masterConfig, srcClock_Hz);
PRINTF(" SPI1 Clock: %i Hz\n\r", srcClock_Hz / LPSPI1_CLOCK_SOURCE_DIVIDER);
PRINTF(" SPI1 Baud rate: %i \n\r", masterConfig.baudRate);
LPSPI_Enable(LPSPI1, false);
LPSPI1->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
LPSPI_Enable(LPSPI1, true);
LPSPI_SetDummyData(LPSPI1, 0x00); // getting this wrong causes 0xC7|F3| issues with ATWINC1500!
LPSPI_MasterTransferCreateHandle(LPSPI1, &handle, ppsys_bsp_spi1_handler, NULL);
}