Part Number: MSP430F5438A
I am working with MSP430F5438A microcontroller and I am using FreeRTOS cooperative mode with 1ms tick time.
I have a scenario where I have to ensure that the Chip Select is pulled high (deselected) as soon as possible after transmission has completed (within 1 ms).
As a result, I tried to pull the CS high inside the ISR after the last byte have been sent out.
However, I noticed on the oscilloscope that the CS is being pulled high before the last byte have been fully transmitted.
I tried observing the results at two different SPI clock rate (12.8KHz and 128KHz) and attached the oscilloscope images.
spi clock (yellow)
Chip Select (pink)
MOSI (green)
with spi clock 12.8KHz (UCA1BR0 set to 100)
with spi clock 128KHz (UCA1BR0 set to 10)
From the image, it can be seen that after the CS has been pulled high, the last few bits are still in the midst of transmitting. The number of bits missed seems to vary with different spi clock rate.
#include <msp430.h>
#include <stdio.h>
#include <stdint.h>
#include "msp430f5xx_6xxgeneric.h"
/**
* main.c
*/
typedef void (*myCallback)(void);
#define HWREG8(x) \
(*((volatile uint8_t *)((uint16_t)x)))
/*******************************************************************************
* Function declaration
******************************************************************************/
void spib_init(void);
void spib_setTx_buf(const uint8_t spibTxBuf[], uint16_t spibTxLen,
myCallback spibLocalCallback);
void transmit_data(void);
void deselect_CS(void);
/******************************************************************************/
uint8_t tx_testdata[6] = {'A','B','C','D','E','\n'};
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
// config CS pin
P9SEL &= ~0x40;
P9DIR |= 0x40;
P9OUT |= 0x40;
spib_init();
__bis_SR_register(GIE); // CPU off, enable interrupts
transmit_data();
while (1)
{
}
// return 0;
}
void transmit_data(void)
{
P9OUT &= ~0x40;
spib_setTx_buf(tx_testdata, 6, &deselect_CS);
}
void deselect_CS(void)
{
P9OUT |= 0x40;
__delay_cycles(1000000);
transmit_data();
}
//******************************************************************************
//
//SPI
//
//******************************************************************************
myCallback spibCallback;
volatile uint8_t *spibPTxData; // Pointer to TX data
volatile uint16_t spibTXByteCtr;
void spib_init(void)
{
// config UCA1 MOSI and MISO pin
P5SEL |= 0xC0;
P5DIR |= 0x40;
// config UCA1 clk pin
P3SEL |= 0x40;
P3DIR |= 0x40;
UCA1CTL1 |= UCSWRST;
UCA1CTL0 |= UCMST+UCSYNC+UCMODE_0+UCCKPH+UCCKPL+UCMSB;
UCA1CTL1 |= UCSSEL__SMCLK;
UCA1BR0 = 0x64; // 100
UCA1BR1 = 0;
UCA1CTL1 &= ~UCSWRST;
}
void spib_setTx_buf(const uint8_t spibTxBuf[], uint16_t spibTxLen,
myCallback spibLocalCallback)
{
spibCallback = spibLocalCallback;
spibPTxData = (unsigned char *)spibTxBuf; // TX array start address
// Place breakpoint here to see each
// transmit operation.
spibTXByteCtr = spibTxLen; // Load TX byte counter
HWREG8(USCI_A1_BASE + OFS_UCAxIFG) &= ~UCTXIE;
HWREG8(USCI_A1_BASE + OFS_UCAxIE) |= UCTXIE;
if (spibTXByteCtr > 0)
{
if (spibPTxData == NULL)
{
UCA1TXBUF = 0xFF;
}
else
{
UCA1TXBUF = *spibPTxData++;
}
spibTXByteCtr--;
}
// UCA1TXBUF = spitxbufdata;
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_A1_VECTOR)))
#endif
void USCI_A1_ISR (void)
{
switch (__even_in_range(UCA1IV,4)){
//Vector 2 - RXIFG
case 2:
break;
case 4:
if(0 < spibTXByteCtr)
{
// UCA1TXBUF = spitxbufdata;
if (spibPTxData == NULL)
{
UCA1TXBUF = 0xFF;
}
else
{
UCA1TXBUF = *spibPTxData++;
}
spibTXByteCtr--;
}
else if(0 == spibTXByteCtr)
{
HWREG8(USCI_A1_BASE + OFS_UCAxIFG) &= ~UCTXIE;
HWREG8(USCI_A1_BASE + OFS_UCAxIE) &= ~UCTXIE;
if(NULL != spibCallback)
(*spibCallback)();
}
break;
default:
break;
}
}
This is the simplified code I have used to generate the above results.
I would like to ask why are the last few cycles happening after CS has been pulled high if I pull the CS high immediately inside ISR after the last byte transmission?
Also, why are the number of cycles left after CS has been pulled high different as the spi clock rate changes?
Other than spi clock rate, are there other possible factors that may cause the number of cycles remaining after CS high to differ (and hence a different amount of delay required before CS is pulled high)?