Flash基础入门之Snow TI DSP --- Running an Application from Internal Flash Memory
小标 2019-03-12 来源 : 阅读 1053 评论 0

摘要:本文主要向大家介绍了Flash基础入门之Snow TI DSP --- Running an Application from Internal Flash Memory,通过具体的内容向大家展现,希望对大家学习Flash基础入门有所帮助。

本文主要向大家介绍了Flash基础入门之Snow TI DSP --- Running an Application from Internal Flash Memory,通过具体的内容向大家展现,希望对大家学习Flash基础入门有所帮助。

Flash基础入门之Snow TI DSP --- Running an Application from Internal Flash Memory

Several special requirements exist for running an application from on-chip flash memory on the TMS320F28xxx. These requirements generally do not manifest themselves during code development in RAM since the Code Composer Studio (CCS) debugger can mask problems associated with initialized sections and their linkage in memory. 

This application report covers the application software modifications needed for execution from on-chip flash memory. Requirements for both DSP/BIOS and non-DSP/BIOS projects are presented.  Some performance considerations and techniques are also discussed.

1. Introduction

The TMS320F28xxx DSP family has been designed for standalone operation in embedded controller applications. The on-chip flash usually eliminates the need for external non-volatile memory and a host processor from which to bootload.

Configuring an application to run from flash memory is a relatively easy matter provided that one follows a few simple steps. This report covers the major concerns and steps needed to properly configure application software for execution from internal flash memory.

2. Creating a User Linker Command File

2.1 Non-DSP/BIOS Projects

In non-DSP/BIOS applications, the user linker command file will be where most memory is defined, and where the linking of most sections is specified. 

These non-BIOS files contain linker MEMORY and SECTIONS declarations for linking the peripheral register structures. Since CCS supports having more than one linker command file in a project, all one needs to do is add the appropriate one of these linker command files to your code project in addition to your user linker command file.

In general, the order of the linker command files is unimportant since during a project build, CCS evaluates the MEMORY section of every linker command file before evaluating the SECTIONS section of any linker command file. This ensures that all memories are defined before linking any sections to those memories. However, advanced users may need manual control over the order of linker command file evaluation in some rare situations.

2.2 DSP/BIOS Projects

The DSP/BIOS configuration tool generates a linker command file that specifies how to link all DSP/BIOS generated sections, and by default all C-compiler generated sections. When running your application from RAM, this linker command file may be the only one in use.

However, when executing from flash memory, there will likely be a need to generate and link one or more user defined sections. In particular, any code that configures the on-chip flash control registers (e.g. flash wait-states) cannot execute from flash. In addition, one may want to run certain time critical functions from RAM (instead of flash) to maximize performance. A user linker command file must be created to handle these user defined sections.

3. Where to Link the Sections

Two basic section types exist: initialized, and uninitialized. Initialized sections must contain valid values at device power-up. For example, code and constants are found in initialized sections. 

When designing a stand-alone embedded system with the F28xxx DSP (e.g., no emulator or debugger in use, no host processor present to perform bootloading), all initialized sections must be linked to non-volatile memory (e.g., on-chip flash). 

An uninitialized section does not contain valid values at device power-up. For example, variables are found in uninitialized sections. Code will write values to the variable locations during code execution. Therefore, uninitialized sections must be linked to volatile memory (e.g. RAM).

It is suggested that the -w linker option be invoked (it is selected by default for all newly created CCS projects). The -w option will produce a warning if the linker encounters any sections in your project that have not been explicitly specified for linking in a linker command file. 

When the linker encounters an unspecified section, it uses a default allocation algorithm to link the section into memory (it will link the section to the first defined memory with enough available free space). This is almost always risky, and can lead to unreliable and unpredictable code behavior. The -w option will identify any unspecified sectors (e.g., those accidentally forgotten by the user) so that the user can make the necessary addition to the appropriate linker command file.

3.1 Caution

It is important that the large memory model be used with the C-compiler (as opposed to the small memory model). Small memory model requires certain initialized sections to be linked to non-volatile memory in the lower 64Kw of addressable space. However, no flash memory is present in this region on any F28xxx devices, and this will likely be true for future F28xxx devices as well. Therefore, large memory model should be used. 

For non-DSP/BIOS projects, one should include the large memory model C-compiler runtime support library into their code project. For the fixed-point devices, this is library rts2800_ml.lib (as opposed to rts2800.lib, which is for the small memory model). For the floating-point devices, this is file rts2800_fpu32.lib for plain C code, or rts2800_fpu32_eh.lib for C++ code (there are no small memory model libraries for the floating-point devices).

For DSP/BIOS projects, DSP/BIOS will take care of including the required library. The user should not include any runtime support library in a DSP/BIOS project.

3.1 Non-DSP/BIOS Projects

The compiler uses a number of specific sections. These sections are the same whether you are running from RAM or flash. However, when running a program from flash, all initialized sections must be linked to non-volatile memory, whereas all uninitialized sections must be linked to volatile memory. Table 1 shows where to link each compiler generated section on the F28xxx DSP.

(SN.) Section Name          Where to Link 

(1) .cinit              Flash

(2) .cio                RAM

(3) .const            Flash

(4) .econst           Flash

(5) .pinit               Flash

(6) .switch            Flash

(7) .text                 Flash

(8) .bss                 RAM

(9).ebss                RAM

(10)  .stack            Lower 64Kw RAM

(11) .sysmem         RAM

(12) .esysmem       RAM

(13) .reset               RAM

Table 1 Notes:

The .reset section contains nothing more than a 32-bit interrupt vector that points to the C-compiler boot function in the runtime support library (the _c_int00 routine). It is almost never used. Instead, the user typically creates their own branch instruction to point to the starting point of the code. When not in use, the .reset section should be omitted from the code build by using a DSECT modifier in the linker command file. For example:

SECTIONS  { .reset    :> FLASH,    PAGE =  0,  TYPE = DSECT  }

Any user created initialized section should be linked to flash (e.g., those sections created using the CODE_SECTION compiler pragma), whereas any user created uninitialized sections should be linked to RAM (e.g., those sections created using the DATA_SECTION compiler pragma).

4. Copying Sections from Flash to RAM

4.1 Copying the Interrupt Vectors (non-DSP/BIOS projects only)

The Peripheral Interrupt Expansion (PIE) module manages interrupt requests on F28xxx devices. At power-up, all interrupt vectors must be located in non-volatile memory (i.e., flash), but copied to the PIEVECT RAM as part of the device initialization procedure in your code. The PIEVECT RAM is a specific block of RAM, which on F28xxx devices covered in this report is a 256x16 block starting at address 0x000D00 in data space.

Several approaches exist for linking the interrupt vectors to flash and then copying them to the PIEVECT RAM at runtime. One approach is to create a constant C-structure of function pointers that contains all 128 32-bit vectors. If using the peripheral header file structures, such a structure, called PieVectTableInit, has already been created in the corresponding file DSP28xxx_PieVect.c. Since this structure is declared using the const type qualifier, it will be placed in the .econst section by the compiler. One simply needs to copy this structure to the PIEVECT RAM at runtime. The C-compiler runtime support library contains a memory copy function called memcpy() that can be used to perform the copy task.

memcpy ((void *) 0x000D00, &PieVectTableInit, 256);

Note that the copy length is 256 because memcpy() copies 16-bit words.

The above example uses a hard coded address for the start of the PIE RAM, specifically 0x000D00. If this is objectionable (as hard coded addresses are not good programming practice), one can use a DATA_SECTION pragma to create an uninitialized dummy variable, and link this variable to the PIE RAM. The name of the dummy variable can then be used in place of the hard coded address. 

For example, when using any of the 28xxx device peripheral structures, an uninitialized structure called PieVectTable is created and linked over the PIEVECT RAM. The memcpy() instruction in the previous example can be replaced by:

memcpy(&PieVectTable, &PieVectTableInit, 256);

Lastly, on some devices, specifically the "Piccolo" devices, the first three 32-bit PIE vector locations are used for bootmode selection when the debugger is in use. Therefore, the code should be modified to avoid overwriting these locations as follows:

memcpy((void *) PieVectTable+6, (Unit16 *) &PieVectTableInit+6, 256-6);

4.2 Initializing the Flash Control Registers (DSP/BIOS and non-DSP/BIOS projects)

The initialization code for the  flash control registers cannot be executed from the flash memory or unpredictable results may occur. Therefore, the initialization function for the flash control registers must be copied from flash (its load address) to RAM (its run address) at runtime.

Caution:(Start)

The flash control registers are protected by either the Code Security Module (CSM) or the Dual Code Security Module (DSCM), depending on the device.

On devices with the CSM, if the CSM is secured you must run the flash register initialization code from CSM secure RAM or the initialization code will be unable to access the flash registers (see the memory map section of the device data sheet to identify the secure memories). Note that the CSM is always locked at device reset, although the ROM bootloader will unlock it if you are using dummy passwords of 0xFFFF.

On devices with the DCSM, the protection of the flash control registers is controlled by the SEM field of the FLSEM register. At reset, the SEM default is such that the flash control registers can be written to by code running from any memory. Normally, software will configure the flash registers prior to changing the SEM field, and therefore the user need only copy the configuration code to any RAM and execute it from there. However, if software first changes the SEM field, the flash configuration code will need to be executed from a RAM block that has security access to the flash configuration registers. This access is determined by the SEM field value.

Caution:(End)

The CODE_SECTION pragma of the C compiler can be used to create a separately linkage section for the flash initialization function. For example, suppose the flash register configuration is to be performed in the C function InitFlash(), and it is desired to place this function into a linkage section called secureRamFuncs.

#pragma CODE_SECTION(InitFlash, "secureRamFuncs")

The section secureRamFuncs can then be linked using the user linker command file. This section will require separate load and run address. Further, it is desired to have the linker generate some global symbols that can be used to determine the load address, run address, and length of the section. This information is needed to perform the copy from the sections load address to its run address.

The memories FlASH and SECURE_RAM are assumed to have been defined either in the MEMORY section of the user linker command file (for non-DSP/BIOS projects) or in the memory section manager of the DSP/BIOS configuration tool (for DSP/BIOS projects). The PAGE designation for these memories should match that of the memory definition. 

Finally, the section must be copied from flash to RAM at runtime.

4.3 Maximizing Performance by Executing Time-critical Functions from RAM (DSP/BIOS and non-DSP/BIOS projects)

The on-chip RAM memory of the F28xxx devices covered in this report provides code execution in MIPS (millions of instructions per second) that is equal to the operating clock frequency of the device in MHz (e.g., 150 MIPS at 150 MHz, 100 MIPS at 100 MHz, etc.). However, the on-chip flash memory gives effective code execution performance that is somewhat less, depending on the device frequency and the application. Rough flash execution performance estimates for the devices covered in this report are:

(1) 90 - 95 MIPS at 150 MHz;

(2) 80 - 85 MIPS at 100 MHz;

(3) 65 - 70 MIPS at 80 MHz;

(4) 50 - 55 MIPS at 60 MHz;

(5) 37 - 39 MIPS at 40 MHz.

It may therefore be desirable to run certain time-critical or computationally demanding routines from on-chip RAM, especially for devices running at 150 MHz. In a standalone embedded system however, all code must initially reside in non-volatile memory. Separate load and run addresses must be setup for those functions running from RAM, and a copy must be performed to move them from on-chip flash to the RAM at runtime. 

Using the CODE_SECTION pragma, one can add multiple functions to the same linkage section. The entire section can then be assigned to run from a particular RAM block, and the user can copy the entire section to RAM all at once. If finer linking granularity is required, separate section names can be created for each function.

4.4 Maximizing Performance by Linking Critical Global Constants to RAM (DSP/BIOS and non-DSP/BIOS projects)

Constants are those data structures declared using the C language const type modifier. The compiler places all constants in the .econst section (large memory model assumed). While special pipeline on the F28xxx devices covered by this report accelerates effective flash performance for code execution, no such pipelining exists for accessing data constants located in the on-chip FLASH. Each flash data access can take multiple cycles. Typical flash wait-states will be 5 cycles at 150 MHz, 3 cycles at 100 or 90 MHz, 2 cycles at 80 or 60 MHz, and 1 cycles at or below 50 MHz device.

It may therefore be desirable to keep heavily accessed constants and constant tables in on-chip RAM. However, a standalone embedded system requires that all initialized data (e.g., constants) initially reside in non-volatile memory. Therefore, separate load and run addresses must be setup for those constants you wish to access in RAM, and a copy must be performed to move them from the on-chip flash to the RAM at runtime. 

5. Programming the Code Security Module Passwords

The code-security module on F28xxx devices provides protection against unwanted copying of and tampering with your software. Devices covered by this report have either a single-zone code security module (CSM), or a dual-zone code security module (DCSM). The CSM uses a single 128-bit password that restricts access to all secure memories. The DCSM provides for two 128-bit passwords, each restricting access to one of the two security zones. Some secure memory resources are fixed in their assignment to one of the two zones, while others can be assigned by software to either zone.

6. Executing Your Code from Flash after a DSP Reset (DSP/BIOS and non-DSP/BIOS projects)

F28xxx devices contain a ROM bootloader that can transfer code execution to the flash after a device reset. When the boot mode selection pins are configured for "Jump-to-Flash" mode, the ROM bootloader will branch to the instruction located at the jump-to-Flash target address in the flash. This address is:

(1) 0x3F7FF6 for F281x, F280x, F2801x, F28044, F2802x, F2803x, and F2806x devices;

(2) 0x3F7FFE for F280x5 devices;

(3) 0x33FFF6 for F2833x and F2823x devices. 

Always confirm the address for your specific device in either the device datasheet, or in the ROM bootloader documentation. The user should place an instruction that branches to the beginning of their code at this address. A long branch (LB in assembly code) occupies two 16-bit words, and the device memory map is designed to accommodate this.

In general, the branch instruction will branch to the start of the C-environment initialization routine located in the C-compiler runtime support library. The entry symbol for this routine is _c_int00. No C code can be executed until this setup routine is run. Alternately, there is sometimes a need to execute a small amount of assembly code prior to starting your C application (for example, to disable the watchdog timer peripheral). In this case, the branch instruction should branch to the start of your assembly code. Regardless, there is a need to properly locate this branch instruction in the flash. The easiest way to do this is with assembly code. The following example creates a named initialized section called codestart that contains a long branch to the C-environment setup routine. The codestart section should be placed in memory with the user linker command file.

For non-DSP/BIOS projects, the user should define a memory named (for example) BEGIN_FLASH on PAGE 0 in the MEMORY portion of the user linker command file.The section codestart can then be linked to this memory.

7. Disabling the Watchdog Timer During C-Environment Boot (DSP/BIOS and non-DSP/BIOS projects)

The C-environment initialization function in the C compiler runtime support library, _c_int00, performs the initialization of global and static variables. This involves a data copy from the .cinit section (located in on-chip flash memory) to the .ebss section (located in RAM) for each initialized global variable. For example, when a global variable is declared in source code as:

int x = 5;

the "5" is placed into the initialized section .cinit, whereas space is reserved in the .ebss section for the symbol "x". The _c_int00 routine then copies the "5" to location "x" at runtime. When a large number of initialized global and static variables are present in the software, the watchdog timer can timeout before the C-environment boot routine can finish and call main() (where the watchdog can be either configured and serviced, or disabled).

This problem may not manifest itself during code development in RAM since the data copy from a .cinit section linked to RAM will occur at a fast pace. However, when the .cinit section is linked to internal flash, copying each data word will take multiple cycles since the internal flash memory defaults to the maximum number of wait-states (wait-states are not configured until the user code reaches main()). In addition, the code performing the data copying is executing from flash, which further increases the time needed to complete the data copy (the code fetches and data reads must share access to the flash). Combined with the fact that the watchdog timeout period defaults to its minimum possible value, a watchdog timeout becomes a real possibility.

You can detect the presence of this problem in your system by using the CCS debugger. Set a breakpoint at the start of main(), and also set a breakpoint at the start of _c_int00. Reset the processor, and then run. You should hit the breakpoint at _c_int00. If you do not, you have a bootmode configuration problem. If you get to _c_int00, run again. This time you should get to the breakpoint in main(). If you do not, the watchdog is timing out before you get there.

The easiest method for correcting the watchdog timeout problem is to disable the watchdog before starting the C-environment boot routine. The watchdog can later be re-enabled after reaching main() and starting your normal code execution flow. 

The watchdog is disabled by setting the WDDIS bit to a 1 in the WDCR register. To disable the watchdog before the boot routine, assembly code must be used (since the C environment is not yet setup). the codestart assembly code section implemented a branch instruction that jumped to the C-environment initialization routine, _c_int00. To disable the watchdog, this branch should instead jump to watchdog disabling code, which can then branch to the _c_int00 routine.


以上就介绍了Flash的相关知识,希望对Flash有兴趣的朋友有所帮助。了解更多内容,请关注职坐标常用软件Flash频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程