打印

at91sam7s64可以读写自己的flash麽?

[复制链接]
5457|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
soulmate|  楼主 | 2008-1-2 16:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
soulmate|  楼主 | 2008-1-2 17:01 | 只看该作者

ddd

我想把串口采集来的数据保存在at91sam7s64内部的flash里面,有人做过麽
~

使用特权

评论回复
板凳
阿南| | 2008-1-2 17:49 | 只看该作者

没有做过,我想应该是不可以的

您可以这样去考虑(或是说寻找答案,实验):
1.先将程序复制到RAM(或映射的方法),然后在RAM中运行.
2.找到读写Flash的方法

使用特权

评论回复
地板
soulmate|  楼主 | 2008-1-2 18:55 | 只看该作者

但是下面这篇文章中好像提出了这个解决办法啊~

http://www.diybl.com/course/3_program/jdkf/20071215/92214.html

因为没有使用过,面临要不要制pcb版~很着急~

文章中的意思和阿南所说的意思类似~但没有详细一些的例子或结论~
一、AT91SAM7S系列芯片简介

AT91SAM7S系列控制器芯片是ATMEL公司推出的基于ARM内核的Flash闪存控制器芯片。其集成了ARM7TDMI ARM Thumb处理器,片内高速Flash存储器,片内高速SRAM,丰富的外设资源,包括一个USB2.0设备,使外部器件数目减至最低的完整系统功能集。这个芯片是那些正在寻求额外处理能力和更大存储器的8位处理器用户的理想选择。

AT91SAM7S系列芯片主要有AT91SAM7S64/AT91SAM7S128/AT91SAM7S256/AT91SAM7S512几种型号。它们之间主要的区别在于Flash和SRAM空间大小的不同,以适应不同产品应用的需要。


二、目标平台介绍和要实现的功能

平台主要实现一个移动电视USB Dongle的功能。外观类似于一个U盘,直接接到电脑或其它支持USB传输的移动设备上,配合视音频解码播放器即可实现移动电视的接收、播放功能。USB Dongleç”±Tuner、Demodulatorå’ŒAT91SAM7S64三个主芯片组成。Tuner实现空中高频信号到中频信号的转换,Demodulator实现信号的基带解调功能,AT91SAM7S64主要完成程序的控制以及将解调出的视音频数据向PC端传输。AT91SAM7S64包含一个64K的片内Flash和一个16K的片内SRAM。

目前平台使用了一块EEPROM用于存储CA(Conditional Access)的一些信息。主程序在Flash上运行,除去主程序占用的空间外,Flash上还留有较大的空间。目标是用实现用剩下的Flash空间替换原来的EEPROM,以节省产品的成本。

三、分散加载程序的实现

AT91SAM7S64的内部Flash只有一个Plane(目前该系列芯片只有AT91SAM7S512是Dual Plane的),在对其编程时不能在其上运行程序,所以对Flash进行编程时,程序必须调入RAM中运行。ATMEL网站上描述如下:

The AT91SAM7S device has only one flash memory plane, thus making impossible read-while-write operations. 

All write/erase flash routines must be run from the internal SRAM. Depending on the memory layout of the application, it will be preferable to disable all interrupts during write and erase operations.

If the exception vectors (and also ISR's) are kept in flash memory, and if IRQs are not disabled, the ARM core will make an access to the vector table located in the flash memory when an IRQ appears. If a write or an erase sequence is on-going at that time, it may lead to an unsuccessfull write or erase operation.

要实现这样的功能在IAR编译器上比较容易实现,只需要在函数定义之前用关键字__ramfunc声明即可。但在ADS上相对要麻烦很多,实现的方法有多种,这里只介绍其中两种。
第一、在启动代码中用汇编实现将存储在Flash上的程序全部Copy到SRAM中,然后再跳转到SRAM上运行。以下代码实现程序拷贝和地址重映射功能:

;------------------------------------------------

           ;copy bootloader in RAM

           LDR r0, =ramstart

           LDR r1, =bootsize

           LDR r2, =0

 

copy

           LDR r3, [r2]

           STR r3, [r2, r0]

           ADD r2, r2, #4

           SUBS r1, r1, #1

           BNE copy

 

           ;perform a RAM remap   

           LDR r0, =AT91C_BASE_MC

           LDR r1, =AT91C_MC_RCB

           STR r1, [r0, #MC_RCR]

;------------------------------------------------

第二、利用ADS分散加载程序的方法实现不同程序加载到不同的地址空间上运行。

由于AT91SAM7S64的片内SRAM只有16K的存储空间,而程序超过了16K,不能满足平台要求,所以用了第二种方法。要实现分散加载必须对AT91SAM7S64地址空间的分配比较清楚。下图列出了AT91SAM7S64的片内存储器映射关系,地址0x00000000在AT91SAM7S64的Remap之前是Flash的访问地址,Remap之后是SRAM的访问地址。




 

 äº†è§£AT91SAM7S64的片内存储器空间分配之后需要对自己的程序存放位置进行规划,以下是自定义的Scf文件(关于Scf文件格式参考另一篇文章“ADS下的分散加载文件应用实例”)。

ROM_LOAD 0x00100000

{

    ROM_EXEC 0x00100000

    {

        Cstartup.o (reset, +First)

        * (+RO)

    }

 

    RAM1 0x00200800

    {

        * (+RW,+ZI)

    }

    

    RAM2 0x00202800

    {

        flash.o (ramfunc)  ; å¯¹Flash编程的函数定义在该文件中

    }

}

利用分散加载方法需要自定义一个函数__user_initial_stackheap,否则编译器编译时会报错。__user_initial_stackheap定义如下:

#include <rt_misc.h>

__value_in_regs struct __initial_stackheap __user_initial_stackheap(

        unsigned R0, unsigned SP, unsigned R2, unsigned SL)

{

    struct __initial_stackheap config;

    

    //config.heap_base = (unsigned int)&bottom_of_heap; // defined in heap.s

                                                      // placed by scatterfile   

    config.stack_base = SP;   // inherit SP from the execution environment

 

    return config;

}

在<rt_misc.h>文件中你可以找到结构体__initial_stackheap的定义 
struct __initial_stackheap { 
unsigned heap_base; /* low-address end of initial heap */ 
unsigned stack_base; /* high-address end of initial stack */ 
unsigned heap_limit; /* high-address end of initial heap */ 
unsigned stack_limit; /* low-address end of initial stack */ 
};

设置编译器的链接方式为Scattered,选择自定义的scf文件,make成功。通过打印函数地址显示,Flash.c文件中定义的函数在SRAM里面运行,其它函数在Flash的地址空间中运行,在Flash中运行的函数调用SRAM中编程Flash的函数,读写正常。

 

 


使用特权

评论回复
5
soulmate|  楼主 | 2008-1-2 19:00 | 只看该作者

阿南~我拜读了您的at91san7s64调试笔记~

  第一次使用这颗芯片~pcb板子已经制了~现在发现就是遇到这个头大的问题了~也就是他能不能在flash中保存数据~
  我有大量的数据要想动态保存到flash里面~很是心急~

使用特权

评论回复
6
mr.king| | 2008-1-2 20:39 | 只看该作者

能放,但速度不快,象所有FLASH写都要时间一样,大量是不合适的

使用特权

评论回复
7
soulmate|  楼主 | 2008-1-2 21:02 | 只看该作者

呵呵~看到希望了~谢谢~

使用特权

评论回复
8
mohanwei| | 2008-1-2 21:16 | 只看该作者

挂一块AT24CXX啦……这么便宜

使用特权

评论回复
9
阿南| | 2008-1-3 18:59 | 只看该作者

如果是应用到产品,楼主可以找ATMEL原长或代理商的技术支持,

你的想法是否可行,及他们有没有这方面的资料.他们的几句话,可能让楼主忙好几天

使用特权

评论回复
10
Swd21ic| | 2008-1-3 20:30 | 只看该作者

!!!!

告诉你肯定能写..因为我就写了..  

不过你要老写就不好了..

一般Flash编程都要判忙的..几十ms.

DATASHEET上说了内部FLASH每页只能编程1万次...所以不安全的.

使用特权

评论回复
11
soulmate|  楼主 | 2008-1-3 20:43 | 只看该作者

唉~

  唉~都找过了~他们自己都没有用过~有的说不知道~有得翻翻书说不行~有的说没有这样用过~英贝德~英蓓特~atmel的代理等等我都问了~ 还是自己想办法解决吧~我只要知道别人能实现就可以了`

使用特权

评论回复
12
chunk| | 2008-1-4 11:19 | 只看该作者

可以写FLASH,

但是向AT91C_BASE_MC->MC_FCR写入命令的代码要放在RAM中,且此代码执行时不能有中断,除非中断服务程序也在RAM中。也就是说FLASH在写入时是不允许同时读取的。

好象IAR的编译器支持__ramfunc这样的扩展,ADS可以使用分散加载,或者你用C编写好WriteFlash函数,编译成汇编源码,把其中的一行处理一下:

        AREA ||.text||, CODE, READONLY    改为
        AREA ||.text||, CODE, READWRITE

以后直接使用这个汇编源码就行了。

使用特权

评论回复
13
wenchang| | 2008-1-6 12:37 | 只看该作者

可以,我就这么做的!

        RSEG ICODE:CODE
        CODE32

        PUBLIC  IFlash_Write_Page

;--------------------------------------------------------------------;BOOL IFlash_Write_Page(unsigned int page, unsigned int *buff)
IFlash_Write_Page:
        SUB      sp,sp,#4
        STMFD    sp!,{r0-r3,lr}
L0_16:
        LDR      r1,=L1_00
        LDR      r2,=L1_88
        ADD      r2,r2,#4
        SUB      r0,r2,r1
        SUB      r0,sp,r0
        STR      r0,[sp,#20]
L0_36:
        LDMIA    r1!,{r3}
        STMIA    r0!,{r3}
        CMP      r1,r2
        BCC      L0_36
        LDMFD    sp!,{r0-r3,lr}

        LDMFD    sp!,{pc}            ;Goto ram for write IFLASH

L1_00:
        MOV      r2,#0x100000        ;IFLASH_ADDR_START: 0x100000
        ADD      r3,r2,r0,LSL #8     ;IFLASH_PAGE_SIZE: 64dword = 256byte
        MOV      r2,#0
L1_12:
        LDR      r12,[r1],#4
        ADD      r2,r2,#1
        CMP      r2,#0x40
        STR      r12,[r3],#4
        BCC      L1_12

        MOV      r1,#0x00480000      ;MCLK = 48M, FMCN = 72
        ORR      r2,r1,#0x100
        MOV      r1,#0
        STR      r2,[r1,#-0xa0]

        LDR      r1,L1_88
        AND      r0,r1,r0,LSL #8
        ORR      r0,r0,#1
        ORR      r0,r0,#0x5a000000
        MOV      r1,#0
        STR      r0,[r1,#-0x9c]
L1_56:
        LDR      r0,[r1,#-0x98]
        TST      r0,#1
        BEQ      L1_56

;       LDR      r0,[r1,#-0x98]
        TST      r0,#0xc
        MVNEQ    r0,#0
        MOVNE    r0,#1

        BX       lr
L1_88:
        DCD      0x0003ff00

;--------------------------------------------------------------------        PUBLIC  ARMDisableInt
ARMDisableInt:
        STMFD   sp!, {r0}
        MRS     r0, CPSR
        ORR     r0, r0, #0x80
        MSR     CPSR_cxsf, r0
        LDMFD   sp!, {r0}
        BX      lr

        PUBLIC  ARMEnableInt
ARMEnableInt:
        STMFD   sp!, {r0}
        MRS     r0, CPSR
        BIC     r0, r0, #0x80
        MSR     CPSR_cxsf, r0
        LDMFD   sp!, {r0}
        BX      lr

;--------------------------------------------------------------------        END


根据你使用的编译工具和芯片做简单修改吧,这里提供思想方法!

使用特权

评论回复
14
hotpower| | 2008-1-6 12:39 | 只看该作者

IAP现在的ARM估计都有此功能~~~

使用特权

评论回复
15
janusz| | 2008-1-18 16:19 | 只看该作者

at91sam7s64可以读写自己的flash麽?

LZ如果不介意的话,可以发个EMAIL过来.janus@baite-group.com.
我们是ATMEL ARM产品线最强的代理.有相当的技术支持及研发能力.

使用特权

评论回复
16
soulmate|  楼主 | 2008-1-25 14:07 | 只看该作者

我已经做成功了~

 贴上来~给有需要的人~
 NND~几句破代码,被搞得神神秘秘的~鄙视一下~
 __ramfunc void Read_Page(int Page_Number,int *Buffer,int len)
{
  unsigned int  *Flash_Address;
  int i;  
  
  Flash_Address = ( unsigned int  * )( 0x100000+Page_Number*256 );
  
  //每次读是一个字,四个字节
  for( i = 0; i < len; i++ )
  {
    Buffer[ i ] = *( Flash_Address + i )  ;
  }
  
}  

__ramfunc int Write_Page( int Page_Number,int *Buffer,int len)
{
  unsigned int  *Flash_Address;
  int i;  
  
  AT91C_BASE_MC->MC_FMR = ( ( 72 ) << 16 ) | AT91C_MC_FWS_1FWS  ;  //编程前页擦除
  AT91C_BASE_MC->MC_FCR = ( 0x5A << 24 ) | ( ( Page_Number << 8 ) & AT91C_MC_PAGEN) | AT91C_MC_FCMD_UNLOCK ;//解锁 
  
  while ( ( AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY) != 1 );    

  Flash_Address = ( unsigned int  * )( 0x100000+Page_Number*256 );
    
  //每次写是一个字,四个字节
  for( i = 0; i < len; i++ )
  {
    *( Flash_Address + i ) = Buffer[ i ];
  }
  
  if( ( AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY) != 1 )
  {  
    return -1;
  }    
  
  
  
  AT91C_BASE_MC->MC_FCR = ( 0x5A << 24 ) | ( ( Page_Number << 8 ) & AT91C_MC_PAGEN) | AT91C_MC_FCMD_PROG_AND_LOCK ;    //编程及锁定
  
  while( 1 )
  {   
    if( AT91C_BASE_MC->MC_FSR & 0x01 )
    { 
      if( AT91C_BASE_MC->MC_FSR & AT91C_MC_LOCKE )
      {
        return -1;
      }
      if( AT91C_BASE_MC->MC_FSR & AT91C_MC_PROGE )
      {    
        return -1;
      }
      
      break;
 
    }
  }
  
  return 1;
} //Write_Page

使用特权

评论回复
17
mxh0506| | 2008-1-26 22:27 | 只看该作者

楼上是个爽快人,佩服!

使用特权

评论回复
18
Swd21ic| | 2008-1-27 18:54 | 只看该作者

Re

楼主,太搞笑.
我已经告诉你可以了..
还问来问去的..

如果Atmel的技术支持说不可以的话我严重怀疑是不是沟通有问题.

使用特权

评论回复
19
numlong| | 2008-1-27 19:24 | 只看该作者

soulmate 顶!赞一个1

使用特权

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

本版积分规则

33

主题

145

帖子

1

粉丝