新闻  |   论坛  |   博客  |   在线研讨会
TMS320C6748_SPI_FLAH例程解析
tronlong | 2014-07-07 17:32:49    阅读:3401   发布文章

广州创龙电子基于TMS320C6748开发的SPI_FLAH程序,此程序的作用是实现SPI FLASH设备的数据读写功能,此设备挂载在SPI1总线,按照工程导入步骤加载SPI_FLASH.out文件,将开发板的UART2和PC机连接,打开ZOC串口调试软件,设置好波特率为115200,数据位8位,停止位1位,检验位无,流控制无,然后点击程序运行按钮。

演示现象

(1)        ZOC串口调试终端会打印出信息:


       此程序先提示是否擦除SPI FLASH,输入y擦除SPI FLASH上的数据,然后对比写入和读出的数据,根据结果判断SPI FLASH设备读写是否成功。


代码解析:


/*******************************************/
/*                                                                          */
/*              核心板及底板SPI FLASH读写 测试            */
/*                                                                          */
/*              2014年5月19日                                      */
/*                                                                          */
/*******************************************/
#include "main.h"
#include <string.h>
#include "soc_C6748.h"
#include "hw_psc_C6748.h"
#include "evmC6748.h"
#include "uart.h"
#include "spi.h"
#include "psc.h"
#include "interrupt.h"
#include "uartStdio.h"


/**************************************
**                       宏定义
**************************************/
/* value to configure SMIO,SOMI,CLK and CS pin as functional pin */
#define SIMO_SOMI_CLK_CS        0x00000E01
#define CHAR_LENGTH             0x8


/* flash address where data will be written and read */
#define SPI_FLASH_ADDR_MSB1     0x0A
#define SPI_FLASH_ADDR_MSB0     0x00
#define SPI_FLASH_ADDR_LSB      0x00


/* sector erase command */
#define SPI_FLASH_SECTOR_ERASE  0xD8


/* page program command */
#define SPI_FLASH_PAGE_WRITE    0x02


/* status register read command */
#define SPI_FLASH_STATUS_RX     0x05


/* write enable command */
#define SPI_FLASH_WRITE_EN      0x06


/* flash data read command */
#define SPI_FLASH_READ          0x03


/* flash data read */
#define WRITE_IN_PROGRESS       0x01


/********************************************
**                      函数原型声明
********************************************/
static void SPIConfigDataFmtReg(unsigned int dataFormat);
static void ReadFromFlash(void);
static void IsFlashBusy(void);
static void WritetoFlash(void);
static void WriteEnable(void);
static void SpiTransfer(void);
static void SectorErase(void);
static int  VerifyData(void);
static void StatusGet(void);
static void SetUpInt(void);
static void SetUpSPI(void);
void SPIIsr(void);


/**********************************************
**                      变量定义
**********************************************/
volatile unsigned int flag = 1;
unsigned int tx_len;
unsigned int rx_len;
unsigned char vrf_data[260];
unsigned char tx_data[260];
unsigned char rx_data[260];
unsigned char *p_tx;
unsigned char *p_rx;


/*****************************************
**                      函数定义
*****************************************/
int main(void)
{
int result = 0;
char choice ;


    /* Waking up the SPI1 instance. */
    PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_SPI1, PSC_POWERDOMAIN_ALWAYS_ON,
                     PSC_MDCTL_NEXT_ENABLE);


    /* Initializing the UART instance for serial communication. */
    UARTStdioInit();


    /* Setting the UART Receiver Trigger Level*/
    UARTFIFOLevelSet(SOC_UART_2_REGS, UART_RX_TRIG_LEVEL_1);
    UARTPuts("\r\n ============Test Start===========.\r\n", -1);
    UARTPuts("Welcome to StarterWare SPI FLASH application.\r\n\r\n", -1);
    UARTPuts("Here the SPI controller on the SoC communicates with", -1);
    UARTPuts(" the SPI Flash present on the SoM.\r\n\r\n", -1);
    /* Performing the Pin Multiplexing for SPI1. */
    SPIPinMuxSetup(1);


    /*
    ** Using the Chip Select(CS) 0 pin of SPI1 to communicate with SPI Flash.
    ** AM1808 EVM mandates us to do so.
    */
    SPI1CSPinMuxSetup(0);


    /* Enable use of SPI1 interrupts. */
    SetUpInt();


    /* Configuring and enabling the SPI1 instance. */
    SetUpSPI();


    /* Preparing the Flash for a Write. */
    WriteEnable();

UARTPuts("Do you want to erase a sector of the flash before writing to it ?.", -1);
    UARTPuts("\r\nInput y(Y)/n(N) to proceed.\r\n", -1);


    choice = UARTGetc();
    UARTPutc(choice);


    if(('y' == choice) || ('Y' == choice))
    {
        /* Erasing a Sector of the Flash. */
        SectorErase();
    }


    WriteEnable();


    /* Programming the necessary data to Flash. */
    WritetoFlash();


    /* Reading from the required location from Flash. */
    ReadFromFlash();


    /* Comparing the written and read data. */


    result = VerifyData();


    UARTPuts("\r\n ============Test End===========.\r\n", -1);
    while(1);
}


/*
** Reads the status register of m25p80 flash
**
*/
static void StatusGet(void)
{
    tx_data[0] = SPI_FLASH_STATUS_RX;
    tx_len = rx_len = 2;
    SPIDat1Config(SOC_SPI_1_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), 0x1);
    SpiTransfer();
}


/*
** Enables write to m25p80 flash
**
*/
static void WriteEnable(void)
{
    tx_data[0] = SPI_FLASH_WRITE_EN;
    tx_len = rx_len = 1;
    SPIDat1Config(SOC_SPI_1_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), 0x1);
    SpiTransfer();
}


/*
** It polls for write in progress bit(wip)in status register of m25p80 flash
**
*/
static void IsFlashBusy(void)
{
    do{
         StatusGet();


      }while(rx_data[1] & WRITE_IN_PROGRESS);
}


/*
** Set the all bits to 1 in chosen sector
**
*/
static void SectorErase(void)
{
    tx_data[0] =  SPI_FLASH_SECTOR_ERASE;
    tx_data[1] =  SPI_FLASH_ADDR_MSB1;
    tx_data[2] =  SPI_FLASH_ADDR_MSB0;
    tx_data[3] =  SPI_FLASH_ADDR_LSB;


    tx_len = rx_len = 4;
    SPIDat1Config(SOC_SPI_1_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), 0x1);
    SpiTransfer();


    IsFlashBusy();
}


/*
** Writes 256 bytes of data to desired memory address
**
*/
static void WritetoFlash(void)
{
    unsigned int index;


    tx_data[0] =  SPI_FLASH_PAGE_WRITE;
    tx_data[1] =  SPI_FLASH_ADDR_MSB1;
    tx_data[2] =  SPI_FLASH_ADDR_MSB0;
    tx_data[3] =  SPI_FLASH_ADDR_LSB;


    /* Populate the data to be written to the flash */
    for (index = 4; index < 260; index++)
    {
        tx_data[index] =  index;
    }


    for(index = 4; index < 260; index++)
    {
         vrf_data[index] = index;
    }


    tx_len = rx_len = index;
    SPIDat1Config(SOC_SPI_1_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), 0x1);
    SpiTransfer();


    IsFlashBusy();
}


/*
** Reads the data from addressed memory of flash
**
*/
static void ReadFromFlash(void)
{
    unsigned int index;


    tx_data[0] =  SPI_FLASH_READ;
    tx_data[1] =  SPI_FLASH_ADDR_MSB1;
    tx_data[2] =  SPI_FLASH_ADDR_MSB0;
    tx_data[3] =  SPI_FLASH_ADDR_LSB;


    /* Reset the data in the tx buffer */
    for (index = 4; index < 260; index++)
    {
        tx_data[index] =  0;
    }


    tx_len = rx_len = index;
    SPIDat1Config(SOC_SPI_1_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), 0x1);
    SpiTransfer();
}


/*
** Verfies the data written to flash and read from the flash of same address
**
*/
/*******************************************/
/*                                                                          */
/*    校验写入到SPI FLASH中的数据与相同地址读出的是否一致  */
/*                                                                          */
/*   返回值      = 1: 一致                                          */
/*           = 0: 不一致                                              */
/*                                                                          */
/*******************************************/
static int VerifyData(void)
{
    unsigned int index;


    for(index = 4; index < 260; index++)
    {
        if(vrf_data[index] != rx_data[index])
        {
            UARTPuts("\r\n", -1);
            UARTPuts("VerifyData: Comparing the data written to and read", -1);
            UARTPuts(" from Flash.\r\nThe two data blocks are unequal.", -1);
            UARTPuts(" Mismatch found at index ", -1);
            UARTPutNum((int)index - 3);
            UARTPuts("\r\n", -1);
UARTPuts("Verify Failed.\r\n", -1);
            return 0;
        }
    }


    if (index == 260)
    {
        UARTPuts("\r\nThe data in the Flash and the one written ", -1);
        UARTPuts("to it are equal.\r\n", -1);
UARTPuts("Verify successfully.\r\n", -1);
        return 1;
    }
}


/*******************************************/
/*                                                                          */
/*              配置DSP中断控制器 产生SPI中断             */
/*                                                                          */
/*******************************************/
static void SetUpInt(void)
{


// Initialize the DSP interrupt controller
IntDSPINTCInit();


// Register the ISR in the vector table
IntRegister(C674X_MASK_INT4, SPIIsr);


// Map system interrupt to the DSP maskable interrupt
IntEventMap(C674X_MASK_INT4, SYS_INT_SPI1_INT);


// Enable the DSP maskable interrupt
IntEnable(C674X_MASK_INT4);


// Enable DSP interrupts globally
IntGlobalEnable();


}


/*******************************************/
/*                                                                          */
/*              配置SPI控制器                                       */
/*                                                                          */
/*******************************************/
static void SetUpSPI(void)
{
    unsigned char cs  = 0x01;
    unsigned char dcs = 0x01;
    unsigned int  val = SIMO_SOMI_CLK_CS;


    SPIReset(SOC_SPI_1_REGS);


    SPIOutOfReset(SOC_SPI_1_REGS);


    SPIModeConfigure(SOC_SPI_1_REGS, SPI_MASTER_MODE);


    SPIClkConfigure(SOC_SPI_1_REGS, 150000000, 20000000, SPI_DATA_FORMAT0);


    SPIPinControl(SOC_SPI_1_REGS, 0, 0, &val);


    SPIDefaultCSSet(SOC_SPI_1_REGS, dcs);


    /* Configures SPI Data Format Register */
    SPIConfigDataFmtReg(SPI_DATA_FORMAT0);


     /* Selects the SPI Data format register to used and Sets CSHOLD
      * to assert CS pin(line)
      */
    SPIDat1Config(SOC_SPI_1_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), cs);


     /* map interrupts to interrupt line INT1 */
    SPIIntLevelSet(SOC_SPI_1_REGS, SPI_RECV_INTLVL | SPI_TRANSMIT_INTLVL);


    /* Enable SPI communication */
    SPIEnable(SOC_SPI_1_REGS);
}
/*******************************************/
/*                                                                          */
/*              配置SPI数据格式寄存器                          */
/*                                                                          */
/*******************************************/
static void SPIConfigDataFmtReg(unsigned int dataFormat)
{
    /* Configures the polarity and phase of SPI clock */
    SPIConfigClkFormat(SOC_SPI_1_REGS,
                       (SPI_CLK_POL_HIGH | SPI_CLK_INPHASE),
                       dataFormat);


    /* Configures SPI to transmit MSB bit First during data transfer */
    SPIShiftMsbFirst(SOC_SPI_1_REGS, dataFormat);


    /* Sets the Charcter length */
    SPICharLengthSet(SOC_SPI_1_REGS, CHAR_LENGTH, dataFormat);
}


/****************************************/
/*                                                                    */
/*              使能 SPI发送和接收中断                    */
/*                                                                     */
/****************************************/
static void  SpiTransfer(void)
{
    p_tx = &tx_data[0];
    p_rx = &rx_data[0];
    SPIIntEnable(SOC_SPI_1_REGS, (SPI_RECV_INT | SPI_TRANSMIT_INT));
    while(flag);
    flag = 1;
    /* Deasserts the CS pin(line) */
    SPIDat1Config(SOC_SPI_1_REGS, SPI_DATA_FORMAT0, 0x1);
}


/*******************************************/
/*                                                                          */
/*              SPI中断处理函数                                    */
/*                                                                          */
/*******************************************/
void SPIIsr(void)
{
    unsigned int intCode = 0;
    IntEventClear(SYS_INT_SPI1_INT);
    intCode = SPIInterruptVectorGet(SOC_SPI_1_REGS);


    while (intCode)
    {
        if(intCode == SPI_TX_BUF_EMPTY)
        {
            tx_len--;
            SPITransmitData1(SOC_SPI_1_REGS, *p_tx);
            p_tx++;
            if (!tx_len)
            {
                SPIIntDisable(SOC_SPI_1_REGS, SPI_TRANSMIT_INT);
            }
        }


        if(intCode == SPI_RECV_FULL)
        {
            rx_len--;
            *p_rx = (char)SPIDataReceive(SOC_SPI_1_REGS);
            p_rx++;
            if (!rx_len)
            {
                flag = 0;
                SPIIntDisable(SOC_SPI_1_REGS, SPI_RECV_INT);
            }
        }


        intCode = SPIInterruptVectorGet(SOC_SPI_1_REGS);
    }
}


/******* End of file **************/


详细代码下载地址:http://download.csdn.net/detail/gzchuanglong/7581033

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客