⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi_flash.c

📁 Freescale MCF5445evb 参考测试代码
💻 C
字号:
/*! * \file    spi_flash.c * \brief   Driver for a generic SPI Flash device * \version $Revision: 1.1 $ * \author  Michael Norman */ #include "common.h"#include "spi_flash.h"#include "dspi.h"/********************************************************************//*! SPI Flash Device ID data */SPI_FLASH_DEVICE_ID dev_id;/*! SPI Flash Device Info */SPI_DEVICE spi_flash = {    .baud           = 20000000,    .mode           = SPI_MODE_0,    .fbit           = SPI_FBIT_MSB,    .cs             = 1,    .cs_is          = 1,    .cs_muxed       = 0,    .frame_size     = 8,    .delay_csclk    = 10,    .delay_clkcs    = 10,    .delay_cscs     = 10,};/********************************************************************//*! * Initialize the SPI Flash device * \return  Zero for success; non-zero otherwise */intspi_flash_init (void){    spi_master_init();    spi_master_device_init(&spi_flash);    spi_flash_read_id();    return 0;}/********************************************************************//*! * Write Enable * \return  Zero for success; non-zero otherwise */static intspi_flash_write_enable (void){    uint8 data;    data = SPIFLASH_WREN;    spi_master_write(&spi_flash, &data, sizeof(data));    data = spi_flash_read_sr();    return !(data & SPIFLASH_SR_WEL);}    /********************************************************************//*! * Write Disable * \return  Zero for success; non-zero otherwise */static intspi_flash_write_disable (void){    uint8 data;    data = SPIFLASH_WRDI;    spi_master_write(&spi_flash, &data, sizeof(data));    data = spi_flash_read_sr();    return (data & SPIFLASH_SR_WEL);}/********************************************************************//*! * Read ID * \return  Pointer to updated device ID  */SPI_FLASH_DEVICE_ID*spi_flash_read_id (void){    int i;    uint8 data[4];    data[0] = SPIFLASH_RDID;    spi_master_write_read(&spi_flash, data, data, sizeof(data));        dev_id.manuf_id = data[1];    dev_id.mem_type = data[2];    dev_id.mem_cap  = data[3];    return &dev_id;}/********************************************************************//*! * Read Status Register * \return  status register contents */uint8spi_flash_read_sr (void){    uint8 data[2];    data[0] = SPIFLASH_RDSR;    spi_master_write_read(&spi_flash, data, data, sizeof(data));    return data[1];}/********************************************************************//*! * Write Status Register * \param   sr  Data to be written to status register * \return  Zero for success; non-zero otherwise */intspi_flash_write_sr (uint8 sr){    uint8 data[2];    data[0] = SPIFLASH_WRSR;    data[1] = sr;    return spi_master_write(&spi_flash, data, sizeof(data));}/********************************************************************//*! * Read Data Bytes * \param   address Address from which to begin reading * \param   length  Number of bytes to read * \param   buffer  Buffer where received data will be stored * \return  Zero for success; non-zero otherwise */intspi_flash_read (ADDRESS address, int length, uint8 *buffer){    uint8 data[4];    SPI_MSG_CHAIN chain;    SPI_MSG_LINK link0, link1;        data[0] = SPIFLASH_READ;    data[1] = (address & 0x00FF0000) >> 16;    data[2] = (address & 0x0000FF00) >> 8;    data[3] = (address & 0x000000FF);        /* Build a message chain */    memset(&chain, 0, sizeof(SPI_MSG_CHAIN));    chain.device    = &spi_flash;    chain.link      = &link0;    memset(&link0, 0, sizeof(SPI_MSG_LINK));    link0.tx_buf    = data;    link0.rx_buf    = NULL;    link0.length    = sizeof(data);    link0.next      = &link1;    memset(&link1, 0, sizeof(SPI_MSG_LINK));    link1.tx_buf    = NULL;    link1.rx_buf    = buffer;    link1.length    = length;    link1.next      = NULL;        return spi_master_transfer(&chain, TRUE);}/********************************************************************//*! * Read Data Bytes (at higher speed) * \param   address Address from which to begin reading * \param   length  Number of bytes to read * \param   buffer  Buffer where received data will be stored * \return  Zero for success; non-zero otherwise */intspi_flash_fast_read (ADDRESS address, int length, uint8 *buffer){    uint8 data[5];    SPI_MSG_CHAIN chain;    SPI_MSG_LINK link0, link1;        data[0] = SPIFLASH_FAST_READ;    data[1] = (address & 0x00FF0000) >> 16;    data[2] = (address & 0x0000FF00) >> 8;    data[3] = (address & 0x000000FF);    data[4] = 0;    /* Dummy Byte */        /* Build a message chain */    memset(&chain, 0, sizeof(SPI_MSG_CHAIN));    chain.device    = &spi_flash;    chain.link      = &link0;    memset(&link0, 0, sizeof(SPI_MSG_LINK));    link0.tx_buf    = data;    link0.rx_buf    = NULL;    link0.length    = sizeof(data);    link0.next      = &link1;    memset(&link1, 0, sizeof(SPI_MSG_LINK));    link1.tx_buf    = NULL;    link1.rx_buf    = buffer;    link1.length    = length;    link1.next      = NULL;    return spi_master_transfer(&chain, TRUE);}/********************************************************************//*! * Page Program * \param   address Address at which to begin programming * \param   length  Number of bytes to program (<= 256) * \param   buffer  Pointer to data to be programmed * \return  Zero for success; non-zero otherwise */intspi_flash_page_program (ADDRESS address, int length, uint8 *buffer){    int i;    uint8 data[4];    SPI_MSG_CHAIN chain;    SPI_MSG_LINK link0, link1;        data[0] = SPIFLASH_PP;    data[1] = (address & 0x00FF0000) >> 16;    data[2] = (address & 0x0000FF00) >> 8;    data[3] = (address & 0x000000FF);        /* Build a message chain */    memset(&chain, 0, sizeof(SPI_MSG_CHAIN));    chain.device    = &spi_flash;    chain.link      = &link0;    memset(&link0, 0, sizeof(SPI_MSG_LINK));    link0.tx_buf    = data;    link0.rx_buf    = NULL;    link0.length    = sizeof(data);    link0.next      = &link1;    memset(&link1, 0, sizeof(SPI_MSG_LINK));    link1.tx_buf    = buffer;    link1.rx_buf    = NULL;    link1.length    = length;    link1.next      = NULL;    if (spi_master_transfer(&chain, TRUE))        return -1;        for (i = 10000000; i > 0; i--)    {        data[0] = spi_flash_read_sr();        if (!(data[0] & SPIFLASH_SR_WIP))            break;    }    return !i;}/********************************************************************//*! * Sector Erase * \param   address Address at which to begin programming * \return  Zero for success; non-zero otherwise */intspi_flash_sector_erase (ADDRESS address){    int i;    uint8 data[4];    data[0] = SPIFLASH_SE;    data[1] = (address & 0x00FF0000) >> 16;    data[2] = (address & 0x0000FF00) >> 8;    data[3] = (address & 0x000000FF);        if (spi_master_write(&spi_flash, data, sizeof(data)))        return -1;        for (i = 10000000; i > 0; i--)    {        data[0] = spi_flash_read_sr();        if (!(data[0] & SPIFLASH_SR_WIP))            break;    }        return !i;}/********************************************************************//*! * Bulk Erase * \return  Zero for success; non-zero otherwise */intspi_flash_bulk_erase (void){    uint8 data[1];    data[0] = SPIFLASH_BE;    return spi_master_write(&spi_flash, data, sizeof(data));}/********************************************************************//*! * Enter Deep Power-Down * \return  Zero for success; non-zero otherwise */intspi_flash_power_down (void){    uint8 data[1];    data[0] = SPIFLASH_DP;    return spi_master_write(&spi_flash, data, sizeof(data));}/********************************************************************//*! * Wake up from Deep Power-Down  * \return  Zero for success; non-zero otherwise */intspi_flash_wake_up (void){    uint8 data[1];    data[0] = SPIFLASH_RES;    return spi_master_write(&spi_flash, data, sizeof(data));}/********************************************************************//*! * Erase some flash * \param   start   Start address * \param   bytes   Bytes to erase * \param   print   Print progress? * \return  Zero for success; non-zero otherwise */intspi_flash_erase(ADDRESS start, int bytes, int print){       int i, ebytes = 0;        if (bytes == 0)        return 0;        for (i = 0; i < SPIFLASH_SECTORS; i++)    {        if (start >= (ADDRESS)SOFFSET(i) &&            start <= (ADDRESS)(SOFFSET(i) + (SSIZE(i) - 1)))            break;    }    ASSERT(i != SPIFLASH_SECTORS);        while (ebytes < bytes)    {        if (print)            out_char('.');                if (spi_flash_write_enable())            return -1;                if (spi_flash_sector_erase(SOFFSET(i)))            return -1;                ebytes += SSIZE(i);        i++;    }        if (print)    {        out_char(0x0D);        out_char(0x0A);    }        return 0;} /********************************************************************//*! * Program some flash * \param   dest    Start address in SPI flash * \param   source  Pointer to data to be programmed * \param   bytes   Bytes to program * \param   erase   Erase first? * \param   print   Print progress? * \return  Zero for success; non-zero otherwise */intspi_flash_program(ADDRESS dest, ADDRESS source, int bytes, int erase, int print){    int i, b, first, hashi=1;    uint8 *src, *dst;    char hash[5];        hash[0]=8;  /* Backspace */    hash[1]=124;/* "|" */    hash[2]=47; /* "/" */    hash[3]=45; /* "-" */    hash[4]=92; /* "\" */    src = (uint8 *)source;    dst = (uint8 *)dest;    /* Erase device if necessary */    if (erase)        if (spi_flash_erase(dest, bytes, print))            return -1;        for (i = 0; i < SPIFLASH_PAGES; i++)    {        if (dest >= (ADDRESS)POFFSET(i) &&            dest <= (ADDRESS)(POFFSET(i) + (PSIZE(i) - 1)))            break;    }    ASSERT(i != SPIFLASH_PAGES);    /* Handle case where start address isn't start of page */    if (dest & (PSIZE(i) - 1))    {        b = PSIZE(i) - (dest & (PSIZE(i) - 1));                if (spi_flash_write_enable())            return -1;                if (spi_flash_page_program((ADDRESS)dst, b, src))            return -1;                bytes -= b; dst += b; src += b;        i++;    }        while (bytes > 0)    {        if (bytes < PSIZE(i))            b = bytes;        else            b = PSIZE(i);                    if (spi_flash_write_enable())            return -1;                if (spi_flash_page_program((ADDRESS)dst, b, src))            return -1;                bytes -= b; dst += b; src += b;        i++;                if (print)        {            out_char(hash[0]);            out_char(hash[hashi]);            hashi++;            if (hashi == 5)                 hashi=1;                        }    }    return 0;}/********************************************************************//*! * Dump the contents of the SPI Flash * \param   addr    Start address  * \param   bytes   Bytes to dump */voidspi_flash_dump (ADDRESS addr, int bytes){    int i;    uint8 *data;    ADDRESS cur, end;        data = (uint8 *)malloc(bytes);    ASSERT(data);        spi_flash_read(addr, bytes, data);        printf("SPI Flash data:");    cur = addr;    for (i = 0; i < bytes; i++)    {        if (!(i % 16))            printf("\n%06X:  ",cur);        printf("%02X ", data[i]);        cur++;    }    printf("\n");    free(data);}/********************************************************************//*! * Dump the contents of the Device ID structure */voidspi_flash_dump_id (void){    int i;        printf("SPI Flash ID data\n------------------\n");    printf("  Manuf ID:   %02X\n", dev_id.manuf_id);    printf("  Mem Type:   %02X\n", dev_id.mem_type);    printf("  Capacity:   %02X\n", dev_id.mem_cap);    printf("\n");}/********************************************************************//*! * Test for correct SPI functionality */voidspi_flash_test (void){    int i;    uint8 data;    uint8 *buffer;    #if 0    printf("\nSPI Flash Test\n");        spi_flash_init();        data = spi_flash_read_sr();    printf("SR = %02X\n", data);        spi_flash_dump_id();    /* Save off data from first sector */    buffer = (uint8 *)malloc(256);    ASSERT(buffer);    spi_flash_read(0x00000000, 256, buffer);        /* Print the contents of the first sector */    spi_flash_dump(0x00000000, 256);        /* Erase the sector */    printf("Erasing first sector...");    spi_flash_sector_erase(0);    printf("done\n");    /* Print the contents of the first sector */    spi_flash_dump(0x00000000, 256);    /* Write the original data back */    spi_flash_program(0x00000000, (ADDRESS)buffer, 256, FALSE, FALSE);    /* Print the contents of the first sector */    spi_flash_dump(0x00000000, 256);#else    printf("\nSPI Flash Test\n");    spi_flash_init();        /* Print the device ID info */    spi_flash_dump_id();    /* Print the contents of the first sector */    spi_flash_dump(0x00000000, 256);        /* Erase the sector */    printf("Erasing first sector");    if (spi_flash_erase(0x00000000, 256, TRUE))        printf("failed\n");    else        printf("done\n");    /* Print the contents of the first sector */    spi_flash_dump(0x00000000, 256);        buffer = (uint8 *)malloc(256);    ASSERT(buffer);        /* Write some data to the flash */    for (i = 0; i < 256; i++)        buffer[i] = i;    if (spi_flash_program(0x00000000, (ADDRESS)buffer, 256, FALSE, FALSE))        printf("Program failed\n");    free(buffer);        /* Print the SR */    data = spi_flash_read_sr();    printf("SR = %02X\n", data);        /* Print the contents of the first sector */    spi_flash_dump(0x00000000, 256);#endif            return;}/********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -