天嵌 ARM开发社区

 找回密码
 注册
查看: 3530|回复: 3

2440读写Nor flash(EN29LV160AB)写入失败

[复制链接]
ftk_vb 发表于 2014-12-15 21:55:07 | 显示全部楼层 |阅读模式
哪位朋友用过EN29LV160AB,即TQ2440开发板配套Nor Flash。最近想学习一下Flash操作,用ADS1.2写了一个简单的测试程序,将bin文件通过Hjtag烧写到Nor flash中,发现写入失败。
主要程序如下:
  1. void Test_NorFlash(void)
  2. {
  3.         U32 EonID, FlashAddr, RdStartAddr,WrStartAddr=0xf0000;        //32K
  4.         U16 i,WrLen=0x20, WrErrNum=0;
  5.         U16 dat=0, RdLen=32, Rddata;
  6.         U8 j=0;
  7.        
  8.         RdStartAddr = WrStartAddr;
  9.         FlashAddr = WrStartAddr;
  10.        
  11.         EonID = EN29LV160AB_GetID();
  12.        
  13.         Uart_Printf("芯片ID:%x\n", EonID);
  14.        
  15.         EN29LV160AB_Reset();                //must write the reset
  16.         Delay(100);
  17.         /*if(!EN29LV160AB_ChipErase())        //Erase fail
  18.         {
  19.                 Uart_Printf("Chip Erase fail!\n");
  20.         }*/
  21.        
  22.         Uart_Printf("Start test Word Program...\n");
  23.         for(i=0; i<WrLen; i++)                                                         //Write data
  24.         {
  25.                 if((FlashAddr % 0x8000) == 0x0)                //32K
  26.                 {
  27.                         if(!EN29LV160AB_SectorErase(FlashAddr))//擦除貌似没什么问题
  28.                         {
  29.                                 Uart_Printf("Erase Sector %x Fail!\n", FlashAddr);
  30.                                 return;
  31.                         }
  32.                 }
  33.                
  34.                 if(!EN29LV160AB_WordProg(FlashAddr, dat))
  35.                 {
  36.                         WrErrNum++;
  37.                 }

  38.                 FlashAddr++;
  39.                 dat++;
  40.                 for(j=0; j<100; j++);
  41.         }
  42.        
  43.         Uart_Printf("Start test Read Chip...\n");                //Read data
  44.         FlashAddr = RdStartAddr;
  45.         for(i=0; i<RdLen; i++)
  46.         {
  47.                 Rddata = EN29LV160AB_Read(FlashAddr);
  48.                 FlashAddr++;       
  49.                 Uart_Printf("%-10x", Rddata);
  50.         }
  51.        
  52.         Uart_Printf("\nEN29LV160AB test finish! WrERR = %-10x\n", WrErrNum);
  53.         return;
  54. }
复制代码
我写的一些基础操作

  1. /*
  2. Vendor:        EON
  3. PartNo:        EN29LV160AB
  4. Type:        Nor FLASH
  5. Sector:        35
  6.                 BYTE:        1        2        1        31
  7.                                 16K        8K        32K        64K
  8.                 Word:        1        2        1        31
  9.                                 8K        4K        16K        32K
  10. Size:        2M
  11. ID:                0x2249001C
  12. Width:        byte/word
  13. */
  14. #define __EN29LV160_H

  15.         #include "../inc/EN29LV160AB.h"

  16. #undef __EN29LV160_H

  17. /**********
  18. 功能:读取存储器
  19. 参数:
  20. *************/
  21. U16 EN29LV160AB_Read(U32 addr)
  22. {
  23.        return *((volatile U16 *)(addr));
  24. }

  25. /**********
  26. 功能:软件复位存储器
  27. 参数:
  28. *************/
  29. void EN29LV160AB_Reset(void)
  30. {
  31.         *((volatile U16 *)0x00) = 0xf0;
  32. }

  33. /**********
  34. 功能:写入存储器
  35. 参数:addr:地址
  36.           dat:数据
  37. *************/
  38. void Writeflash( U32 addr,U16 dat )
  39. {
  40.         addr = addr << 1;
  41.         *((volatile U16 *)addr) = dat;

  42. }


  43. /**********
  44. 功能:等待结束
  45. 参数:
  46. 返回:1-正常结束  0-失败
  47. *************/
  48. U8 Waitfor_endofprg(void)
  49. {
  50.         volatile U16 waitno=0;
  51.         volatile U32 Old_status, New_status;
  52.         Old_status = *((volatile U16 *)0x00);                //read first
  53.         while(1)
  54.         {
  55.                 New_status = *((volatile U16 *)0x00);        //read second
  56.                 if((Old_status & 0x40) == (New_status & 0x40))        //DQ6=Toggle?
  57.                 {       
  58.                         break;                                //pass
  59.                 }
  60.                 //waitno++;
  61.                 if(New_status & 0x20)         //DQ5 = 1
  62.                 {
  63.                         Old_status = *((volatile U16 *)0x00);                //read first
  64.                         New_status = *((volatile U16 *)0x00);                //read second
  65.                         if((Old_status & 0x40) == (New_status & 0x40))        //DQ6=Toggle?
  66.                         {       
  67.                                 break;                                //pass
  68.                         }
  69.                         else
  70.                                 return 0;                        //fail
  71.                 }
  72.                 Old_status = New_status;
  73.         }
  74.         //Uart_Printf("%x", waitno);
  75.         return 1;
  76. }

  77. /**********
  78. 功能:芯片擦除
  79. 参数:
  80. 返回:1-正常结束  0-失败
  81. *************/
  82. U8 EN29LV160AB_ChipErase(void)
  83. {
  84.         Writeflash(0x555, 0xAA);
  85.         Writeflash(0x2AA, 0x55);
  86.         Writeflash(0x555, 0x80);
  87.         Writeflash(0x555, 0xAA);
  88.         Writeflash(0x2AA, 0x55);
  89.         Writeflash(0x555, 0x10);
  90.        
  91.         return Waitfor_endofprg();       
  92. }

  93. /**********
  94. 功能:扇区擦除
  95. 参数:SAaddr:地址(对应扇区)
  96. *************/
  97. U8 EN29LV160AB_SectorErase(U32 SAaddr)
  98. {
  99.         Writeflash(0x555, 0xAA);
  100.         Writeflash(0x2AA, 0x55);
  101.         Writeflash(0x555, 0x80);
  102.         Writeflash(0x555, 0xAA);
  103.         Writeflash(0x2AA, 0x55);
  104.         *((volatile U16 *)SAaddr)=0x30;

  105.         return Waitfor_endofprg();       
  106. }

  107. /**********
  108. 功能:写入双字
  109. 参数:addr:地址
  110.           dat:数据
  111. *************/
  112. U8 EN29LV160AB_WordProg(U32 addr,U16 dat)
  113. {
  114.         Writeflash(0x555, 0xAA);
  115.         Writeflash(0x2AA, 0x55);
  116.         Writeflash(0x555, 0xA0);
  117.         Writeflash(addr, dat);
  118.        
  119.         return Waitfor_endofprg();               
  120.        
  121. }


  122. /**********
  123. 功能:读取存储器ID
  124. 参数:
  125. 返回:ID
  126. 备注:AutoSelect Command程序执行结束,必须复位才能进行读写操作
  127. *************/
  128. U32 EN29LV160AB_GetID(void)
  129. {
  130.         U32 temp;
  131.        
  132.         Writeflash(0x555, 0xAA);
  133.         Writeflash(0x2AA, 0x55);
  134.         Writeflash(0x555, 0x90);
  135.        
  136.         temp = (*(volatile unsigned short *)(0x1<<1))<<16;        //A1->A0. Left shift
  137.     temp |= *(volatile unsigned short *)(0x100<<1);
  138.        
  139.         return temp;
  140. }


复制代码
串口调试信息及技术手册相关部分,如图



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| ftk_vb 发表于 2014-12-16 08:29:12 | 显示全部楼层
自己顶一个。就是测试开发板上的Nor flash
回复

使用道具 举报

 楼主| ftk_vb 发表于 2014-12-16 13:48:10 | 显示全部楼层
找到原因了,EN29LV160AB_Read(U32 addr)函数中少了地址移位addr = addr << 1;,难怪读出来全是0xFFFF。
回复

使用道具 举报

 楼主| ftk_vb 发表于 2014-12-17 15:09:16 | 显示全部楼层
又发现一个错误 EN29LV160AB_SectorErase(U32 SAaddr)中,*((volatile U16 *)SAaddr)=0x30第6命令序列地址没有左移一位,应改为Writeflash(SAaddr, 0x30)。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号-2 )

GMT+8, 2025-8-21 13:00 , Processed in 2.057548 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表