打印
[ARM入门]

norflash 驱动

[复制链接]
1011|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xishuidemian|  楼主 | 2016-3-10 09:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
想法是这样的,利用norflash中未用的sector保存运行数据。
实验:
1、芯片:s3c2440,norflash:en29lv160ab。裸机程序在ADS1.2中编译,完成读取ID,擦除,写,读,代码基本是网上的。
2、将附件中的代码通过JLINK焼写进norfalsh,从norflash启动。
3、很长时间(十几分钟)才出现显示结果,结果正确。

请大家帮我看看是什么问题。

相关帖子

沙发
xishuidemian|  楼主 | 2016-3-10 09:07 | 只看该作者
//======================================================================
//        功能描述:        EN29LV160AB操作

//        硬件连接:       
//                               

//        维护记录:        2016.3.9
          
//  实验结果:        没反应,有时等待很长(数十分钟)时间可能显示结果(实验基本失败)
//======================================================================

#include "2440addr.h"
#include "def.h"
#include <string.h>
#include "uart.h"
#include "gpio.h"

#define _ISR_STARTADDRESS         0x33ffff00



#define flash_base 0x00000000
#define CMD_ADDR0 *( (volatile U16 *)((0x555<<1)+flash_base) )
#define CMD_ADDR1 *( (volatile U16 *)((0x2aa<<1)+flash_base) )

#define sector_5_base ( ((0x20000<<1)+flash_base) )
#define sector_5_size 32000

#define sector_33_base ( ((0xf0000<<1)+flash_base) )
#define sector_33_size 32000

U8 en29lv160ab_check_toggle(void);
U8 en29lv160ab_sector_erase(U32 section_addr);
U8 en29lv160ab_chip_erase(void);
U8 en29lv160ab_program(U32 addr,U16 dat);
U16 en29lv160ab_read(U32 addr);
void en29lv160ab_reset(void);
U32 en29lv160ab_id(void);
void delay_ms(int t);

//测试
int Main(void)
{

        U16 while_i = 0;//循环次数
        U32 i;
        U32 id = 0;
        U16 tem = 0;
       
       
        Uart0_Init(115200);//串口初始化
        Gpio_Init();
       
        //读ID号
        LED_ON;
        id = en29lv160ab_id();
        LED_OFF;
       
        en29lv160ab_reset();
        delay_ms(500);
       
       
        Uart0Printf("EN29LV160AB的ID号为:%x\r\n",id);
       
        while(1)
        {
                while_i++;
                if(while_i > 1)
                {
                        while_i = 1;
                }
                else
                {
                        //擦除sector
                        tem = en29lv160ab_sector_erase(sector_33_base);
                        if(tem == 0)
                        {
                                Uart0Printf("sector_33 擦除失败!\r\n");
                        }
                        else
                        {
                                Uart0Printf("sector_33 擦除成功!\r\n");

                                for(i=0;i<32000;i++)
                                {
                                        Uart0Printf("%x\r\n",en29lv160ab_read(sector_33_base+(i<<1)));
                                }
                                //写操作
                                for(i=0;i<32000;i++)
                                {
                                        en29lv160ab_program(sector_33_base+(i<<1),i);
                                }
                                //读操作
                                for(i=0;i<32000;i++)
                                {
                                        Uart0Printf("%x\r\n",en29lv160ab_read(sector_33_base+(i<<1)));
                                }
                        }       
                }
        }
       
        return 0;
}

//check_toggle
U8 en29lv160ab_check_toggle(void)
{
        volatile U16 newtoggle;
        volatile U16 oldtoggle;
       
        while(1)
        {
                newtoggle = *( (volatile U16 *)0x0 );
                if( (oldtoggle&0x40) == (newtoggle&0x40) ) //DQ6
                        break;
                       
                if(newtoggle & 0x20)//DQ5
                {
                        oldtoggle = *((volatile U16 *)0x0);
                        newtoggle = *((volatile U16 *)0x0);
                       
                        if( (oldtoggle & 0x40) == (newtoggle & 0x40) )
                                break;
                        else
                                return 0;//错误
                }
                oldtoggle = newtoggle;
        }
        return 1;//正确
}

//sector擦除
U8 en29lv160ab_sector_erase(U32 section_addr)
{
        CMD_ADDR0 = 0xaa;
        CMD_ADDR1 = 0x55;
        CMD_ADDR0 = 0x80;
        CMD_ADDR0 = 0xaa;
        CMD_ADDR1 = 0x55;
       
        *( (volatile U16 *)(section_addr) ) = 0x30;
       
        return en29lv160ab_check_toggle();
}

//chip擦除
U8 en29lv160ab_chip_erase(void)
{
        CMD_ADDR0 = 0xaa;
        CMD_ADDR1 = 0x55;
        CMD_ADDR0 = 0x80;
        CMD_ADDR0 = 0xaa;
        CMD_ADDR1 = 0x55;
        CMD_ADDR0 = 0x10;
       
        return en29lv160ab_check_toggle();
}

//写操作
U8 en29lv160ab_program(U32 addr,U16 dat)
{
        CMD_ADDR0 = 0xaa;
        CMD_ADDR1 = 0x55;
        CMD_ADDR0 = 0xa0;
       
        *( (volatile U16 *)(addr) ) = dat;
       
        return en29lv160ab_check_toggle();
}

//读操作
U16 en29lv160ab_read(U32 addr)
{
        return *( (volatile U16 *)(addr) );
}

//软件复位
void en29lv160ab_reset(void)
{
        *( (volatile U16 *)0x0 ) = 0xf0;
}

//读取ID,高2个字节为设备ID,低两个字节为芯片ID
U32 en29lv160ab_id(void)
{
        U32 temp = 0;
       
       
        CMD_ADDR0 = 0xaa;
       
        CMD_ADDR1 = 0x55;
       
        CMD_ADDR0 = 0x90;
       
        temp = (*( (volatile U16 *)(flash_base+(0x100<<1)) ))<<16;
       
        CMD_ADDR0 = 0xaa;
       
        CMD_ADDR1 = 0x55;
       
        CMD_ADDR0 = 0x90;
        temp += (*(volatile U16 *)(flash_base+(0x1<<1)));
       
        return temp;
}
//延时
void delay_ms(int t)
{
        int i,j;
        for(i=0;i<t;i++)
        {
                for(j=0;j<1000;j++)
                {
                        ;
                }
        }
}












使用特权

评论回复
板凳
xishuidemian|  楼主 | 2016-3-10 09:14 | 只看该作者
实验结果:
1、在读ID的时候要等很长时间(几分钟)
2、从结果看,擦除没有问题
3、从写入和读出的数据看,有对也有错,呈现规律。00~3F对,40~7F错,然后循环。如
30
31
32
33
34
35
36
37
38
39
3a
3b
3c
3d
3e
3f
40
ffff
42
ffff
44
ffff
46
ffff
48
ffff
4a
ffff
4c
ffff
4e
ffff
50
ffff

使用特权

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

本版积分规则

15

主题

43

帖子

0

粉丝