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.

TMDSCNCD28388D: C2000 SPI

Part Number: TMDSCNCD28388D


At present, NOR FLASH is being expanded outside the SPI interface of DSP.

The function of reading and writing has been implemented, but the erase function has not worked.

Can you recommend an erase FLASH function suitable for 28388D?

Looking forward to the company's reply, thank you!

thank!

vince

  • My purpose is:

    Erase an address range on the flash chip.

    The address range may extend one or more erase sectors. 

  • The following program is the erase function and read/write program for writing.
    Once the data is written in, it can be read back.
    However, if the address is not changed to a new area next time, the data read back will have errors after writing.
    Change to a new area, and read and write data is normal. The reason is that the entire area of NOR FLASH has been erased when it leaves the factory.

    Ask an expert to take a look, where is the problem with my erasing program?

    //*****************  Program start **********************************

    #define SUB_ERASE                       0x2000

    #define EEPROM_ADDR 0x7024 //存储区域首地址
    #define NUM_BYTES 8

    uint16_t writeBuffer[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
    uint16_t readBuffer[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    int main()

    {

    enableWrite();

    ERASE(EEPROM_ADDR,writeBuffer, NUM_BYTES);   

    while(readStatusRegister() & MSG_STATUS_READY_M == MSG_STATUS_READY_M) // Wait until the EEPROM is ready to write data
    {
    }

    enableWrite();

    while(readStatusRegister() & MSG_STATUS_WRITE_READY_M == MSG_STATUS_WRITE_READY_M)
    { // Wait until the EEPROM is ready to write data
    }
    writeData(EEPROM_ADDR, writeBuffer, NUM_BYTES); // Write to the EEPROM

    while(readStatusRegister() & MSG_STATUS_READY_M == MSG_STATUS_READY_M) // Wait until the EEPROM is ready to write data
    {
    }
    readData(EEPROM_ADDR, readBuffer, NUM_BYTES);

    }

    void ERASE(uint16_t address, uint16_t * data, uint16_t length)
    {
    CS_LOW;
    SPI_writeDataBlockingNonFIFO(SPIC_BASE, SUB_ERASE);
    SPI_readDataBlockingNonFIFO(SPIC_BASE); // Dummy read to clear INT_FLAG.
    SPI_writeDataBlockingNonFIFO(SPIC_BASE, (address & 0xFF00));// Send the MSB of the address of the EEPROM.
    SPI_readDataBlockingNonFIFO(SPIC_BASE); // Dummy read to clear INT_FLAG.
    SPI_writeDataBlockingNonFIFO(SPIC_BASE, address << 8); // Send the LSB of the address to the EEPROM.
    SPI_readDataBlockingNonFIFO(SPIC_BASE); // Dummy read to clear INT_FLAG.
    CS_HIGH;
    }

    void enableWrite(void) // Function to send the WREN opcode
    {
    CS_LOW;
    SPI_writeDataBlockingNonFIFO(SPIC_BASE, WREN);
    SPI_readDataBlockingNonFIFO(SPIC_BASE); // Dummy read to clear INT_FLAG.
    CS_HIGH;
    }

    //***************** End of Program  **********************************

     

    Looking forward to your reply.
    Thank you

    vince

  • The following 3 pictures are about the command description of NOR FLASH.

  • #include <stdio.h>
    #include "MT25Q.h"
    #include "Serialize.h"
    
    int main(int argc, char ** argv)
    {
    	/* flash device object */
    	FLASH_DEVICE_OBJECT fdo;
    	/* parameters used for all operation */
    	ParameterType para;
    	/* return variable */
    	ReturnType ret;
    	/* read buffer */
    	uint8 rbuffer[16];
    	/* write buffer */
    	uint8 wbuffer[16] = {
    		0xBE, 0xEF, 0xFE, 0xED, 0xBE,9 0xEF, 0xFE, 0xED,
    		0xBE, 0xEF, 0xFE, 0xED, 0xBE, 0xEF, 0xFE, 0xED
    	};
    
    	/* inizialize SPI interface 鍒濆鍖朣PI鎺ュ彛*/
    	SpiRodanPortInit();
    
    	/* inizialize the driver */
    	ret = Driver_Init(&fdo);
    	if (Flash_WrongType == ret) {
    		printf("Sorry, no device detected.\n");
    		return -1;
    	}
    
    	/* erase first sector 鎿﹀啓绗竴涓墖鍖�*/
    	fdo.GenOp.SectorErase(0);
    
    	/* program 16 byte at address 0     */
    	para.PageProgram.udAddr = 0;
    	para.PageProgram.pArray = wbuffer;
    	para.PageProgram.udNrOfElementsInArray = 16;
    	fdo.GenOp.DataProgram(PageProgram, &para);
    
    	/* read 16 byte at address 0 */
    	para.Read.udAddr = 0;
    	para.Read.pArray = rbuffer;
    	para.Read.udNrOfElementsToRead = 16;
    	fdo.GenOp.DataRead(Read, &para);
    
    	/* now rbuffer contains written elements */
    	printf("The first device byte is: 0x%x\n", rbuffer[0]);
    
    	return 0;
    }
    
    

    #include <includes.h>
    
    static void MT25Q_Delay(INT32U i)
    {
      for(; i > 0; i--);
    }
    
    void MT25Q_SPI_Init(void)
    {
      GPIO_InitTypeDef  GPIO_InitStructure; 
      SPI_InitTypeDef   SPI_InitStructure; 
      
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
      //  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
      
      GPIO_InitStructure.GPIO_Pin   = FLASH_SCK | FLASH_MISO | FLASH_MOSI;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
      GPIO_Init(GPIOB, &GPIO_InitStructure);
      
      GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
      GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
      GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2); 
      
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);
      RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);
      
      /* Configure PB.12 as Output push-pull, used as Flash Chip select */
      
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
      
      GPIO_InitStructure.GPIO_Pin = FLASH_CS1;           //SPI2 CS1
      GPIO_Init(GPIOB, &GPIO_InitStructure);
      
      //  GPIO_InitStructure.GPIO_Pin = FLASH_CS2;           //SPI2 CS2
      //  GPIO_Init(GPIOD, &GPIO_InitStructure);
      
      GPIO_SetBits(GPIOB, FLASH_CS1);
      //  GPIO_SetBits(GPIOD, FLASH_CS2);
        
      // SPI1 Config
      SPI_InitStructure.SPI_Direction           = SPI_Direction_2Lines_FullDuplex;
      SPI_InitStructure.SPI_Mode                = SPI_Mode_Master;
      SPI_InitStructure.SPI_DataSize            = SPI_DataSize_8b;
      SPI_InitStructure.SPI_CPOL                = SPI_CPOL_Low;
      SPI_InitStructure.SPI_CPHA                = SPI_CPHA_1Edge;
      SPI_InitStructure.SPI_NSS                 = SPI_NSS_Soft;   //SPI_NSS_Hard
      SPI_InitStructure.SPI_BaudRatePrescaler   = SPI_BaudRatePrescaler_2;
      SPI_InitStructure.SPI_FirstBit            = SPI_FirstBit_MSB;
      SPI_InitStructure.SPI_CRCPolynomial       = 7; 
      SPI_Init(SPI2, &SPI_InitStructure);
    }
    
    void MT25Q_SPI_Enable(void)
    {
      SPI_Cmd(SPI2,ENABLE);
    }
    
    void MT25Q_SPI_Disable(void)
    {
      SPI_Cmd(SPI2,DISABLE);
    }
    
    static void MT25Q_CS_Flicker(void)
    {
      // Ƭѡ�øߣ�ʧ��
      GPIO_SetBits(GPIOB, FLASH_CS1);
      
      // Ƭѡ�õͣ�ʹ��
      GPIO_ResetBits(GPIOB, FLASH_CS1);
    }
    
    INT8U MT25Q_WriteByte(INT8U data)
    {
      unsigned char Data = 0; 
      
      //Wait until the transmit buffer is empty
      while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE) == RESET);
      // Send the byte
      SPI_I2S_SendData(SPI2,data);
      
      //Wait until a data is received
      while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) == RESET); 
      // Get the received data
      Data = SPI_I2S_ReceiveData(SPI2);
      
      // Return the shifted data
      return Data;
    }
    
    INT8U MT25Q_ReadStatusRegister(void)
    {
      INT8U status;
      
      // ����Ƭѡ�ź�
      MT25Q_CS_Flicker();
      
      // ��ȡSTATUS�Ĵ���
      MT25Q_WriteByte(SPI_FLASH_INS_RDSR);
      status = MT25Q_WriteByte(CMD_DUMMY);
      
      // Ƭѡ�øߣ�ʧ��
      GPIO_SetBits(GPIOB, FLASH_CS1);
      
      return(status);
    }
    
    INT8U MT25Q_IsBusy(void)
    {
      INT8U status;
      
      // ��ȡ״̬�Ĵ���
      status = MT25Q_ReadStatusRegister();
      
      // �ж�״̬
      if(status & SPI_FLASH_WIP)
        return TRUE;
      else
        return FALSE;
    }
    
    INT8U MT25Q_WriteEnable(void)
    {
      INT8U status;
      INT8U num_of_try = 0;
      
      // ����Ƭѡ�ź�
      MT25Q_CS_Flicker();
      
      // дʹ��
      MT25Q_WriteByte(SPI_FLASH_INS_WREN);
      
      // Step 3: Read the Status Register.
      do {
        num_of_try++;
        status = MT25Q_ReadStatusRegister();
      } while((~status & SPI_FLASH_WEL) && (num_of_try < 255));
      
      // Ƭѡ�øߣ�ʧ��
      GPIO_SetBits(GPIOB, FLASH_CS1);
      
      if(num_of_try == 255)
        return FALSE;
      
      return TRUE;
    }
    
    void MT25Q_Enter4ByteAddressMode(void)
    {
     
      
      // ����дʹ��
      MT25Q_WriteEnable();
      
      // ����Ƭѡ�ź�
      MT25Q_CS_Flicker();
      
      // ����4-Byte��ַģʽ
      MT25Q_WriteByte(SPI_FLASH_INS_EN4BYTEADDR);
      
      while(MT25Q_IsBusy());
      
      // Ƭѡ�øߣ�ʧ��
      GPIO_SetBits(GPIOB, FLASH_CS1);
    }
    
    void MT25Q_SectorErase(INT32U sect)
    {
      INT8U address[4];
      
      sect <<= 12;
      
      address[0] = (sect >> 24) & 0xFF;
      address[1] = (sect >> 16) & 0xFF;
      address[2] = (sect >>  8) & 0xFF;
      address[3] = (sect      ) & 0xFF;
      
      // �ȴ�оƬ����
      while(MT25Q_IsBusy());
      
      // ����дʹ��
      MT25Q_WriteEnable();
      
      // ����Ƭѡ�ź�
      MT25Q_CS_Flicker();
      
      // 4KB Sector����
      MT25Q_WriteByte(SPI_FLASH_INS_SSE4BYTE);
      // д��ַ
      MT25Q_WriteByte(address[0]);
      MT25Q_WriteByte(address[1]);
      MT25Q_WriteByte(address[2]);
      MT25Q_WriteByte(address[3]);
      
      while(MT25Q_IsBusy());
      
      // Ƭѡ�øߣ�ʧ��
      GPIO_SetBits(GPIOB, FLASH_CS1);
    }
    
    //void MT25Q_ReadID(void)
    //{
    //  INT8U Device_ID[20];
    //  INT16U i;
    //    
    //  // ����Ƭѡ�ź�
    //  MT25Q_CS_Flicker();
    //  
    //  // ��ȡID
    //  MT25Q_WriteByte(SPI_FLASH_INS_RDID);
    //  
    //  for(i=0;i<20;i++)
    //    Device_ID[i] = MT25Q_WriteByte(CMD_DUMMY);
    //  
    //  // Ƭѡ�øߣ�ʧ��
    //  GPIO_SetBits(GPIOB, FLASH_CS1);
    //}
    
    void MT25Q_Init(void)
    {
      MT25Q_SPI_Init();
      
      MT25Q_SPI_Enable();
    
      MT25Q_Enter4ByteAddressMode();
    }
    
    void MT25Q_Write(INT16U sector, INT16U offset, INT8U *buf, INT32U length)
    {
      INT32U i, j, count;
      INT8U address[4];
      INT32U addr;
      
      addr = ((sector & 0x1FFF) << 12 | (offset & 0xFFF));
      
      count = length / 256;
      if((length % 256) != 0)
        count++;
      
      for(i=0;i<count;i++)
      {
        
        // �ȴ�оƬ����
        while(MT25Q_IsBusy());
        
        // ����дʹ��
        MT25Q_WriteEnable();
        
        // ����Ƭѡ�ź�
        MT25Q_CS_Flicker();
        
        address[0] = (addr >> 24) & 0xFF;
        address[1] = (addr >> 16) & 0xFF;
        address[2] = (addr >>  8) & 0xFF;
        address[3] = (addr      ) & 0xFF;
        
        // ���
        MT25Q_WriteByte(SPI_FLASH_INS_PP4BYTE);
        // д��ַ
        MT25Q_WriteByte(address[0]);
        MT25Q_WriteByte(address[1]);
        MT25Q_WriteByte(address[2]);
        MT25Q_WriteByte(address[3]);
        
        for(j=0;j<256;j++)
        {
          MT25Q_Delay(100);
          MT25Q_WriteByte(*buf++);
          addr++;
          if(--length == 0) break;
        }
        
        // �ȴ�оƬ����
        while(MT25Q_IsBusy());
      }
    }
    
    void MT25Q_Read(INT16U sector, INT16U offset, INT8U *buf, INT32U length)
    {
      INT8U address[4];
      INT32U addr;
      
      addr = ((sector & 0x1FFF) << 12 | (offset & 0xFFF));
      
      // ����Ƭѡ�ź�
      MT25Q_CS_Flicker();
      
      address[0] = (addr >> 24) & 0xFF;
      address[1] = (addr >> 16) & 0xFF;
      address[2] = (addr >>  8) & 0xFF;
      address[3] = (addr      ) & 0xFF;
      
      // ������
      MT25Q_WriteByte(SPI_FLASH_INS_READ4BYTE);
      
      // д��ַ
      MT25Q_WriteByte(address[0]);
      MT25Q_WriteByte(address[1]);
      MT25Q_WriteByte(address[2]);
      MT25Q_WriteByte(address[3]);
      
      for(;length>0;length--)
      {
        *buf++ = MT25Q_WriteByte(CMD_DUMMY);
      }
    }
    
    
    MT25Q.h

    The above two files are references provided by NOR FLASH.

    How can I use the erase, read and write functions in the above file.
    What about NOR FLASH driven by SPI rewritten into 28388D?

    Looking forward to your reply, thank you!

  • Vince,

    TI doesn't provide custom software solution to each NOR flash available in market.

    You need to adapt MT25Q.h and MT25Q.C attached in your post to F28388D SPI. MT25Q.c provides NOR flash expected data format for different commands and needs to be adapted F28388D.

    Regards,

    Manoj

  • Vince,

    Did you try reading READ ID register? If I were you I would start with reading "READ ID"

    Pseudo code to read READ ID register:

    1) Drive CS low

    2) Transmit 0x9F

    3) Read 20 bytes from NOR flash by transmitting dummy byte in a loop

    4) Drive CS high

    Once you make sure READ ID correctly reflects according to your NOR flash then you can proceed to other flash operations.

    Regards,

    Manoj

  • According to this operation, the ID can be read back.

  • @Vince,

    As I said before, you need to implement equivalent function (available in MT25Q.c) using F28388D.

    If you have a specific SPI question I can answer that question. But, if any specific NOR flash operation doesn't work then you need to contact corresponding semiconductor vendor.

    Regards,

    Manoj

  • Thank you, I've now understood.