基于arm7的(lpc2388)flash的读写操作

开始工作不久就碰到一个flash读写的问题。是一块lpc2388的芯片(arm7),

开始总是抱着一arm11的flash读写的方式去看数据手册。看了好长时间都没有一个很好的解决方发。

后来我在keil的库文件中找到:flash的写入方式。如下://C:\Keil\ARM\Flash\LPC2888\FlashPrg.c

/*
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,  1 - Failed
 */

int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
  unsigned long i;

  // Preset data latches
  F_CTRL   = FC_CS | FC_FUNC | FC_WEN | FC_SET_DATA;
  F_CTRL   = FC_CS | FC_FUNC | FC_WEN;

  // Set timer register for programming
  F_PROG_TIME = 800 | FPT_ENABLE;

  // If size is not whole number of words, 
  // fill rest of last word with 0xFF
  if ((sz%4) != 0) {
    *((unsigned long *)buf+(sz/4)) |= or_mask[sz%4];
  }

  // Load data to data latches
  for (i = 0; i < ((sz+3)/4); i++)  {
    M32(adr) = *((unsigned long *)buf);
    buf += 4;
    adr += 4;
  }
  // Load remaining bytes to full page (512) with 0xFF
  for (i = ((sz+3)/4); i < (512/4); i++) {
    M32(adr) = 0xFFFFFFFF;
    adr += 4;
  }

  // Issue program command
  F_CTRL   = FC_CS | FC_FUNC | FC_PROTECT | FC_PROG_REQ;

  while (!(F_STAT & FS_DONE));          // Wait command to finish

  // Disable timer
  F_PROG_TIME = 0;

  return (0);                           // Done successfully
}

这里有很清晰的flash的写入方式,可是读取的方式了。

于是在看手册想找到一个寄存器之类的,进行读取啊。《LPC2388中文资料》在这里居然还是没找到,看下英文的吧,可是英文水平不咋的,还是无济于事啊。

                                **Arm7(lpc2388)Flash的读取**

后来在经理的帮助下原来lpc2388的flash的读写是这么的简单啊。(其他的单片机没有用到,我想arm系列的单片机可能都是这样子的了)

#define DestAddr    0x00038000      ///276k    0X0007CFFF
//就是一个flash的起始地址,
/*
recindex是一个其实地址的便宜,可以这样理解,可以根据自己的需要便宜,可以是任意值(0~1024)具体的范围的看数据手册。

adata是数据的保存,就是你分配的内存空间
*/
uint32 flash_read_256( int recindex, unsigned char *adata )
{
    unsigned int addr = DestAddr + recindex*256 ;
//把地址加出来
    unsigned char *intd = (unsigned char *)addr , no  ;
//转下
    memcpy( adata , intd , 230 ) ;
//直接memcpy()以内存读取的方式把flash的数据保存到内存中。230是你读取的数据长度,读取的数据长度是随意的,可以是1个也可以使256个,只要你个的内存可以放的下就行了
    return 1 ;     
}

这是写的代码:在下面是我自己整理的代码

/*
 *  Erase Sector in Flash Memory
 *    Parameter:      adr:  Sector Address
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseSector (unsigned long adr) {
  unsigned long n;

  n = GetSecNum(adr);                          // Get Sector Number

  IAP.cmd    = 50;                             // Prepare Sector for Erase
  IAP.par[0] = n;                              // Start Sector
  IAP.par[1] = n;                              // End Sector
  IAP_Call (&IAP.cmd, &IAP.stat);              // Call IAP Command
  if (IAP.stat) return (1);                    // Command Failed

  IAP.cmd    = 52;                             // Erase Sector
  IAP.par[0] = n;                              // Start Sector
  IAP.par[1] = n;                              // End Sector
  IAP.par[2] = CCLK;                           // CCLK in kHz
  IAP_Call (&IAP.cmd, &IAP.stat);              // Call IAP Command
  if (IAP.stat) return (1);                    // Command Failed

  return (0);                                  // Finished without Errors
}


/*
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,  1 - Failed
 */

int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
  unsigned long n;

#if SET_VALID_CODE != 0                        // Set valid User Code Signature
  if (adr == 0) {                              // Check for Vector Table
    n = *((unsigned long *)(buf + 0x00)) +
        *((unsigned long *)(buf + 0x04)) +
        *((unsigned long *)(buf + 0x08)) +
        *((unsigned long *)(buf + 0x0C)) +
        *((unsigned long *)(buf + 0x10)) +
        *((unsigned long *)(buf + 0x14)) +
        *((unsigned long *)(buf + 0x18));
    *((unsigned long *)(buf + 0x1C)) = 0 - n;  // Signature at Reserved Vector
  }
#endif

  n = GetSecNum(adr);                          // Get Sector Number

  IAP.cmd    = 50;                             // Prepare Sector for Write
  IAP.par[0] = n;                              // Start Sector
  IAP.par[1] = n;                              // End Sector
  IAP_Call (&IAP.cmd, &IAP.stat);              // Call IAP Command
  if (IAP.stat) return (1);                    // Command Failed

  IAP.cmd    = 51;                             // Copy RAM to Flash
  IAP.par[0] = adr;                            // Destination Flash Address
  IAP.par[1] = (unsigned long)buf;             // Source RAM Address
  IAP.par[2] = 1024;                           // Fixed Page Size
  IAP.par[3] = CCLK;                           // CCLK in kHz
  IAP_Call (&IAP.cmd, &IAP.stat);              // Call IAP Command
  if (IAP.stat) return (1);                    // Command Failed

  return (0);                                  // Finished without Errors
}

自由发挥的:

/*
块的选择
*/
int SelSector(unsigned char sec1,unsigned char sec2)
{
    flash_paramin[0] = IAP_SELECTOR;
    flash_paramin[1] = sec1;
    flash_paramin[2] = sec2;
    (*(void(*)())STAT_ADR)(flash_paramin,flash_paramout);
//STAT_ADR是需要查数据手册来确定地址的。就是一个地址
    return(flash_paramout[0]);  
}

//擦除
Int EraseSector(unsigned int sec1,unsigned int sec2)
{
    flash_paramin[0] = IAP_ERASESECTOR;
    flash_paramin[1] = sec1;
    flash_paramin[2] = sec2;
    flash_paramin[3] = IAP_FCCLK;
    (*(void(*)())STAT_ADR)(flash_paramin,flash_paramout);
    return(flash_paramout[0]);  
}

//写入
int RamToFlash(unsigned int dst, unsigned int src, unsigned int no)
{
    flash_paramin[0] = IAP_RAMTOFLASH;
    flash_paramin[1] = dst; 
    flash_paramin[2] = src;
    flash_paramin[3] = no;
    flash_paramin[4] = IAP_FCCLK;
    (*(void(*)())STAT_ADR)(flash_paramin,flash_paramout); 
    return(flash_paramout[0]);  
}

//比较
int flash_Compare(unsigned int dst, unsigned int src, unsigned int no)
{
    flash_paramin[0] = IAP_COMPARE; 
    flash_paramin[1] = dst;
    flash_paramin[2] = src;
    flash_paramin[3] = no;
    (*(void(*)())STAT_ADR)(flash_paramin,flash_paramout);
    return( flash_paramout[0]); 
}
//块的计算
unsigned long GetSecNum_6208 (unsigned long adr, unsigned char *firstflag) 
{
    unsigned long n ;

    *firstflag = 0 ;

    n = (adr >> 12) & 0x7F;                      // Pseudo Sector Number
    if (n >= 0x78) {                             // High Small 4kB Sectors
        n -= 0x62;

        // addr 
        if( (adr & 0xFFF) == 0 ) {
            *firstflag = 1 ;
        } 
    }
    else if (n >= 0x08) {                        // Large 32kB Sectors
        n = 0x07 + (n >> 3);

        // addr 
        if( (adr & 0x7FFF) == 0 ) {
            *firstflag = 1 ;
        } 
    }
    return (n);                                  // Sector Number
}


对于写入,可以直接看keil的库文件的写法。
    no = GetSecNum( addr, &firstflag );    
    if( firstflag ) {
        recode =SelSector( no , no);
        if(0 != recode) SerOutput("flash_SelSector 1 error\n");
        recode = EraseSector( no , no );
        if(0 != recode) SerOutput("flash_EraseSector error\n");
    }

    recode = Compare( addr, (uint32)&flash_SendData, FLASH_SEG_SIZE);
    if( 0 != recode ){
        no = GetSecNum( addr );

        recode = SelSector( no, no);
        if(0 != recode) SerOutput("flash_SelSector 2 error\n");

        recode = RamToFlash( addr , (uint32)&flash_SendData, FLASH_SEG_SIZE);
        if(0 != recode) SerOutput("flash_RamToFlash error\n");

        SerOutput("flash_Compare 1 ERROR\n");
    }
    else SerOutput("flash_Compare 1 SUCCESS\n");

以上内容全属原作者经验所结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值