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.

MSP430F47187: Help required with initializing SPI on USCI B1

Part Number: MSP430F47187

Hello All, 

I am trying to interface a Microchip NOR flash (SST25VF080B) to the MSP43047187 on SPI port (USCI B1) . 

The same port was originally interfaced to an SD card. Pins used are P2.1, P2.2, and P2.3.

Currently the SD card holder has not been mounted , although the pull up resistors (10K) on all lines are in place.

I am using SPI in the 3 pin mode. The CE#  and WP# are derived from P1.3 and P1.4 in my hardware and bit banged when required. 

My problem is I am not able to initialize the SPI bus itself. I do not see any activity on either the CLK, SIMO or the SOMI pins. Only the Enable and WP pins get toggled since they are bit banged. 

Initialization code is attached below. 

// SPI Ports
#define SPI_SEL         P2SEL
#define SPI_DIR         P2DIR
#define SPI_OUT         P2OUT
#define SPI_REN         P2REN
// SPI pins
#define SPI_MOSI        BIT1
#define SPI_MISO        BIT2
#define SPI_CLK         BIT3

// NOR Flash Pins
#define NOR_CS          BIT3
#define NOR_WP          BIT4
#define NOR_HOLD        BIT7
// #define NOR_HOLD         BIT0

// NOR flash definitions
#define NOR_CS_SEL		P1SEL
#define NOR_CS_OUT		P1OUT
#define NOR_CS_DIR		P1DIR
#define	NOR_CS_REN		P1REN


void Init_SPI(void)
{
	// Initialize USCI_B1 for SPI Master operation
	UCB1CTL1 = UCSWRST;          	// Reset state machine

	UCB1CTL0 = UCCKPH + UCCKPL + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master
	UCB1CTL1 = UCSWRST + UCSSEL_2;  // Use SMCLK, hold in RESET condition


	UCB1BR0 = 80;                   // Initial SPI clock must be <400kHz
	UCB1BR1 = 0;                    // f_UCxCLK = 16MHz/40 = 400kHz

	// Port initialization for NOr Flash operation
	SPI_SEL |= SPI_CLK + SPI_MISO + SPI_MOSI; 	// Select SPI functions for pins allocated
	SPI_REN |= SPI_CLK + SPI_MISO + SPI_MOSI;	// Enable Internal Pull up on MISO
	SPI_OUT |= SPI_CLK + SPI_MISO + SPI_MOSI;	// Set Output state to High
	SPI_DIR |= SPI_CLK + SPI_MOSI;	// Configure as Output.
	SPI_DIR &= ~SPI_MISO;			// Configure as input.

	// Clock polarity select - The inactive state is high
	// MSB first
	UC1IE	=	0x00;
	UCB1CTL1 &= ~UCSWRST;           // Release USCI from reset state
	UC1IFG &= ~(UCB1RXIFG);
}	// end of Init SPI Bus
void Init_NOR_Flash(void)
{
	NOR_CS_SEL &= ~(NOR_CS + NOR_WP);	// CS is plain I/O port.
	NOR_CS_OUT |= NOR_CS + NOR_WP;		// Chip is Disabled mode
	NOR_CS_REN |= NOR_CS + NOR_WP;
	NOR_CS_DIR |= NOR_CS + NOR_WP;		// Chip Enable direction to Output mode.

	NOR_HOLD_SEL &= ~NOR_HOLD;
	NOR_HOLD_OUT |= NOR_HOLD;
	NOR_HOLD_DIR |= NOR_HOLD;

	NOR_ENABLE;
	_NOP();
	Send_NOR_Command(NOR_WRDI);
	NOR_DISABLE;
	_NOP();
	Flash_Lock();
	_NOP();
}

These are called in Main as follows:

void main(void)
{

   unsigned int i;

   WDTCTL = WDTPW + WDTHOLD;              // Stop watchdog timer

   FLL_CTL0 |= DCOPLUS;                   // DCO+ set, freq = xtal x D x N+1
   SCFI0 = FLLD_4+FN_4;                   // x4 DCO freq, 16MHz nominal DCO
   SCFQCTL = 31;                          //(31+1) x 32768 x 4 = 4 MHz
   FLL_CTL1 |= XT2OFF + LFXT1DIG;

   for (i = 0; i < 10; i++)
     delay(10000);

   // Wait for xtal to stabilize
   do
   {
     IFG1 &= ~OFIFG;                       // Clear OSCFault flag
     for (i = 500; i > 0; i--);            // Time for flag to set
   }
   while ((IFG1 & OFIFG));                 // OSCFault flag

   //wait for power to stabalize
   SVSCTL = 0xb0;
   for(i = 0; i < 10000; i++);

   while(SVSCTL & SVSFG)
   {
     SVSCTL &= ~SVSFG;
     for(i = 0; i < 10000; i++);
   }

   //switch to high speed
   FLL_CTL0 |= DCOPLUS;                   // DCO+ set, freq = xtal x D x N+1
   SCFI0 = FLLD_4+FN_4;                   // x4 DCO freq, 16MHz nominal DCO
   SCFQCTL = 124;                         //(124+1) x 32768 x 4 = 16 MHz
   FLL_CTL1 |= XT2OFF + LFXT1DIG;

   //Wait for xtal to stabilize
   do
   {
     IFG1 &= ~OFIFG;                       // Clear OSCFault flag
     for (i = 10000; i > 0; i--);          // Time for flag to set
   }
   while ((IFG1 & OFIFG));                 // OSCFault flag

   FCTL2 = FWKEY + FSSEL0 + FN5 + FN4;     // MCLK/41 for Flash Timing Generator


	P4SEL = 0x00;                             //i/o function selected for P4
	P4REN = 0x00;
	P4DIR = 0xff;                             //all output
	P4OUT = 0xff;
     Init_SPI();
     Init_NOR_Flash();

       while(1)

       {

       }

 

 

  • Hello Aniruddha,

    Are you sure that your code exits the clock system setup and services the SPI initialization properly? The PxREN, PxOUT, and PxDIR registers do not need to be altered since the port pins are set for SPI functionality, and you should not have external pull-up resistors installed. Please make sure that you are using the proper clock phase and polarity settings for your slave device as described in the datasheet. You also do not share the code that actually populates the transmit buffer so it is difficult to further discern the issue.

    Regards,
    Ryan
  • Hi Ryan,

    Thanks for your response. Sorry, my fault.... I forgot to add that part.
    The TxBuf is stuffed in the function call below:

    Could you please elaborate on your question"Are you sure that your code exits the clock system setup and services the SPI initialization properly?" I am not sure I understand what you mean. Am I missing something in the initialization part.The Clock initialization is there in code above.
    Best Regards
    Aniruddha

    /********************************************************************************
    * Function : Send NOR Command
    * Description : This functions writes a command to the NOR FLASH.
    *
    * Variables : takes a byte as command variable.Returns none
    * Author : Aniruddha Phadnis
    * Created : 23 Aug 2017
    ********************************************************************************/
    void Send_NOR_Command(unsigned char cmd)
    {
    _DINT();
    while (!(UC1IFG & UCB1TXIFG)) ; // Wait while not ready for TX
    UCB1TXBUF = cmd; // Write byte
    while (UCB1STAT & UCBUSY) ; // Wait for all TX/RX to finish
    _EINT();
    }
  • Hi Aniruddha,

    I mean to ask if your code gets stuck at any particular line during debugging.

    Regards,
    Ryan
  • HI Ryan,

    Sorry for the delayed response. Thank you for your suggestions. There were three issues actually, each linearly linked to each other.

    I have no idea why, but I had to actually add pull up resistors to the clock and SOMI lines. These were originally missing. When I checked these lines on the scope, I saw the signal never attained its required level (2.2V) for it to be recognized as a high level. There is probably an issue with stray capacitance some where but for the time being its been resolved by the pull up resistors.
    Even after getting the clock and SIMO lines to toggle correctly, there was still a clock phase and polarity issue.
    Even after getting that .... it would be nice if they had highlighted the fact that the controller does not generate the clock for slave response on its own. I was waiting for the controller to generate the clock on its own.. which never happened. It took many readings of the data sheet for me to figure it out.... yeah may be I am slow.
    Regards
    Aniruddha

**Attention** This is a public forum