打印

试着对flash写点内容,现在只写入了一个字节,请帮忙看看

[复制链接]
3756|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
adibe|  楼主 | 2008-5-28 08:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
SST的flash,main函数中定义了一个字符数组:char txt[]="This is a example";然后用此语句  Program(0,txt); 调用下面的函数。

uint8  Program(uint16 Addr, char *Data) 
{  volatile uint16  *ip;
   uint16  temp1,temp2;
   
   ip = GetAddr(0x5555);
   ip[0] = 0xaaaa;            
   ip = GetAddr(0x2aaa);
   ip[0] = 0x5555;            
   ip = GetAddr(0x5555);
   ip[0] = 0xa0a0;            
   ip = GetAddr(Addr);  

   while(Data!='\0')
   {
     *ip++ = *Data++;    
   }

现在只能写入第一个字母 T ,其它的就无法再写入,但是在内存中监视这个addr和Data是有变化的。我现在分析有如下原因:
1、现在只对flash的地址0 (ip[0])进行了“初始化”,也就只能对这个地址写入,所以其它的均无法写入。
2、Program(0,txt);这句话也只是针对了flash的0地址,所以只能写入一个字节。
针对这两个疑问,我吧 Program(0,txt); 中的0地址改用了指针代替,把写入函数改为了:uint8  Program(uint16 *Addr, char *Data) ,出了很多问题。
现在把这些问题写出来,也许对你们来说肯定是很简单的问题,我以前基本没接触到嵌入式编程,希望能得到大家的帮助。谢谢。

相关帖子

沙发
adibe|  楼主 | 2008-5-28 09:09 | 只看该作者

这个判断while(Data!='\0')也有问题

见笑了。是个死循环,跳不出来,因为内存里的内容不只有这个数组。
我现在关注的是如何将内存里的东西写到flash里,一步一步来吧。

使用特权

评论回复
板凳
dld2| | 2008-5-28 09:38 | 只看该作者

FLASH编程

写一次命令序列,只能编程一个word,而不是很多word。

使用特权

评论回复
地板
adibe|  楼主 | 2008-5-28 09:58 | 只看该作者

那如果要连续写入很多数据怎么做呢?


就像我直接用仿真器那样,一次性全部写进去。

每次都要编写命令序列?

使用特权

评论回复
5
wujiarui| | 2008-5-28 12:10 | 只看该作者

把编程命令序列写入循环中

使用特权

评论回复
6
来与君| | 2008-5-28 18:30 | 只看该作者

贴个U-boot的flash.c,但愿没把简单问题搞复杂

/*
 * (C) Copyright 2003-2004
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * (C) Copyright 2004
 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
 *
 * Modified for the CMC PU2 by (C) Copyright 2004 Gary Jennejohn
 * garyj@denx.de
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>

#ifndef    CFG_ENV_ADDR
#define CFG_ENV_ADDR    (CFG_FLASH_BASE + CFG_ENV_OFFSET)
#endif

flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */

#define FLASH_CYCLE1    0x0555
#define FLASH_CYCLE2    0x02AA

/*-----------------------------------------------------------------------
 * Functions
 */
static ulong flash_get_size(vu_short *addr, flash_info_t *info);
static void flash_reset(flash_info_t *info);
static int write_word_amd(flash_info_t *info, vu_short *dest, ushort data);
static flash_info_t *flash_get_info(ulong base);

/*-----------------------------------------------------------------------
 * flash_init()
 *
 * sets up flash_info and returns size of FLASH (bytes)
 */
unsigned long flash_init (void)
{
    unsigned long size = 0;
    ulong flashbase = CFG_FLASH_BASE;

    /* Init: no FLASHes known */
    memset(&flash_info[0], 0, sizeof(flash_info_t));

    flash_info[0].size = flash_get_size((vu_short *)flashbase, &flash_info[0]);

    size = flash_info[0].size;

#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
    /* monitor protection ON by default */
    flash_protect(FLAG_PROTECT_SET,
              CFG_MONITOR_BASE,
              CFG_MONITOR_BASE+monitor_flash_len-1,
              flash_get_info(CFG_MONITOR_BASE));
#endif

#ifdef    CFG_ENV_IS_IN_FLASH
    /* ENV protection ON by default */
    flash_protect(FLAG_PROTECT_SET,
              CFG_ENV_ADDR,
              CFG_ENV_ADDR+CFG_ENV_SIZE-1,
              flash_get_info(CFG_ENV_ADDR));
#endif

    return size ? size : 1;
}

/*-----------------------------------------------------------------------
 */
static void flash_reset(flash_info_t *info)
{
    vu_short *base = (vu_short *)(info->start[0]);

    /* Put FLASH back in read mode */
    if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
        *base = 0x00FF;    /* Intel Read Mode */
    else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
        *base = 0x00F0;    /* AMD Read Mode */
}

/*-----------------------------------------------------------------------
 */

static flash_info_t *flash_get_info(ulong base)
{
    int i;
    flash_info_t * info;

    info = NULL;
    for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
        info = & flash_info;
        if (info->size && info->start[0] <= base &&
            base <= info->start[0] + info->size - 1)
            break;
    }

    return i == CFG_MAX_FLASH_BANKS ? 0 : info;
}

/*-----------------------------------------------------------------------
 */

void flash_print_info (flash_info_t *info)
{
    int i;

    if (info->flash_id == FLASH_UNKNOWN) {
        printf ("missing or unknown FLASH type\n");
        return;
    }

    switch (info->flash_id & FLASH_VENDMASK) {
    case FLASH_MAN_AMD:    printf ("AMD ");        break;
    case FLASH_MAN_BM:    printf ("BRIGHT MICRO ");    break;
    case FLASH_MAN_FUJ:    printf ("FUJITSU ");        break;
    case FLASH_MAN_SST:    printf ("SST ");        break;
    case FLASH_MAN_STM:    printf ("STM ");        break;
    case FLASH_MAN_INTEL:    printf ("INTEL ");        break;
    default:        printf ("Unknown Vendor ");    break;
    }

    switch (info->flash_id & FLASH_TYPEMASK) {
    case FLASH_S29GL064M:
        printf ("S29GL064M-R6 (64Mbit, uniform sector size)\n");
        break;
    default:
        printf ("Unknown Chip Type\n");
        break;
    }

    printf ("  Size: %ld MB in %d Sectors\n",
        info->size >> 20,
        info->sector_count);

    printf ("  Sector Start Addresses:");

    for (i=0; i<info->sector_count; ++i) {
        if ((i % 5) == 0) {
            printf ("\n   ");
        }
        printf (" %08lX%s",
            info->start,
            info->protect ? " (RO)" : "     ");
    }
    printf ("\n");
    return;
}

/*-----------------------------------------------------------------------
 */

/*
 * The following code cannot be run from FLASH!
 */

ulong flash_get_size (vu_short *addr, flash_info_t *info)
{
    int i;
    ushort value;
    ulong base = (ulong)addr;

    /* Write auto select command sequence */
    addr[FLASH_CYCLE1] = 0x00AA;    /* for AMD, Intel ignores this */
    addr[FLASH_CYCLE2] = 0x0055;    /* for AMD, Intel ignores this */
    addr[FLASH_CYCLE1] = 0x0090;    /* selects Intel or AMD */

    /* read Manufacturer ID */
    udelay(100);
    value = addr[0];
    debug ("Manufacturer ID: %04X\n", value);

    switch (value) {

    case (AMD_MANUFACT & 0xFFFF):
        debug ("Manufacturer: AMD (Spansion)\n");
        info->flash_id = FLASH_MAN_AMD;
        break;

    case (INTEL_MANUFACT & 0xFFFF):
        debug ("Manufacturer: Intel (not supported yet)\n");
        info->flash_id = FLASH_MAN_INTEL;
        break;

    default:
        printf ("Unknown Manufacturer ID: %04X\n", value);
        info->flash_id = FLASH_UNKNOWN;
        info->sector_count = 0;
        info->size = 0;
        goto out;
    }

    value = addr[1];
    debug ("Device ID: %04X\n", value);

    switch (addr[1]) {

    case (AMD_ID_MIRROR & 0xFFFF):
        debug ("Mirror Bit flash: addr[14] = %08X  addr[15] = %08X\n",
            addr[14], addr[15]);

        switch(addr[14]) {
        case (AMD_ID_GL064M_2 & 0xFFFF):
            if (addr[15] != (AMD_ID_GL064M_3 & 0xffff)) {
                printf ("Chip: S29GLxxxM -> unknown\n");
                info->flash_id = FLASH_UNKNOWN;
                info->sector_count = 0;
                info->size = 0;
            } else {
                debug ("Chip: S29GL064M-R6\n");
                info->flash_id += FLASH_S29GL064M;
                info->sector_count = 128;
                info->size = 0x00800000;
                for (i = 0; i < info->sector_count; i++) {
                    info->start = base;
                    base += 0x10000;
                }
            }
            break;    /* => 16 MB    */
        default:
            printf ("Chip: *** unknown ***\n");
            info->flash_id = FLASH_UNKNOWN;
            info->sector_count = 0;
            info->size = 0;
            break;
        }
        break;

    default:
        printf ("Unknown Device ID: %04X\n", value);
        info->flash_id = FLASH_UNKNOWN;
        info->sector_count = 0;
        info->size = 0;
        break;
    }

out:
    /* Put FLASH back in read mode */
    flash_reset(info);

    return (info->size);
}

/*-----------------------------------------------------------------------
 */

int    flash_erase (flash_info_t *info, int s_first, int s_last)
{
    vu_short *addr = (vu_short *)(info->start[0]);
    int flag, prot, sect, ssect, l_sect;
    ulong now, last;

    debug ("flash_erase: first: %d last: %d\n", s_first, s_last);

    if ((s_first < 0) || (s_first > s_last)) {
        if (info->flash_id == FLASH_UNKNOWN) {
            printf ("- missing\n");
        } else {
            printf ("- no sectors to erase\n");
        }
        return 1;
    }

    if ((info->flash_id == FLASH_UNKNOWN) ||
        (info->flash_id > FLASH_AMD_COMP)) {
        printf ("Can't erase unknown flash type %08lx - aborted\n",
            info->flash_id);
        return 1;
    }

    prot = 0;
    for (sect=s_first; sect<=s_last; ++sect) {
        if (info->protect[sect]) {
            prot++;
        }
    }

    if (prot) {
        printf ("- Warning: %d protected sectors will not be erased!\n",
            prot);
    } else {
        printf ("\n");
    }

    /* Disable interrupts which might cause a timeout here */
    flag = disable_interrupts();

    /*
     * Start erase on unprotected sectors.
     * Since the flash can erase multiple sectors with one command
     * we take advantage of that by doing the erase in chunks of
     * 3 sectors.
     */
    for (sect = s_first; sect <= s_last; ) {
        l_sect = -1;

        addr[FLASH_CYCLE1] = 0x00AA;
        addr[FLASH_CYCLE2] = 0x0055;
        addr[FLASH_CYCLE1] = 0x0080;
        addr[FLASH_CYCLE1] = 0x00AA;
        addr[FLASH_CYCLE2] = 0x0055;

        /* do the erase in chunks of at most 3 sectors */
        for (ssect = 0; ssect < 3; ssect++) {
            if ((sect + ssect) > s_last)
                break;
            if (info->protect[sect + ssect] == 0) {    /* not protected */
                addr = (vu_short *)(info->start[sect + ssect]);
                addr[0] = 0x0030;
                l_sect = sect + ssect;
            }
        }
        /* wait at least 80us - let's wait 1 ms */
        udelay (1000);

        /*
         * We wait for the last triggered sector
         */
        if (l_sect < 0)
            goto DONE;

        reset_timer_masked ();
        last  = 0;
        addr = (vu_short *)(info->start[l_sect]);
        while ((addr[0] & 0x0080) != 0x0080) {
            if ((now = get_timer_masked ()) > CFG_FLASH_ERASE_TOUT) {
                printf ("Timeout\n");
                return 1;
            }
            /* show that we're waiting */
            if ((now - last) > 1000) {    /* every second */
                putc ('.');
                last = now;
            }
        }
        addr = (vu_short *)info->start[0];
        addr[0] = 0x00F0;    /* reset bank */
        sect += ssect;
    }

    /* re-enable interrupts if necessary */
    if (flag)
        enable_interrupts();

DONE:
    /* reset to read mode */
    addr = (vu_short *)info->start[0];
    addr[0] = 0x00F0;    /* reset bank */

    printf (" done\n");
    return 0;
}

/*-----------------------------------------------------------------------
 * Copy memory to flash, returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 */

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
    ulong wp, data;
    int rc;

    if (addr & 1) {
        printf ("unaligned destination not supported\n");
        return ERR_ALIGN;
    };

    if ((int) src & 1) {
        printf ("unaligned source not supported\n");
        return ERR_ALIGN;
    };

    wp = addr;

    while (cnt >= 2) {
        data = *((vu_short *)src);
        if ((rc = write_word_amd(info, (vu_short *)wp, data)) != 0) {
printf ("write_buff 1: write_word_amd() rc=%d\n", rc);
            return (rc);
        }
        src += 2;
        wp += 2;
        cnt -= 2;
    }

    if (cnt == 0) {
        return (ERR_OK);
    }

    if (cnt == 1) {
        data = (*((volatile u8 *) src)) | (*((volatile u8 *) (wp + 1)) << 8);
        if ((rc = write_word_amd(info, (vu_short *)wp, data)) != 0) {
printf ("write_buff 1: write_word_amd() rc=%d\n", rc);
            return (rc);
        }
        src += 1;
        wp += 1;
        cnt -= 1;
    }

    return ERR_OK;
}

/*-----------------------------------------------------------------------
 * Write a word to Flash for AMD FLASH
 * A word is 16 or 32 bits, whichever the bus width of the flash bank
 * (not an individual chip) is.
 *
 * returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 */
static int write_word_amd (flash_info_t *info, vu_short *dest, ushort data)
{
    int flag;
    vu_short *base;        /* first address in flash bank    */

    /* Check if Flash is (sufficiently) erased */
    if ((*dest & data) != data) {
        return (2);
    }

    base = (vu_short *)(info->start[0]);

    /* Disable interrupts which might cause a timeout here */
    flag = disable_interrupts();

    base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
    base[FLASH_CYCLE2] = 0x0055;    /* unlock */
    base[FLASH_CYCLE1] = 0x00A0;    /* selects program mode */

    *dest = data;        /* start programming the data    */

    /* re-enable interrupts if necessary */
    if (flag)
        enable_interrupts();

    reset_timer_masked ();

    /* data polling for D7 */
    while ((*dest & 0x0080) != (data & 0x0080)) {
        if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) {
            *dest = 0x00F0;    /* reset bank */
            return (1);
        }
    }
    return (0);
}

使用特权

评论回复
7
adibe|  楼主 | 2008-5-28 18:49 | 只看该作者

谢谢楼上大哥

现在改了下可以了

while(*Data!='\0') 

  ip = GetAddr(0x5555); 
  *ip = 0xaaaa;            
  ip = GetAddr(0x2aaa); 
  *ip = 0x5555;            
  ip = GetAddr(0x5555); 
  *ip = 0xa0a0;            
  ip = GetAddr(Addr);  

  *ip++ = *Data++;    


果然是那个问题,ip【0】只有第一个地址的时序,现在改为*ip后可以对后面的地址做时序,所以现在可以写进去东西了。 while判断也已经ok,现在的问题是:我定义的数组是:static char  txt[]="This is an example"; 8位的,可是现在cpu都是按字16位操作的,所以搞8位全写0,低8位才是数组数据,这个矛盾怎么解决? 现在写入flash的内容都是有一个字节的空格的:T_h_i_s …… 

使用特权

评论回复
8
来与君| | 2008-5-28 20:08 | 只看该作者

还是看上面那个U-Boot的例子吧

每次写一个int的话,指针加2,最后在小于等于2个字节时再另外处理。

使用特权

评论回复
9
adibe|  楼主 | 2008-5-29 15:11 | 只看该作者

为什么加了一个printf函数后程序不能运行

在写完一个数组后,我加了个printf函数。
AXD里应该有输出终端可以显示打印的窗口吧?

现在加了这句后程序无法运行,停在软件中断那里,程序无法载入内存里。注释掉这句话就可以了,这是为什么?

使用特权

评论回复
10
adibe|  楼主 | 2008-5-30 09:24 | 只看该作者

已经搞定

按上面的思路:把调用函数的data改为了16位的,uint8  Program(uint16 Addr, uint16 *Data) ,使之和地址位数对齐,这样让字符串的指针也一次加一个字,在函数调用时做个类型转换,对应就没问题了。 

使用特权

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

本版积分规则

111

主题

275

帖子

0

粉丝