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.

LP-MSPM0G3507: SPI Communication with NOR Flash

Part Number: LP-MSPM0G3507
Other Parts Discussed in Thread: MSPM0G3507

Dear TI Team, 

I have ZD25WQ16CTIGT NOR Flash( SPI enabled)  and trying to read and write operation with the same.

I have done the above setup with STM32 MCU below I attached the code as well ( Reading manufacture ID of NOR flash after reset).

void ZD25WQ16_RESET(void)
{
uint8_t Txdata[2];

Txdata[0] = 0x66; // Enable reset command
Txdata[1] = 0x99; // Reset command

CS_LOW();
HAL_SPI_Transmit(&ZD25WQ16_SPI, Txdata, 2, 1000);
CS_HIGH();
HAL_Delay(100);
}


void ZD25WQ16_ID(void)
{
uint8_t Txdata= 0x9f; //Send command for Reading manufacture ID [ (MID7-MID0) , (ID15 - ID8) ,(ID7 - ID0)]
//Expected result should be [MID7-MID0 -> BA], [ID15 - ID8 -> 60] [ID7 - ID0 -> 15]
CS_LOW();
HAL_SPI_Transmit(&ZD25WQ16_SPI, &Txdata, 1, 1000);
 HAL_SPI_Receive(&ZD25WQ16_SPI, Rxtdata, 3, 3000);
CS_HIGH();

}

Same thing I try to do with MSPM0G3507 MCU , I am getting only garbage value , even I check the clock  on oscilloscope that is getting fine , Below i attached the code for the same as well (first reset then Reading manufacture ID of NOR flash)

I am little bit confused about the driver library of MSPM0 MCU,I took the example code form the MSPM0 SDK for spi_fifo_multibyte and start my project over the same.

uint8_t Txdata[SPI_PACKET_SIZE] = {0x66,0x99}; // Reset command;

uint8_t Txdata1[2]= {0x9f};  //Send command for Reading manufacture ID 
uint8_t Rxtdata[3];

int main(void)
{
    SYSCFG_DL_init();

    /* Fill TX FIFO with data and transmit to SPI Peripheral */

     DL_SPI_fillTXFIFO8(SPI_0_INST, &Txdata[0], SPI_PACKET_SIZE);
     while (DL_SPI_isBusy(SPI_0_INST));
     
     /* Wait until all bytes have been transmitted and the TX FIFO is empty */
     DL_SPI_fillTXFIFO8(SPI_0_INST, &Txdata1[0], 1);
     while (DL_SPI_isBusy(SPI_0_INST));
 
 // Wait to receive the SPI data
     for (uint8_t i = 0; i < 3; i++) {
              Rxtdata[i] = DL_SPI_receiveDataBlocking8(SPI_0_INST);  //Expected result should be [MID7-MID0 -> BA], [ID15 - ID8 -> 60] [ID7 - ID0 -> 15]
          }
 
     
    while (1) {
    
          }
   
   }

apart from that one thing I could not understand the Chip select pin as I did the ST code , should I have to do the same manually or that is mux with the SPI pin??

Thanks & Regards 

Arjun singh

  • 1) I recommend you (continue to) use a GPIO as a Chip Select, since the MSPM0's built-in CS is (effectively) de-selected every time the SPI goes idle, something you don't have complete control over. (That's why you're using it on the STM32 as well.)

    2) The SPI always receives as many bytes as are transmitted. HAL_SPI_Transmit sends N bytes, then throws away the Rx bytes. I don't see a function in dl_spi.c that does this, i.e. the model is more like HAL_SPI_TransmitReceive(). For your purposes, you need to read the Rx bytes (2 for the reset, + one for the read-ID command) and throw them away yourself; then you can send three more (dummy) bytes to read out the ID bytes it sends back. (Also you need to toggle CS between the reset and read-ID.)

    3) The procedure you're using will work for (1+3) bytes, but doesn't scale, since the FIFO only has 4 entries. There are various methods you can use, but perhaps the simplest is to use DL_SPI_transmitDataBlocking8 instead of FillFIFO. 

    [Edit: The ID response is 3 bytes (I didn't read far enough down Fig 66). Also the device requires wiggling Chip Select between transactions.]

  • Thank you for your response ,

    I try the same as you mention above but I am not getting the appropriate result , please find the code below I attached and I request to add the line which that necessary to perform that task, once I able to read the manufacture ID of NOR flash then I able  to understand the flow SPI library and do further operation regarding the same.

         Txdata[0] = 0x66; // Enable reset command
         Txdata[1] = 0x99; // Reset command
    
         CS_LOW();
         DL_SPI_transmitDataBlocking8(SPI_0_INST, Txdata[0]);
         delay_cycles(1000);
         DL_SPI_transmitDataBlocking8(SPI_0_INST, Txdata[1]);
         delay_cycles(1000);
         CS_HIGH();
    
    
         Txdata[1] = 0x9f;  // uint8_t Txdata= 0x9f; //Send command for Reading manufacture ID [ (MID7-MID0) , (ID15 - ID8) ,(ID7 - ID0)]       //Expected result should be [MID7-MID0 -> BA], [ID15 - ID8 -> 60] [ID7 - ID0 -> 15]
         CS_LOW();
         DL_SPI_transmitDataBlocking8(SPI_0_INST, Txdata[1]);
         delay_cycles(1000);
             for (uint8_t i = 0; i < 4 ; i++)
             {
                 gRxPacket[i] = DL_SPI_receiveDataBlocking8(SPI_0_INST);
             }
         delay_cycles(3000);
         CS_HIGH();

     Thanks & regards 

    Arjun singh

  • 1) Each call to DL_SPI_transmitDataBlocking8 will result (eventually) in a byte in the Rx FIFO; those will stay there until you read them out, even if you don't want them. (After 4x transmissions, the Rx FIFO will overflow.)

    So a simple strategy is to match (follow) each call to DL_SPI_transmitDataBlocking8 with a call to DL_SPI_receiveDataBlocking8, the result of which you can use or throw away. You can predict the contents of each Rx byte by following ZD25 data sheet Fig 66 vertically. This doesn't use much of the FIFOs, but it's very predictable. Since the Blocking functions wait for completion, you don't need those delay_cycles() calls.

    2) To receive a byte, you need to send a byte; for a receive-only sequence (as with your loop) you need to supply a sequence of so-called "dummy" bytes (the value doesn't matter). HAL_SPI__Receive did this for you, but here you have to do it yourself. 

    So in your receive-results loop, match (precede) each call to DL_SPI_receiveDataBlocking8 with a call resembling

    > DL_SPI_transmitDataBlocking8(SPI_0_INST, 0xFF); // Dummy byte to get result back

    You'll probably save some typing by packaging the two calls in a separate function.