This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BSL with USCIA interface.

Other Parts Discussed in Thread: MSP430F5438A

Hi all,

I'm custumizing BSL with USCIA on MSP430F5438A. In BSL context, the micro should be clocked on DCO at 8 MHZ.

I'm working with "no parity" (I removed the configuration with PARITY EVEN).

Unfortunatly, BSL receive my commands, but I receive back wrong frame because the bytes are scrashed or overruned. I think it is caused by my send function in BSL.

#include "BSL_Device_File.h"
#include "BSL430_PI.h"
#include "BSL430_Command_Interpreter.h"
#include "BSL430_Command_Definitions.h"
/*******************************************************************************
Change Log:
--------------------------------------------------------------------------------
Version 0x52 
3.15.10  LCW   changed to DCORSEL_4
--------------------------------------------------------------------------------
Version 0x53 
5.18.10  LCW   made buffer size unsized to align with Interface
--------------------------------------------------------------------------------
*******************************************************************************/
//errors
#define HEADER_INCORRECT (PI_COMMAND_UPPER+0x01)
#define CHECKSUM_INCORRECT (PI_COMMAND_UPPER+0x02) 
#define PACKET_SIZE_ZERO (PI_COMMAND_UPPER+0x03)
#define PACKET_SIZE_TOO_BIG (PI_COMMAND_UPPER+0x04)
#define UNKNOWN_ERROR (PI_COMMAND_UPPER+0x05)
// errors for PI commands
#define UNKNOWN_BAUD_RATE (PI_COMMAND_UPPER+0x06)

// TA PI Commands
#define CHANGE_BAUD_RATE (PI_COMMAND_UPPER + 0x02)

// 4800 (unused)
#define BAUD_4800   0x01
#define BAUD_9600   0x02
#define BAUD_19200  0x03
#define BAUD_38400  0x04
#define BAUD_57600  0x05
#define BAUD_115200 0x06

#define MAX_BUFFER_SIZE 260

char verifyData( int checksum );
char receiveByte();
void sendByte( char data );
void interpretPI_Command();
void init_USCI( char baud_rate );

__no_init char *BSL430_ReceiveBuffer;
__no_init char *BSL430_SendBuffer;
__no_init unsigned int BSL430_BufferSize;
#pragma data_alignment=2
__no_init char RAM_Buf[MAX_BUFFER_SIZE];

#define USCIA_VERSION 0x03

#if 0
const unsigned char BSL430_PI_Version @ "BSL430_VERSION_PI" = (BSL430_USCIA_PI+USCIA_VERSION);
#pragma required=BSL430_PI_Version
#else
const unsigned char BSL430_PI_Version = (BSL430_USCIA_PI+USCIA_VERSION);
#endif
/*******************************************************************************
*Function:    init
*Description: Initialize the USCI and Ports
*Parameters: 
*******************************************************************************/
void PI_init()
{
  volatile int i;
  BSL430_ReceiveBuffer = RAM_Buf;
  BSL430_SendBuffer = RAM_Buf;

  UCSCTL4 = SELA__REFOCLK + SELM__DCOCLK + SELS__DCOCLK;  // to do check SELA
  
  UCSCTL0 = 0x000;                          // Set DCO to lowest Tap
  
  UCSCTL1 = DCORSEL_4;                      // 8MHz nominal DCO
  UCSCTL5 = DIVM_0 + DIVS_0;
  UCSCTL2 = FLLD_2 | (((DCO_SPEED/ACLK_SPEED)/4) - 1); // 8MHz

  // init led
  P8DIR |= BIT4; //Set LED0 as output
  P8OUT |= BIT4; //Set LED0 by default
                
  init_USCI( BAUD_9600 );
  
}//init


/*******************************************************************************
*Function:    receivePacket
*Description: Reads an entire packet, verifies it, and sends it to the core to be interpreted
*******************************************************************************/
char PI_receivePacket()
{
  char RX_StatusFlags = RX_PACKET_ONGOING;
  char dataByte = 0;
  int dataPointer = 0;
  volatile int checksum = 0;
  while( RX_StatusFlags == RX_PACKET_ONGOING )
  {
    dataByte = receiveByte();               // get another byte from host
    if( dataPointer == 0 )                  // first byte is the size of the Core packet
    {
      if ( dataByte != 0x80 )               // first byte in packet should be 0x80
      {
        sendByte( HEADER_INCORRECT );
        RX_StatusFlags = RX_ERROR_RECOVERABLE;
      }
      else
      {
        dataPointer++;
      }
    }
    else if( dataPointer == 1 )             // first byte is the size of the Core packet
    {
      BSL430_BufferSize = dataByte;
      dataPointer++;
    }
    else if( dataPointer == 2 )
    {
      BSL430_BufferSize |= (int)dataByte<<8;
      if( BSL430_BufferSize == 0 )
      {
        sendByte( PACKET_SIZE_ZERO );
        RX_StatusFlags = RX_ERROR_RECOVERABLE;
      }
      if( BSL430_BufferSize > MAX_BUFFER_SIZE )        // For future devices that might need smaller packets
      {
        sendByte( PACKET_SIZE_TOO_BIG );
        RX_StatusFlags = RX_ERROR_RECOVERABLE;
      } 
      dataPointer++;
    }
    else if( dataPointer == (BSL430_BufferSize + 3 ) )
    {
      // if the pointer is pointing to the Checksum low data byte which resides
      // after 0x80, rSize, Core Command.
      checksum = dataByte;
      dataPointer++;
    } 
    else if( dataPointer == (BSL430_BufferSize+4) ) 
    {  
      // if the pointer is pointing to the Checksum low data byte which resides
      // after 0x80, rSize, Core Command, CKL.
      checksum = checksum | dataByte<<8;
      if( verifyData(checksum) )
      {
        if( (RAM_Buf[0] & 0xF0) == PI_COMMAND_UPPER)
        {
          interpretPI_Command();
          RX_StatusFlags = RX_PACKET_ONGOING;
          dataByte = 0;
          dataPointer = 0;
          checksum = 0;
        }
        else
        {
          sendByte( ACK );
          RX_StatusFlags = DATA_RECEIVED;
        }
      }
      else
      {
        sendByte( CHECKSUM_INCORRECT );
        RX_StatusFlags = RX_ERROR_RECOVERABLE;
      }
    }
    else
    {
      RAM_Buf[dataPointer-3] = dataByte;
      dataPointer++;
    }
    
  }
  return RX_StatusFlags;
}
/*******************************************************************************
*Function:    sendData
*Description: Sends the data in the data buffer
*******************************************************************************/
void PI_sendData(int size)
{
  int i;
  sendByte( 0x80 );
  sendByte( size & 0xFF );
  sendByte( size>>8 & 0xFF );
  CRCINIRES = 0xFFFF;
  for( i = 0; i < size; i++){
    CRCDIRB_L = RAM_Buf[i];
    sendByte( RAM_Buf[i] );
  }
  i = CRCINIRES;
  sendByte( i & 0xFF );
  sendByte( i>>8 & 0xFF );
}

/*******************************************************************************
*Function:    sendByte
*Description: Sends a byte
*******************************************************************************/
void sendByte(char data)
{
  while (!(UCA0IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
  while((UCA0STAT & UCBUSY) == UCBUSY);
  UCA0TXBUF = data;
}

void sendString( const char * string )
{
  int i=0;
  while(string[i] != 0)
  {
    sendByte(string[i]);
    i++;
  }
}
/*******************************************************************************
*Function:    receiveByte
*Description: receives a byte
*******************************************************************************/
char receiveByte()
{
  while( !(UCA0IFG & UCRXIFG));       // wait for RX flag
  return UCA0RXBUF;
}
/*******************************************************************************
*Function:    verifyData
*Description: verifies the data in the data buffer against a checksum
*Parameters: 
*           int checksum    the checksum to check against
*Returns:
*           1 checksum parameter is correct for data in the data buffer
*           0 checksum parameter is not correct for the data in the buffer
*******************************************************************************/
char verifyData( int checksum )
{
  int i;
  CRCINIRES = 0xFFFF;
  for( i = 0; i < BSL430_BufferSize; i++)
  {
    CRCDIRB_L = RAM_Buf[i];
  }
  return (CRCINIRES == checksum );
}

/*******************************************************************************
*Function:    getBufferSize
*Description: Returns the max Data Buffer Size for this PI
*Returns:     max buffer size
*******************************************************************************/
int PI_getBufferSize()
{
  return MAX_BUFFER_SIZE;
}


/*******************************************************************************
*Function:    interpretPI_Command
*Description: processes a PI command
*******************************************************************************/
void interpretPI_Command()
{
  char command = RAM_Buf[0];
  if( command == CHANGE_BAUD_RATE )
  {
    volatile int i;
    char rate = RAM_Buf[1];
    if( (rate < BAUD_9600 )||(rate > BAUD_115200) )
    {
        sendByte(UNKNOWN_BAUD_RATE);
    }
    else
    {
      sendByte(ACK);
      while(UCA0STAT&UCBUSY);
      init_USCI( rate );
    }
  }
}

/*******************************************************************************
*Function:    init_USCI
*Description: internal code size saving function used by init and change baud rate
*******************************************************************************/
void init_USCI( char baud_rate )
{
  UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**
  //UCA0CTL0 |= UCPEN+UCPAR;                  // even parity
  UCA0CTL0 = 0;
  UCA0CTL1 |= UCSSEL__SMCLK;                // SMCLK
  switch ( baud_rate )
  {
    case BAUD_9600:
      UCA0BRW = 833 ;                           // 8MHz 9600 (see User's Guide)
      UCA0MCTL = UCBRS_2 + UCBRF_0;             // Modulation   
    break;
    case BAUD_19200:
      UCA0BRW = 416;                            // 8MHz 19200 (see User's Guide)
      UCA0MCTL = UCBRS_6 + UCBRF_0;             // Modulation   
    break;
    case BAUD_38400:
      UCA0BRW = 208;                            // 8MHz 38400 (see User's Guide)
      UCA0MCTL = UCBRS_3 + UCBRF_0;             // Modulation   
    break;
    case BAUD_57600:
      UCA0BRW = 138;                            // 8MHz 57600 (see User's Guide)
      UCA0MCTL = UCBRS_7 + UCBRF_0;             // Modulation   
    break;
    case BAUD_115200:
      UCA0BRW = 69;                            // 8MHz 115200 (see User's Guide)
      UCA0MCTL = UCBRS_4 + UCBRF_0;            // Modulation   
    break; 
  }
  USCI_PORT_SEL = RXD+TXD;                        // P1.5.6 = USCI_A0 TXD/RXD
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
}

I attached here the code. If someone have few minutes to see what goes wrong, it will be very nice.

Thanks

Mikael

  • In your sendByte funciton, you check for UCBUSY. Besides the fact that the '==UCBUSY' is superfluous, as (UCA0STAT & UCBUSY) is either 0 (= false) or UCBUSY (!=0 and therefore true), it is inefficient (as it waits until the previous byte is fully sent while you could already out the next byte into TXBUF) and also blocking if the RX part of the USCI is active. UCBUSY is set too if there's something coming in.

    In PI_sendData, the &0xff in the calls to sendByte are superfluous, since sendByte already takes a byte parameter. But it won't hurt, just waste some time and space if teh compielr isn't smart enough to optimize it away.
    Note that your use of CRCDIRB_L isn't compatible with the non-A version of the 5438 (which doesn't have the RB registers).

    I recommend renaming PI_getBufferSize to PI_getMaxBufferSize, as the current name might give the impression that the current buffer size is returned.

    But none of these things should cause a problem on sending. My best guess is that your baudrate is off, so you get bit errors and even framing errors.
    The original, timer-based BSL takes the PCs first byte to get its timing, but with the USCI, you need to provide it by yourself and you might be too much off.

    btw: if you add the CRC to the bytes under test, CRCINIRES will return 0 if the CRC was correct. So if the checksum is right behind your data (MSB first, I think), you can just feed it to the CRC module. No need to separately pass and then compare it.

**Attention** This is a public forum