服务热线 ( tel ) :
13615027669
联系我们

国晶(福州)光伏有限公司

电话:13615027669 / 13860667676

邮箱:972105035@qq

邮编:350000

地址:福州晋安区五四北泰禾广场3#-1625

当前位置:首页 > 行业动态 > 太阳能光伏发电的广泛应用范围 行业动态

太阳能光伏发电的广泛应用范围

时间:[2018-01-12]

太阳能光伏发电的广泛应用范围:

1.用户太阳能电源:(1)小型电源10-100W不等,用于偏远无电地区如高原、海岛、牧区、边防哨所等军民生活用电,如照明、电视、收录机等;(2)3-5KW家庭屋顶并网发电系统;(3)光伏水泵:解决无电地区的深水井饮用、灌溉。

2.交通领域:如航标灯、交通/铁路信号灯、交通警示/标志灯、路灯、高空障碍灯、高速公路/铁路无线电话亭、无人值守道班供电等。

3.通讯/通信领域:太阳能无人值守微波中继站、光缆维护站、广播/通讯/寻呼电源系统;农村载波电话光伏系统、小型通信机、士兵GPS供电等。

4.石油、海洋、气象领域:石油管道和水库闸门应急保护太阳能电源系统、石油钻井平台生活及应急电源、海洋检测设备、气象/水文观测设备等。

5.家庭灯具电源:如庭院灯、路灯、手提灯、野营灯、登山灯、垂钓灯、黑光灯、割胶灯、节能灯等。

6.光伏电站:10KW-50MW独立光伏电站、风光(柴)互补电站、各种大型停车厂充电站等。

7.太阳能建筑:将太阳能发电与建筑材料相结合,使得未来的大型建筑实现电力自给,是未来一大发展方向。

8.其他领域包括:(1)与汽车配套:太阳能汽车/电动车、电池充电设备、汽车空调、换气扇、冷饮箱等;(2)太阳能制氢加燃料电池的再生发电系统;(3)海水淡化设备供电;(4)卫星、航天器、空间太阳能电站等。

目前美国、欧洲各国特别是德国及日本、印度等都在大力发展太阳电池应用,开始实施的"十万屋顶"计划、"百万屋顶"计划等,极大地推动了光伏市场的发展,前途十分光明。


?
  • 主页
  • 彩民资料论坛
  • 红姐资料论坛
  • 钱多多六合资料
  • 主页 > 钱多多六合资料 >

    ARM系列之分散加载描述符(scatte)文件的应用

      发布时间:2019-05-12 02:28

      使用分散加载,可以将用户定义的结构体或代码定位到指定物理地址上的外设,这种外设可以是定时器、实时时钟、静态SRAM或者是两个处理器间用于数据和指令通信的双端口存储器等。在程序中不必直接访问相应外设,只需访问相应的内存变量即可实现对指定外设的操作,因为相应的内存变量定位在指定的外设上。这样,对外设的访问看不到相应的指针操作,对结构体成员的访问即可实现对外设相应存储单元的访问,让程序员感觉到仿佛没有外设,只有内存。

      例如,一个带有两个32位寄存器的定时器外设,在系统中的物理地址为Ox04000000,其C语言结构描述如下:

      要使用分散加载将上述结构体定位到Ox04000000的物理地址,可以将上述结构体放在一个文件名为timer_regs.c中,并在分散加载文件中指定即可,如下:

      分散加载机制在提供将指定代码和数据定位在指定物理地址的能力的同时,也提供了一种代码分割机制可以将指定的零初始化段(ZI段)从可执行代码中分离出来。这样最终生成的烧入ROM或Flash中的镜像文件就不包括那部分分割了的零初始化段,即使该零初始化段再大,也不影响最终生成的镜像文件的大小。但不采用分散加载机制,零初始化段在编译连接后是直接生成到镜像文件中的。它的大小直接影响最终要烧写的文件的大小,且零初始化段的大小还取决于内存的大小,它不能大到超过内存的大小;而采用分散加载机制,可以将某个零初始化段定位到非内存地址的一个存储器外设上,如NVRAM(非易失性随机存储器)。

      笔者曾在一个实际工程中采用这种分散加载机制,将一个2MB的结构体数组定位到外部NVRAM中,用于记录设备在工作过程中采集到的数据;而在本系统中,ARM处理器的内存只有256 KB,Flash存储器也只有2 MB。如果不采用分散加载,程序根本无法运行,也不能烧写到Flash中。

      采用分散加载,把对复杂外设的访问变成对结构体数组的访问,使程序代码精简易懂。对程序员来说,对结构体数组的操作还是和内存变量的操作一样的。

      3. 某些特殊应用,需要将代码段或者数据段的部分放置在指定位置,方便更新,或者其他加密等原因。

      4. 某些特殊应用,需要固定函数地址的时候,可以将那个函数放于固定的区域,而不管其他程序有误变化。

      5. 对于程序中的一些配置型的变量,可能需要集中放置在一个区域,方便下次直接更新那块存储空间。

      下面着重描述分散描述符的写法,分散描述文件的类型为 .scf 。写完后,可以通过ADS进行加载。

      在实际的嵌入式系统中,ADS提供的缺省存储器映射是不能满足要求的。用户的目标硬件通常有多个存储器设备位于不同的位置,并且这些存储器设备在程序装载和运行时可能还有不同的配置。

      Scattertoading可以通过一个文本文件来指定一段代码或数据在加载和运行时在存储器中的不同位置。这个文本文件scatterfile在命令行中由-scatter开关指定,例如:

      在scatterfile中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,Scatlertoading的存储区块可以分成二种类型:

      执行区:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。

      映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。在系统启动时,C函数库中的__main初始化代执行必要的复制及清零操作,使应用程序的相应代码和数据段从装载状态转入执行状态。

      每个块由一个头标题开始定义,头中至少包含块的名字和起始地址,另外还有最大长度和其他一些属性选项。块定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。

      一个执行块必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。

      图8所示样例中,只有一个加载块,包含了所有的代码和数据,起始地址为0。这个加载块一共对应两个执行块。一个包含所有的RO代码和数据,执行地址与装载地址相同;同时另一个起始地址为0x10000的执行块,包含所有的RW和ZI数据。这样当系统开始启动时,从第一个执行块开始运行(执行地址等于装载地址),在执行过程中,有一段初始化代把装载块中的一部分代码转移到另外的执行块中。

      在大多数应用中,并不是像前例那样,简单地把所有属性都放在一起,用户需要控制特定代码和数据段的放置位置。这可以通过在scatter文件中对单个目标文件进行定义实现,而不是只简单地依靠通配符。

      为了覆盖标准的连接器布局规则,我们可以使用+FIRST和+LAST分散加载指令。典型的例子是在执行块的开始处放置中断向量表格:

      根区是一个执行块,它的加载地址与执行地址是一致的。每个scatter文件至少有一个根区。分散加载有一个限制:创建执行块的代码和数据(即完成复制和清零的代码和数据)无法自行复制到另一个位置。因此,在根区中必须含有下面的部分:

      由于上面两个部分的属性是只读的,因此他们被*〈+RO〉通配符语法匹配。如果*〈+RO〉被用在了非根区中,则在根区中必须显式地指明另一个RO区域。

      Scatterloading机制提供了一种指定代码和静态数据布局的方法。下面介绍如何放置应用程序的堆栈和heap。

      应用程序的堆栈和heap是在C库函数初始化过程中建立起来的。可以通过重定向对应的子程序来改变堆栈和heap的位置,在ADS的库函数中,即_user_initial_stackheap()函数。

      当用户使用分散装载功能的时候,必须重调用_user_initial_stackheap(),否则连接器会报错:

      ADS提供了两种实时存储器模型。缺省时为one-region,应用程序的堆栈和heap位于同一个存储器区块,使用的时候相向生长,当在heap区分配一块存储器空间时需要检查

      堆栈指针。另一种情况是堆栈和heap使用两块独立的存储器区域。对于速度特别快的RAM,可选择只用来作堆栈使用。为了使用这种two-region模型,用户需要导入符号use_two_region_memory,heap使用需要检查heap的长度限制值。对这两种模型来说,缺省情况下对堆栈的生长都不进行检查。用户可以在程序编译时使用 -apcs/swst 编译器选项来进行软件堆栈检查。如果使用two-region模型,必须得在执行_user_initial_stackheap时指定一个堆栈限制值。

      图10中显示了一个基于ARM的嵌入式系统的基本初始化过程。可以看到,在_main之前加入了一个复位处理模块reset handler,它在系统上电复位时立即启动。标识为$sub$$main的新代码块在进入主程序之前执行。

      复位处理模块reset handler通常是一小段汇编代码,在系统复位时执行。它至少完成应用程序中使用到的所有处理器模式的堆栈初始化工作。对于含有本地存储器系统的内核(比如含cache的ARM内核),配置工作也必须在这一段初始化过程中完成。当完成系统初始化之后,通常程序会跳向_main,开始C库函数的初始化过程。

      系统初始化过程一般还包括另外一些内容,中断使能等,这些大多安排在C库函数的初始化完成之后执行。$sub$$main()完成这部分功能。

      所有的ARM系统都有一张中断向量表当出现异常需要处理时,必须调用向量表。向量表一般要位于0地址处。

      一种简单的方法,就是把系统0x0000开始的一块地址分配给ROM。其缺点是,由于ROM的访问速度比RAM慢很多,当执行中断响应需要从中断向量表跳转时,会给系统性能带来损失;同时,在ROM中的向量表内容也不能被用户程序动态修改。

      另外一种可行的方案如图11所示。ROM位于地址0x1000开始的地方,但是在系统复位时又被存储器映射到0x0000地址处。这样当系统启动之后,在地址0x0000看到的是ROM,系统执行这块ROM中的启动代码,启动代码跳转到真正的ROM的地址,并让存储器移除对ROM的地址映射。这时0x0000地址处的存储器又恢复回了RAM。__main中的代码把向量表copy到0x0000处的RAM中去,使得异常时能被正确响应。

      表1为ARM汇编中执行ROM/RAM重定向和映射的一个例子。它以ARM公司的Integrator平台为基础的,该方法适用于类似ROM/RAM重定向方法的所有平台。第一条指令完成从ROM的映射地址(0x00000)到真实地址的跳转。地址标号instruct_2是ROM的线)。然后通过设置Integrator平台上的相应控制寄存器,移除ROM的地址映射。代码在系统一启动就被执行。所有关于地址重定向/映射的操作必须在C库函数初始化之前完成。

      许多ARM处理器都有片上存储器系统,如cache和紧密耦合存储器(TCM)、存储器管理单元(MMU)或存储器保护单元(MPU)。这些设备都要在系统初始化过程中正确配置,并且有一些特殊的要求需要考虑。

      由前文可知,_main中的C库函数初始化代码负责程序运行时的存储器系统设置。因此,整个存储器系统本身必须得在__main之前完成初始化工作,如MMU或MPU必须在reset handler里面完成配置。

      紧密耦合存储器(TCM)的初始化同样须在_main之前完成(通常在MMU/MPU之前),因为一般程序都需要把代码和数据分散装入TCM。需要注意的是当TCM被使能后,不再访问被TCM屏蔽的存储器。

      关于cache的一致性问题,如果cache在_main之前使能的话,那么当_main里面进行从装载区到执行区的代码和数据拷贝时(因为在拷贝过程中指令和数据在本质上都是被当作数据处理),指令会出现在数据缓冲区。避免此问题的方法是在C库函数初始化完成后再使能cache。

      无论是通过ROM/RAM重定向还是MMU配置的方法,如果系统在启动和运行时存储器分布不一致,scatterloading文件中的定义就要按照系统重定向后的存储器分布情况进行。

      在表2中,堆栈位于stack_base标识的地址中。这个符号可以是存储器系统中的一个直接地址,也可以在另外的汇编文件中定义,由scatter文件来定义分配地址。表2代码为FIQ和IRQ模式各分配了一个256字节的堆栈,用户可以用同样的方法为其他模式也分配堆栈。最简单的方法就是进入相应的模式,然后为SP寄存器指定相应的值。如果想使用软件堆栈检查,还必须指定一个堆栈长度限制值。

      一般来说,应该把所有的系统初始化代码与主应用程序分离开来,但是有几个例外,比如cache和中断的使能,需要在C库函数初始化之后执行。

      许多在启动过程中使用到的功能,如MMU/MPU的配置、中断的使能等,只能在特权级模式下进行。如果需要在特权极模式下运行自己的应用程序,只要在退出初始化过程之前改变到相应的模式就行了,没有其他任何问题。

      如果使用user模式,必须保证所有只能在特权模式下执行的功能完成之后,才能进入user模式。因为system模式和user模式使用相同的寄存器组,reset handler应该从system模式退出,_user_initial_stackheap在system模式下完成应用程序堆栈的初始化。这样在处理器进入user模式后,所有的堆栈空间都已经被正确设置好了。

      虽然可以在一个scatter文件中描述代码和数据的分散布局,但是目标硬件中的外设寄存器,堆栈和heap配置仍然直接采用硬件地址在程序源代码中进行设置。如果把所有存储器地址相关的信息都在scatter文件中进行定义,避免在源文件中引用绝对硬件地址,对程序的工程化管理是有大好处的。

      通常外设寄存器的地址在程序文件或头文件中定义,也可以声明一个结构类型指向外设寄存器,结构的地址定位在scatter文件中完成。

      举例来说,目标定时器上有2个32位的寄存器,可以用表4来映射这些寄存器。为了把结构放置在指定的存储器地址上面,创建一个新的执行区(见表5)。scatter文件便把timer_regs结构定位在了地址0x40000000。

      注意,在启动过程当中这些寄存器的内容不需要清零,改变寄存器的内容可能影响系统状态。在执行区上加UNINIT属性可以防止ZI数据在初始化过程中被清零。

      在许多情况下,用scatter文件来定义堆栈和heap的地址会带来一些好处,主要有:所有的存储器分配信息集中在一个文件里;改变堆栈和heap的地址只要重新连接就行了,不需要重新编译。

      在ADS1.2环境下,这是最简单的方法。在前文中引用过2个符号stack_base和heap_base,这2个符号在汇编模块中创建,在scatter文件中各自的执行区里定位(见表6)。

      表7文件中,heap基地址定位在0x20000上,堆栈基地址位于0x40000。现在heap和堆栈的位置就可以非常方便地进行编辑了。

      这种方法需要在目标文件中指定好heap和堆栈的长度。这在一定程度上减弱了本节开头描述的两个优点。

      首先在汇编源程序中定义heap和堆栈的长度。关键词SPACE用来保留一块存储器空间,NOINT则可以阻止清零操作(见表8)。注意在这里的源文件中并不需要地址标号。

      然后这些部分就可以在scatter文件中对应的执行区里定位了(见表9)。连接器产生的符号指向每一个执行区的基地址和长度限制,这些符号可以被_user_initial_stackheap调用的重定向代码使用。在代码中使用DCD来给这些值定义更有意义的名字,可以增强代码的可读性(见表10)。

      文件把heap基地址定位在0x15000,堆栈地址定位在0x4000。Heap和堆栈的位置可以通过编辑对应执行区的地址方便地改变。

      分散加载描述文件供ARM-ADS链接器使用,用来决定各个代码段和数据段的存储位置,下面为一个添加注释后的.scf文件例子: