打印
[AVR单片机]

关于AT45DB081的问题

[复制链接]
5010|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
crystaling1984|  楼主 | 2010-10-11 15:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我现在在改进一个设备,我们做的医疗器材,现在有台心血管功能仪,但是缺少存储数据及串口输出功能,现在我们需要加AT45DB081芯片来解决测试数据的存储、调用、删除等功能,我现在需要用C语言来完成这些功能,之前的设备的代码都有,使用KEIL51做的,现在哪位大哥能帮忙搞下这个存储及串口输出的C语言程序,以及这么加入到原来的程序中以实现整理功能。我是初学者,可是我们刚进公司,这个项目接手后我是头大了,我还在试用期,不想失去这份来之不易的工作,希望给位大侠能帮上忙,小弟感激不尽,可以加我qq45889779,也可以邮箱:crystaling1984@163.com

相关帖子

沙发
crystaling1984|  楼主 | 2010-10-12 08:45 | 只看该作者
没人解决啊!高手呢?出来帮帮小弟吧!

使用特权

评论回复
板凳
crystaling1984|  楼主 | 2010-10-12 08:46 | 只看该作者
没人解决啊!高手呢?出来帮帮小弟吧!

使用特权

评论回复
地板
mxh0506| | 2010-10-12 13:12 | 只看该作者
可以参考这个贴子,有ATMEL的源程序
https://bbs.21ic.com/redirect.php ... 259&ptid=197540

使用特权

评论回复
5
crystaling1984|  楼主 | 2010-10-13 09:19 | 只看该作者
这个源程序出来后怎么样跟原来的设备程序融合呢?有没有高手再帮我下。我是菜鸟

使用特权

评论回复
6
crystaling1984|  楼主 | 2010-10-14 14:10 | 只看该作者
除了4楼真的没人可以帮帮忙啊,我需要详细点的。高手出来吧

使用特权

评论回复
7
john_light| | 2010-10-14 15:09 | 只看该作者

/*
* Copyright (C) 2006 by egnite Software GmbH. All rights reserved.
* Copyright (C) 2008 by egnite GmbH. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
*    contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* For additional information see http://www.ethernut.de/
*
*/

#include <cfg/os.h>
#include <cfg/memory.h>

#include <sys/timer.h>

#include <string.h>
#include <stdlib.h>

#include <dev/at91_spi.h>
#include <dev/at45db.h>

#ifndef MAX_AT45_DEVICES
#define MAX_AT45_DEVICES        1
#endif

#ifndef MAX_AT45_CMDLEN
#define MAX_AT45_CMDLEN         8
#endif

#ifndef AT45_CONF_DFSPI
#define AT45_CONF_DFSPI         SPI0_BASE
#endif

#ifndef AT45_CONF_DFPCS
#define AT45_CONF_DFPCS         1
#endif

#ifndef AT45_ERASE_WAIT
#define AT45_ERASE_WAIT         3000
#endif

#ifndef AT45_CHIP_ERASE_WAIT
#define AT45_CHIP_ERASE_WAIT    50000
#endif

#ifndef AT45_WRITE_POLLS
#define AT45_WRITE_POLLS        1000
#endif

#define DFCMD_CONT_READ_LF      0x03

#define DFCMD_CONT_READ_HF      0x0B

#define DFCMD_BLOCK_ERASE       0x50

#define DFCMD_SECTOR_ERASE      0x7C

#define DFCMD_PAGE_ERASE        0x81

#define DFCMD_BUF1_PROG         0x82

#define DFCMD_BUF1_FLASH        0x83

#define DFCMD_BUF1_WRITE        0x84

#define DFCMD_BUF2_PROG         0x85

#define DFCMD_BUF2_FLASH        0x86

#define DFCMD_BUF2_WRITE        0x87

#define DFCMD_BUF1_FLASH_NE     0x88

#define DFCMD_BUF2_FLASH_NE     0x89

#define DFCMD_CHIP_ERASE        0xC7

#define DFCMD_BUF1_READ_LF      0xD1

#define DFCMD_READ_PAGE         0xD2

#define DFCMD_BUF2_READ_LF      0xD3

#define DFCMD_BUF1_READ         0xD4

#define DFCMD_BUF2_READ         0xD6

#define DFCMD_READ_STATUS       0xD7

#define DFCMD_CONT_READ         0xE8

#define AT45DB_AT91


#if defined(AT45DB_SPI0_DEVICE)

#include <dev/sppif0.h>
#if defined(AT45DB_RESET_ACTIVE_HIGH)
#define SpiReset(act)       Sppi0ChipReset(AT45DB_SPI0_DEVICE, act)
#else
#define SpiReset(act)       Sppi0ChipReset(AT45DB_SPI0_DEVICE, !act)
#endif
#define SpiSetMode()        Sppi0SetMode(AT45DB_SPI0_DEVICE, AT45DB_SPI_MODE)
#define SpiSetSpeed()       Sppi0SetSpeed(AT45DB_SPI0_DEVICE, AT45DB_SPI_RATE)
#if defined(AT45DB_SELECT_ACTIVE_HIGH)
#define SpiSelect()         Sppi0SelectDevice(AT45DB_SPI0_DEVICE)
#define SpiDeselect()       Sppi0DeselectDevice(AT45DB_SPI0_DEVICE)
#else
#define SpiSelect()         Sppi0NegSelectDevice(AT45DB_SPI0_DEVICE)
#define SpiDeselect()       Sppi0NegDeselectDevice(AT45DB_SPI0_DEVICE)
#endif
#define SpiByte             Sppi0Byte

#elif defined(AT45DB_SBBI0_DEVICE)

#include <dev/sbbif0.h>
#if defined(AT45DB_RESET_ACTIVE_HIGH)
#define SpiReset(act)       Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, act)
#else
#define SpiReset(act)       Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, !act)
#endif
#define SpiSetMode()        Sbbi0SetMode(AT45DB_SBBI0_DEVICE, AT45DB_SPI_MODE)
#define SpiSetSpeed()       Sbbi0SetSpeed(AT45DB_SBBI0_DEVICE, AT45DB_SPI_RATE)
#if defined(AT45DB_SELECT_ACTIVE_HIGH)
#define SpiSelect()         Sbbi0SelectDevice(AT45DB_SBBI0_DEVICE)
#define SpiDeselect()       Sbbi0DeselectDevice(AT45DB_SBBI0_DEVICE)
#else
#define SpiSelect()         Sbbi0NegSelectDevice(AT45DB_SBBI0_DEVICE)
#define SpiDeselect()       Sbbi0NegDeselectDevice(AT45DB_SBBI0_DEVICE)
#endif
#define SpiByte             Sbbi0Byte

#endif

typedef struct _AT45_DEVTAB {
    uint32_t devt_pages;
    unsigned int devt_pagsiz;
    unsigned int devt_offs;
    uint8_t devt_srmsk;
    uint8_t devt_srval;
} AT45_DEVTAB;

typedef struct _AT45DB_DCB {
    AT45_DEVTAB *dcb_devt;
    unsigned int dcb_spibas;
    unsigned int dcb_spipcs;
    uint8_t dcb_cmdbuf[MAX_AT45_CMDLEN];
} AT45DB_DCB;

AT45_DEVTAB at45_devt[] = {
    {512, 264, 9, 0x3C, 0x0C},  /* AT45DB011B - 128kB */
    {1025, 264, 9, 0x3C, 0x14}, /* AT45DB021B - 256kB */
    {2048, 264, 9, 0x3C, 0x1C}, /* AT45DB041B - 512kB */
    {4096, 264, 9, 0x3C, 0x24}, /* AT45DB081B - 1MB */
    {4096, 528, 10, 0x3C, 0x2C},        /* AT45DB0161B - 2MB */
    {8192, 528, 10, 0x3C, 0x34},        /* AT45DB0321B - 4MB */
    {8192, 1056, 11, 0x38, 0x38},       /* AT45DB0642 - 8MB */
    {0, 0, 0, 0, 0}             /* End of table */
};

static AT45DB_DCB dcbtab[MAX_AT45_DEVICES];

/* Number of active chips. */
static uint_least8_t dcbnum;

/* Chip used for parameter storage. */
static int dd_param = -1;

int At45dbSendCmd(int dd, uint8_t op, uint32_t parm, int len, CONST void *tdata, void *rdata, int datalen)
{
    uint8_t *cb = dcbtab[dd].dcb_cmdbuf;

    if (len > MAX_AT45_CMDLEN) {
        return -1;
    }
    memset(cb, 0, len);
    cb[0] = op;
    if (parm) {
        cb[1] = (uint8_t) (parm >> 16);
        cb[2] = (uint8_t) (parm >> 8);
        cb[3] = (uint8_t) parm;
    }
    return At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, cb, cb, len, tdata, rdata, datalen);
}

uint8_t At45dbGetStatus(int dd)
{
    uint8_t buf[2] = { DFCMD_READ_STATUS, 0xFF };

    if (At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, buf, buf, 2, NULL, NULL, 0)) {
        return (uint8_t) - 1;
    }
    return buf[1];
}

int At45dbWaitReady(int dd, uint32_t tmo, int poll)
{
    uint8_t sr;

    while (((sr = At45dbGetStatus(dd)) & 0x80) == 0) {
        if (!poll) {
            NutSleep(1);
        }
        if (tmo-- == 0) {
            return -1;
        }
    }
    return 0;
}

int At45dbInit(unsigned int spibas, unsigned int spipcs)
{
    int dd = -1;
    uint8_t sr;
    uint_fast8_t i;

    for (i = 0; i < dcbnum; i++) {
        if (dcbtab[i].dcb_spibas == spibas && dcbtab[i].dcb_spipcs == spipcs) {
            return i;
        }
    }

    if (dcbnum >= MAX_AT45_DEVICES) {
        return -1;
    }

#if defined(MCU_AT91SAM7X) || defined(MCU_AT91SAM7SE) || defined(MCU_AT91SAM9260) || defined(MCU_AT91SAM9XE)
    At91SpiInit(spibas);
    At91SpiReset(spibas);
    At91SpiInitChipSelects(spibas, _BV(spipcs));
    At91SpiSetRate(spibas, spipcs, 1000000);
    At91SpiSetModeFlags(spibas, spipcs, SPIMF_MASTER | SPIMF_SCKIAHI | SPIMF_CAPRISE);
#elif defined(MCU_AT91R40008)
#endif

    dcbtab[dcbnum].dcb_spibas = spibas;
    dcbtab[dcbnum].dcb_spipcs = spipcs;
    sr = At45dbGetStatus(dcbnum);

    for (i = 0; at45_devt[i].devt_pages; i++) {
        if ((sr & at45_devt[i].devt_srmsk) == at45_devt[i].devt_srval) {
            dcbtab[dcbnum].dcb_devt = &at45_devt[i];
            dd = dcbnum++;
            break;
        }
    }
    return dd;
}

int At45dbPageErase(int dd, uint32_t pgn)
{
    pgn <<= dcbtab[dd].dcb_devt->devt_offs;
    return At45dbSendCmd(dd, DFCMD_PAGE_ERASE, pgn, 4, NULL, NULL, 0);
}

int At45dbChipErase(void)
{
    return -1;
}

int At45dbPageRead(int dd, uint32_t pgn, void *data, unsigned int len)
{
    pgn <<= dcbtab[dd].dcb_devt->devt_offs;
    return At45dbSendCmd(dd, DFCMD_CONT_READ, pgn, 8, data, data, len);
}

int At45dbPageWrite(int dd, uint32_t pgn, CONST void *data, unsigned int len)
{
    int rc = -1;
    void *rp;

    if ((rp = malloc(len)) != NULL) {
        /* Copy data to dataflash RAM buffer. */
        if (At45dbSendCmd(dd, DFCMD_BUF1_WRITE, 0, 4, data, rp, len) == 0) {
            /* Flash RAM buffer. */
            pgn <<= dcbtab[dd].dcb_devt->devt_offs;
            if (At45dbSendCmd(dd, DFCMD_BUF1_FLASH, pgn, 4, NULL, NULL, 0) == 0) {
                rc = At45dbWaitReady(dd, AT45_WRITE_POLLS, 1);
            }
        }
        free(rp);
    }
    return rc;
}

uint32_t At45dbPages(int dd)
{
    return dcbtab[dd].dcb_devt->devt_pages;
}

unsigned int At45dbPageSize(int dd)
{
    return dcbtab[dd].dcb_devt->devt_pagsiz;
}

uint32_t At45dbParamPage(void)
{
#ifdef AT45_CONF_PAGE
    return AT45_CONF_PAGE;
#else
    return dcbtab[dd_param].dcb_devt->devt_pages - 1;
#endif
}

int At45dbParamSize(void)
{
    int rc;

    if (dd_param == -1 && (dd_param = At45dbInit(AT45_CONF_DFSPI, AT45_CONF_DFPCS)) == -1) {
        return -1;
    }
#ifdef AT45_CONF_SIZE
    rc = AT45_CONF_SIZE;
#else
    rc = dcbtab[dd_param].dcb_devt->devt_pagsiz;
#endif
    return rc;
}

int At45dbParamRead(unsigned int pos, void *data, unsigned int len)
{
    int rc = -1;
    uint8_t *buff;
    int csize = At45dbParamSize();
    uint32_t cpage = At45dbParamPage();

    /* Load the complete configuration area. */
    if (csize > len && (buff = malloc(csize)) != NULL) {
        rc = At45dbPageRead(dd_param, cpage, buff, csize);
        /* Copy requested contents to caller's buffer. */
        memcpy(data, buff + pos, len);
        free(buff);
    }
    return rc;
}

int At45dbParamWrite(unsigned int pos, CONST void *data, unsigned int len)
{
    int rc = -1;
    uint8_t *buff;
    int csize = At45dbParamSize();
    uint32_t cpage = At45dbParamPage();

    /* Load the complete configuration area. */
    if (csize > len && (buff = malloc(csize)) != NULL) {
        rc = At45dbPageRead(dd_param, cpage, buff, csize);
        /* Compare old with new contents. */
        if (memcmp(buff + pos, data, len)) {
            /* New contents differs. Copy it into the sector buffer. */
            memcpy(buff + pos, data, len);
            /* Erase sector and write new data. */
            rc = At45dbPageWrite(dd_param, cpage, buff, csize);
        }
        free(buff);
    }
    return rc;
}


出处在此:Nut/OS API

使用特权

评论回复
8
john_light| | 2010-10-14 15:22 | 只看该作者

/*
* Atmel SPI DataFlash support
*
* Copyright (C) 2008 Atmel Corporation
* Licensed under the GPL-2 or later.
*/

#include <common.h>
#include <malloc.h>
#include <spi_flash.h>

#include "spi_flash_internal.h"

/* AT45-specific commands */
#define CMD_AT45_READ_STATUS                0xd7
#define CMD_AT45_ERASE_PAGE                0x81
#define CMD_AT45_LOAD_PROG_BUF1                0x82
#define CMD_AT45_LOAD_BUF1                0x84
#define CMD_AT45_LOAD_PROG_BUF2                0x85
#define CMD_AT45_LOAD_BUF2                0x87
#define CMD_AT45_PROG_BUF1                0x88
#define CMD_AT45_PROG_BUF2                0x89

/* AT45 status register bits */
#define AT45_STATUS_P2_PAGE_SIZE        (1 << 0)
#define AT45_STATUS_READY                (1 << 7)

/* DataFlash family IDs, as obtained from the second idcode byte */
#define DF_FAMILY_AT26F                        0
#define DF_FAMILY_AT45                        1
#define DF_FAMILY_AT26DF                2        /* AT25DF and AT26DF */

struct atmel_spi_flash_params {
        u8                idcode1;
        /* Log2 of page size in power-of-two mode */
        u8                l2_page_size;
        u8                pages_per_block;
        u8                blocks_per_sector;
        u8                nr_sectors;
        const char        *name;
};

/* spi_flash needs to be first so upper layers can free() it */
struct atmel_spi_flash {
        struct spi_flash flash;
        const struct atmel_spi_flash_params *params;
};

static inline struct atmel_spi_flash *
to_atmel_spi_flash(struct spi_flash *flash)
{
        return container_of(flash, struct atmel_spi_flash, flash);
}

static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
        {
                .idcode1                = 0x22,
                .l2_page_size                = 8,
                .pages_per_block        = 8,
                .blocks_per_sector        = 16,
                .nr_sectors                = 4,
                .name                        = "AT45DB011D",
        },
        {
                .idcode1                = 0x23,
                .l2_page_size                = 8,
                .pages_per_block        = 8,
                .blocks_per_sector        = 16,
                .nr_sectors                = 8,
                .name                        = "AT45DB021D",
        },
        {
                .idcode1                = 0x24,
                .l2_page_size                = 8,
                .pages_per_block        = 8,
                .blocks_per_sector        = 32,
                .nr_sectors                = 8,
                .name                        = "AT45DB041D",
        },
        {
                .idcode1                = 0x25,
                .l2_page_size                = 8,
                .pages_per_block        = 8,
                .blocks_per_sector        = 32,
                .nr_sectors                = 16,
                .name                        = "AT45DB081D",
        },
        {
                .idcode1                = 0x26,
                .l2_page_size                = 9,
                .pages_per_block        = 8,
                .blocks_per_sector        = 32,
                .nr_sectors                = 16,
                .name                        = "AT45DB161D",
        },
        {
                .idcode1                = 0x27,
                .l2_page_size                = 9,
                .pages_per_block        = 8,
                .blocks_per_sector        = 64,
                .nr_sectors                = 64,
                .name                        = "AT45DB321D",
        },
        {
                .idcode1                = 0x28,
                .l2_page_size                = 10,
                .pages_per_block        = 8,
                .blocks_per_sector        = 32,
                .nr_sectors                = 32,
                .name                        = "AT45DB642D",
        },
};

static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout)
{
        struct spi_slave *spi = flash->spi;
        unsigned long timebase;
        int ret;
        u8 cmd = CMD_AT45_READ_STATUS;
        u8 status;

        timebase = get_timer(0);

        ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
        if (ret)
                return -1;

        do {
                ret = spi_xfer(spi, 8, NULL, &status, 0);
                if (ret)
                        return -1;

                if (status & AT45_STATUS_READY)
                        break;
        } while (get_timer(timebase) < timeout);

        /* Deactivate CS */
        spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);

        if (status & AT45_STATUS_READY)
                return 0;

        /* Timed out */
        return -1;
}

/*
* Assemble the address part of a command for AT45 devices in
* non-power-of-two page size mode.
*/
static void at45_build_address(struct atmel_spi_flash *asf, u8 *cmd, u32 offset)
{
        unsigned long page_addr;
        unsigned long byte_addr;
        unsigned long page_size;
        unsigned int page_shift;

        /*
         * The "extra" space per page is the power-of-two page size
         * divided by 32.
         */
        page_shift = asf->params->l2_page_size;
        page_size = (1 << page_shift) + (1 << (page_shift - 5));
        page_shift++;
        page_addr = offset / page_size;
        byte_addr = offset % page_size;

        cmd[0] = page_addr >> (16 - page_shift);
        cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8);
        cmd[2] = byte_addr;
}

static int dataflash_read_fast_p2(struct spi_flash *flash,
                u32 offset, size_t len, void *buf)
{
        u8 cmd[5];

        cmd[0] = CMD_READ_ARRAY_FAST;
        cmd[1] = offset >> 16;
        cmd[2] = offset >> 8;
        cmd[3] = offset;
        cmd[4] = 0x00;

        return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
}

static int dataflash_read_fast_at45(struct spi_flash *flash,
                u32 offset, size_t len, void *buf)
{
        struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
        u8 cmd[5];

        cmd[0] = CMD_READ_ARRAY_FAST;
        at45_build_address(asf, cmd + 1, offset);
        cmd[4] = 0x00;

        return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
}

/*
* TODO: the two write funcs (_p2/_at45) should get unified ...
*/
static int dataflash_write_p2(struct spi_flash *flash,
                u32 offset, size_t len, const void *buf)
{
        struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
        unsigned long page_size;
        u32 addr = offset;
        size_t chunk_len;
        size_t actual;
        int ret;
        u8 cmd[4];

        /*
         * TODO: This function currently uses only page buffer #1.  We can
         * speed this up by using both buffers and loading one buffer while
         * the other is being programmed into main memory.
         */

        page_size = (1 << asf->params->l2_page_size);

        ret = spi_claim_bus(flash->spi);
        if (ret) {
                debug("SF: Unable to claim SPI bus\n");
                return ret;
        }

        for (actual = 0; actual < len; actual += chunk_len) {
                chunk_len = min(len - actual, page_size - (addr % page_size));

                /* Use the same address bits for both commands */
                cmd[0] = CMD_AT45_LOAD_BUF1;
                cmd[1] = addr >> 16;
                cmd[2] = addr >> 8;
                cmd[3] = addr;

                ret = spi_flash_cmd_write(flash->spi, cmd, 4,
                                buf + actual, chunk_len);
                if (ret < 0) {
                        debug("SF: Loading AT45 buffer failed\n");
                        goto out;
                }

                cmd[0] = CMD_AT45_PROG_BUF1;
                ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
                if (ret < 0) {
                        debug("SF: AT45 page programming failed\n");
                        goto out;
                }

                ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
                if (ret < 0) {
                        debug("SF: AT45 page programming timed out\n");
                        goto out;
                }

                addr += chunk_len;
        }

        debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
                        len, offset);
        ret = 0;

out:
        spi_release_bus(flash->spi);
        return ret;
}

static int dataflash_write_at45(struct spi_flash *flash,
                u32 offset, size_t len, const void *buf)
{
        struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
        unsigned long page_addr;
        unsigned long byte_addr;
        unsigned long page_size;
        unsigned int page_shift;
        size_t chunk_len;
        size_t actual;
        int ret;
        u8 cmd[4];

        /*
         * TODO: This function currently uses only page buffer #1.  We can
         * speed this up by using both buffers and loading one buffer while
         * the other is being programmed into main memory.
         */

        page_shift = asf->params->l2_page_size;
        page_size = (1 << page_shift) + (1 << (page_shift - 5));
        page_shift++;
        page_addr = offset / page_size;
        byte_addr = offset % page_size;

        ret = spi_claim_bus(flash->spi);
        if (ret) {
                debug("SF: Unable to claim SPI bus\n");
                return ret;
        }

        for (actual = 0; actual < len; actual += chunk_len) {
                chunk_len = min(len - actual, page_size - byte_addr);

                /* Use the same address bits for both commands */
                cmd[0] = CMD_AT45_LOAD_BUF1;
                cmd[1] = page_addr >> (16 - page_shift);
                cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8);
                cmd[3] = byte_addr;

                ret = spi_flash_cmd_write(flash->spi, cmd, 4,
                                buf + actual, chunk_len);
                if (ret < 0) {
                        debug("SF: Loading AT45 buffer failed\n");
                        goto out;
                }

                cmd[0] = CMD_AT45_PROG_BUF1;
                ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
                if (ret < 0) {
                        debug("SF: AT45 page programming failed\n");
                        goto out;
                }

                ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
                if (ret < 0) {
                        debug("SF: AT45 page programming timed out\n");
                        goto out;
                }

                page_addr++;
                byte_addr = 0;
        }

        debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
                        len, offset);
        ret = 0;

out:
        spi_release_bus(flash->spi);
        return ret;
}

/*
* TODO: the two erase funcs (_p2/_at45) should get unified ...
*/
int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len)
{
        struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
        unsigned long page_size;

        size_t actual;
        int ret;
        u8 cmd[4];

        /*
         * TODO: This function currently uses page erase only. We can
         * probably speed things up by using block and/or sector erase
         * when possible.
         */

        page_size = (1 << asf->params->l2_page_size);

        if (offset % page_size || len % page_size) {
                debug("SF: Erase offset/length not multiple of page size\n");
                return -1;
        }

        cmd[0] = CMD_AT45_ERASE_PAGE;
        cmd[3] = 0x00;

        ret = spi_claim_bus(flash->spi);
        if (ret) {
                debug("SF: Unable to claim SPI bus\n");
                return ret;
        }

        for (actual = 0; actual < len; actual += page_size) {
                cmd[1] = offset >> 16;
                cmd[2] = offset >> 8;

                ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
                if (ret < 0) {
                        debug("SF: AT45 page erase failed\n");
                        goto out;
                }

                ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
                if (ret < 0) {
                        debug("SF: AT45 page erase timed out\n");
                        goto out;
                }

                offset += page_size;
        }

        debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
                        len, offset);
        ret = 0;

out:
        spi_release_bus(flash->spi);
        return ret;
}

int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len)
{
        struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
        unsigned long page_addr;
        unsigned long page_size;
        unsigned int page_shift;
        size_t actual;
        int ret;
        u8 cmd[4];

        /*
         * TODO: This function currently uses page erase only. We can
         * probably speed things up by using block and/or sector erase
         * when possible.
         */

        page_shift = asf->params->l2_page_size;
        page_size = (1 << page_shift) + (1 << (page_shift - 5));
        page_shift++;
        page_addr = offset / page_size;

        if (offset % page_size || len % page_size) {
                debug("SF: Erase offset/length not multiple of page size\n");
                return -1;
        }

        cmd[0] = CMD_AT45_ERASE_PAGE;
        cmd[3] = 0x00;

        ret = spi_claim_bus(flash->spi);
        if (ret) {
                debug("SF: Unable to claim SPI bus\n");
                return ret;
        }

        for (actual = 0; actual < len; actual += page_size) {
                cmd[1] = page_addr >> (16 - page_shift);
                cmd[2] = page_addr << (page_shift - 8);

                ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
                if (ret < 0) {
                        debug("SF: AT45 page erase failed\n");
                        goto out;
                }

                ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
                if (ret < 0) {
                        debug("SF: AT45 page erase timed out\n");
                        goto out;
                }

                page_addr++;
        }

        debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
                        len, offset);
        ret = 0;

out:
        spi_release_bus(flash->spi);
        return ret;
}

struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
{
        const struct atmel_spi_flash_params *params;
        unsigned page_size;
        unsigned int family;
        struct atmel_spi_flash *asf;
        unsigned int i;
        int ret;
        u8 status;

        for (i = 0; i < ARRAY_SIZE(atmel_spi_flash_table); i++) {
                params = &atmel_spi_flash_table[i];
                if (params->idcode1 == idcode[1])
                        break;
        }

        if (i == ARRAY_SIZE(atmel_spi_flash_table)) {
                debug("SF: Unsupported DataFlash ID %02x\n",
                                idcode[1]);
                return NULL;
        }

        asf = malloc(sizeof(struct atmel_spi_flash));
        if (!asf) {
                debug("SF: Failed to allocate memory\n");
                return NULL;
        }

        asf->params = params;
        asf->flash.spi = spi;
        asf->flash.name = params->name;

        /* Assuming power-of-two page size initially. */
        page_size = 1 << params->l2_page_size;

        family = idcode[1] >> 5;

        switch (family) {
        case DF_FAMILY_AT45:
                /*
                 * AT45 chips have configurable page size. The status
                 * register indicates which configuration is active.
                 */
                ret = spi_flash_cmd(spi, CMD_AT45_READ_STATUS, &status, 1);
                if (ret)
                        goto err;

                debug("SF: AT45 status register: %02x\n", status);

                if (!(status & AT45_STATUS_P2_PAGE_SIZE)) {
                        asf->flash.read = dataflash_read_fast_at45;
                        asf->flash.write = dataflash_write_at45;
                        asf->flash.erase = dataflash_erase_at45;
                        page_size += 1 << (params->l2_page_size - 5);
                } else {
                        asf->flash.read = dataflash_read_fast_p2;
                        asf->flash.write = dataflash_write_p2;
                        asf->flash.erase = dataflash_erase_p2;
                }

                break;

        case DF_FAMILY_AT26F:
        case DF_FAMILY_AT26DF:
                asf->flash.read = dataflash_read_fast_p2;
                break;

        default:
                debug("SF: Unsupported DataFlash family %u\n", family);
                goto err;
        }

        asf->flash.size = page_size * params->pages_per_block
                                * params->blocks_per_sector
                                * params->nr_sectors;

        printf("SF: Detected %s with page size %u, total ",
               params->name, page_size);
        print_size(asf->flash.size, "\n");

        return &asf->flash;

err:
        free(asf);
        return NULL;
}
出处:U-Boot
能不能参透就看你的造化了。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
crystaling1984 + 1
9
粉丝| | 2010-10-14 18:37 | 只看该作者
楼上的贴子有意思。

使用特权

评论回复
10
john_light| | 2010-10-15 12:25 | 只看该作者
烦请9楼不吝赐教

使用特权

评论回复
11
crystaling1984|  楼主 | 2010-10-18 09:11 | 只看该作者
8# john_light

高手:你给我回的那个程序第一个是AT45DB的c源程序吗?8楼还留了个程序是什么的呢?

使用特权

评论回复
12
crystaling1984|  楼主 | 2010-10-18 09:11 | 只看该作者
8# john_light

高手:你给我回的那个程序第一个是AT45DB的c源程序吗?8楼还留了个程序是什么的呢?

使用特权

评论回复
13
crystaling1984|  楼主 | 2010-10-18 09:11 | 只看该作者
8# john_light

高手:你给我回的那个程序第一个是AT45DB的c源程序吗?8楼还留了个程序是什么的呢?

使用特权

评论回复
14
john_light| | 2010-10-18 11:47 | 只看该作者
两个源程序都是AT45系列Flash的驱动源码,由不同的人写就。

你需要自己消化,挑出自己能用的部分。

使用特权

评论回复
15
crystaling1984|  楼主 | 2010-10-19 08:32 | 只看该作者
14# john_light

能不能帮忙下把我需要的挑下给我,我是这方面的新手,消化需要时间,但是公司的任务是限时间的,求你帮忙下了

使用特权

评论回复
16
john_light| | 2010-10-19 08:34 | 只看该作者
这点,帮不了你。

另找高人吧。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

41

帖子

1

粉丝