打印
[嵌入式linux]

Home » LPCXpresso Software Knowledgebase

[复制链接]
5780|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 sinanjj 于 2010-8-7 15:16 编辑

C library support
C库
LPCXpresso 有俩C库分类:
  • Newlib - GNU C库
  • Redlib - 我们自己的C库
The Newlib (family of) libraries provide complete C99 and C++ library support at the expense of a larger (in some cases, much larger) code size in your application. If you prefer a smaller application and don't need the additional functionality of the C99 or C++ libraries, you should use Redlib, which can can produce much smaller applications.
标准的GNU库newlib, 往往太大太完善(做了很多错误判断), 所以当你想精简程序的时候, 应先首先用redlib.
Switching between Newlib and Redlib

The two libraries use different header files. Thus when switching between Newlib and Redlib libraries, you must also switch the headers. To do this:
  • Select the project in Project Explorer
  • Right-click and select Properties
  • Expand C/C++ Build and select Settings
  • In the Tools settings tab, select Target under MCU Compiler
  • In Use header for C library, select Newlib or Redlib
Repeat the above sequence for all Build Configurations (typically Debug and Release).
就是这里啦
:


To then change the libraries actually being linked with (assuming you are using Managed linker scripts):
  • Select the project in Project Explorer
  • Right-click and select Properties
  • Expand C/C++ Build and select Settings
  • In the Tools settings tab, select Target under MCU Linker
  • In Use C library, select one of the libraries options from the dropdown list. For an explanation of the various library options, see below.
Again repeat the above sequence for all Build Configurations (typically Debug and Release).
Bottom of the C library (library stubs)The Code Red tools suite is supplied with several 'stubs' that form the very bottom of the C library and include certain low-level functions used by other functions in the library. In many embedded microcontroller applications it is possible to use no stub by careful use of the C library.
C Library stub code
  • None : This is literally no stub and has the smallest memory footprint. It excludes low-level functions for all file-based I/O and some string and memory handling functions.
  • Nohost : This provides the string and memory handling functions and some file-based I/O functions. However, it assumes that you have no debugging host system, thus any file I/O will do nothing. For Redlib, it also provide the errno variable.
  • Semihost : This provides implementation of all functions, including file I/O. The file I/O will be directed through the debugger and will be performed on the host system. For example, printf/scanf will use the debugger console window and fread/fwrite will operate on files on the host system.
Equivalent libraries are supplied for both Newlib and Redlib and are named:
    * Newlib (none)
    * Newlib (nohost)
    * Newlib (semihost)
    * Redlib (none)
    * Redlib (nohost)
    * Redlib (semihost)
Note that using the printf/scanf family of functions can significantly increase the size of your application.
Important noteWhen you have linked with the semihosting library, your application will no longer work standalone - it will only work when connected to the debugger.
C Library DocumentationGeneral information on Standard C library:
http://www.cplusplus.com/reference/clibrary/
http://en.wikipedia.org/wiki/C_library
Information on 'Newlib' C libary:
http://sourceware.org/newlib/libc.html
http://en.wikipedia.org/wiki/Newlib

(简单说一句话: 就是redlib是newlib的精简版, 体积有限制的程序用redlib就是了)

相关帖子

沙发
sinanjj|  楼主 | 2010-8-7 15:17 | 只看该作者
本帖最后由 sinanjj 于 2010-8-7 15:42 编辑

Compiler optimization
编译器优化

Compiling for better performance
编译出更好的性能
The four basic optimization options offered by the GNU compiler are -O0,-O1,-O2 and -O3. These offer an increasing level of optimization such that -O0 carries out no optimization of the compiled code, whereas -O3 carries out the most optimization.

As the level of optimization increases, the compiler will attempt to produce better performing code. This may also have the effect of reducing the code size at levels -O1 and -O2 (compared to -O0).

However at level -O3, a number of additional optimization techniques are enabled which may produce higher performance code - but which are likely to also increase the code size.
gcc优化选项, -O0是不优化. -o3是优化的最厉害. 不过优化的最厉害的时候往往会增加体积. 所以...同志们看着办吧

With Code Red's tools suite, the Debug configuration defaults to building -O0, and the Release configuration defaults to either -O2 or-O3 (depending on which version of the tools suite you are using). You can modify the optimization option used by a particular build configuration as follows:
code red的工具(当然包括LPCXpresso )都是默认的 debug模式不优化 -o0, release模式优化为-O2或者-O3 , 具体看什么软件. 如果要改动这个优化. 按照下列操作.

   1. Open the Project properties. There are a number of ways of doing this. For example, make sure the Project is highlighted in the Project Explorer view then open the menu "Project -> Properties".
   2. In the left-hand list of the Properties window, open "C/C++ Build" and select "Settings" and then the "Tool Settings" tab.
   3. Now choose "MCU C Compiler - Optimization" and select the required optimization level from the drop-down.



Compiling for better code size
优化出更小的代码
As noted earlier, the above options are focussed on improving the performance of your code. This will sometimes, but not always, also reduce code size. If code size is your primary focus, then there is an additional option that may be of use, the -Os. This enables all -O2 optimizations that do not typically increase code size, but also performs further optimizations designed to reduce code size.

You can modify the optimization option used by a particular build configuration to -Os by selecting "MCU C Compiler - Optimization" in Project Properties and entering -Os into the "Other optimization options" field.
减小代码优化选项 -Os, 一般都打开了.
具体情况多试试各个选项的结合.

Actual code size and performance

The code size and performance results you will obtain for your particular source code for a particular optimization level are very much dependent on both the source code and the system that the code is executed it. It is well worth compiling at a number of optimization levels and seeing which provides the result closest to your ideal balance of code size and performance. The optimization level number gives an indication as to what the heuristics within the compiler's optimization engine will try to achieve for an average system. They are not a guarantee of the actual result.


Optimized code fails to execute correctly
优化代码引起的运行失败
Although the reason why code built with optimization fails to run correctly is sometimes a fault with the compiler, quite often it is actually down to the way that your code is written is not "optimization friendly". The two of the most common causes of problems are:
优化代码以解决这一问题, 一下方法优化:
   1. Where variables which map onto memory mapped peripheral devices have not been marked as 'volatile'. With a debug build, such code can often work, as the compiler does not optimize out memory access. But if such variables are not marked as 'volatile', a release build will often optimise them out. For more information, please see:
          * http://en.wikipedia.org/wiki/Volatile_variable
          * http://users.ece.utexas.edu/~val ... /chap4.htm#VOLATILE
一个硬件可以改变的变量没有volatile关键字声明. (这个一般是头文件的事. 非高手就不要乱改头文件了...)

   2. Timing loops. When compiled for release, if you have loops which simply count up to a particular value, for example waiting for a configuration register to change, the count can often no longer be sufficient when the code is compiled for Release due to the additional optimisation. In addition, if the variables used in such loops are not marked as volatile, they may well be just optimized away!

Debugging of optimized code
调试优化过的代码
At -O0, one or more machine instructions can effectively be mapped onto a specific source statement. However as the level of optimization carried out by the compiler increases, the mapping between source code and the generated machine instructions becomes much more complex. For example, this may lead to instructions originally generated from a number of source lines being merged or reordered.

One of the consequences of this is that when debugging optimized code, program behavior can sometimes be different to what might be expected from just looking at the original source code.

For example a breakpoint set on the first source statement of a loop might only get hit once, as the actual breakpoint may have been set on an initialisation instruction that only executes the first time through the loop.

Another example is that sometimes stepping a single source statement may lead to the program stopping at the previous source statement - so that it appears that the program has executed backwards! However what has actually happened is that the next machine instruction is actually mapped to the previous source statement in the debug data (the part of the ELF image created by the compiler/link that is used by the debugger to map between source and executable).

When debugging your application, it can often therefore be sensible to debug using as low a level of optimization as possible (normally -O0) until you are sure that the program is correct algorithmically, and only then start to increase the optimization level.

(就是调试的时候别优化, 老老实实的用-O0 要不可能出奇怪问题)
And finally...

This article is very much an overview and only covers the top-level compiler options. There are a number of other compiler optimization that you might want to consider using in particular circumstances. For more information on these, please see the GCC documentation.

(其他问题参考gcc文档.--------本来就是gcc)

使用特权

评论回复
板凳
sinanjj|  楼主 | 2010-8-7 15:44 | 只看该作者
本帖最后由 sinanjj 于 2010-8-7 16:09 编辑

Generating srec (Motorola S format), binary, ihex (Intel Hex) files
生成bin文件

When building a project, the Code Red tools suite will create an ARM executable format (AXF) file - which is actually ELF/DWARF. This file can be programmed directly down to your target using the Code Red debug functionality. But it may also be converted into a variety of formats suitable for use in other external tools. The objcopy (arm-none-eabi-objcopy) utility is used for this. Objcopy can convert into the following formats:
axf 文件实际上就是elf文件. 用arm-none-eabi-objcopy这个文件来转换成一下格式
    * srec
    * binary
    * ihex
    * tekhex

For example, to convert example.axf into binary format, use the following command:
例如: 转换example.axf成binary格式, 用一下命令:
arm-none-eabi-objcopy -O binary example.axf example.bin

If you Ctrl-click on the projectname on the right hand side of the bottom bar of the IDE, this will launch a command prompt in the project directory with appropriate paths set up. All you need to do before running the objcopy command is change into the directory of the required Build configuration.

You can also select the .axf file in the Project Explorer, right-click and select "Binary Utilities->Create binary". You can change the options used to create a binary file in this way on the "Windows->;Preferences, LPCXpresso/Utilites" preference page.

Objcopy may also be used to automatically convert an axf file during a build. To do this, create an appropriate Post-build step. For more details please see the Knowledgebase entry Post-processing your linked application.

使用特权

评论回复
地板
sinanjj|  楼主 | 2010-8-7 16:16 | 只看该作者
There is no stack checking on the Cortex-M families, so you have to be careful where you place the stack, program data, and the heap (e.g. malloc() space).

If you are using the standard (provided) linker scripts, the stack is placed at the top of RAM, program data is at the bottom on RAM, and the heap immediately after that.

If you are using a lot of stack, it can grow into the heap or even the program data space. If the stack has 'overflowed' into those spaces, when you write to the heap/program data it can overwrite values on the stack and thus corrupt it.

The stack is used for both your application AND any interrupts that may be firing (including nested interrupt), so you need to ensure there is enough space for the worst-case scenario.

Also, check that you are not allocating large amounts of data on the stack (e.g. allocating a local array, as this will be placed on the stack).


stack和heap不检查
(从来没在MCU里用过malloc(), 特别是2kram的MCU)

使用特权

评论回复
5
sinanjj|  楼主 | 2010-8-7 16:27 | 只看该作者
本帖最后由 sinanjj 于 2010-8-7 16:44 编辑

Support for CMSIS

Background on CMSIS

CMSIS, the Cortex Microcontroller Software Interface Standard, defines for a Cortex-M Microcontroller System:
corte-M0 软件标准: (arm公司制定的?)
    * A common way to access peripheral registers and a common way to define exception vectors. (如何访问外设寄存器和如何定义中断向量)
    * The register names of the Core Peripherals and the names of the Core Exception Vectors. (寄存器名字-----就是名字都统一了)
    * An device independent interface for RTOS Kernels including a debug channel.
(和rtos独立的接口????? rtos很多种啊...)

Code Red support for CMSIS

The LPCXpresso IDE project wizard provides built in support for creating projects that make use of CMSIS.After giving your new project a name, where built-in support for CMSIS is available, the next screen will prompt you to select whether the project you a re creating should use the built in CMSIS support, and if so which CMSIS library you wish to use.
主要是头文件和库符合这个标准.

At the time of writing the only selection possible is CMSIS 1.30 for the MCU family you are using. But as new versions of CMSIS of released and encorporated into the Code Red tools, you will be able to select the version you wish to use.
标准还有version---我*

After making your CMSIS choices, the rest of the project wizard then allows you create startup files, select the build configurations to be created, and finally select the actual target MCU.

What does the Project Wizard actually do?

When you choose to create a CMSIS-based project, the wizard will make a number of modifications to (all build configurations of) the project that it creates:

   1. It will define the symbol __USE_CMSIS. This existence of the symbol is checked by Code Red's standard MCU startup code to determine whether to call the CMSIS system initialization function. You can also use it in your own sources to determine whether other CMSIS functionality can be used.

   2. It will create include paths for your project to a CMSIS library project specific for the MCU family you are using.

   3. It will also add the appropriate CMSIS library to the project's link step, allowing appropriate CMSIS library code to be linked in to your application executable.

This CMSIS library project will have a name in the form "CMSIS<version>_<MCUfamily>". For example the CMSIS 1.30 library projects for the NXP LPC17xx and LPC13xx MCU families are "CMSISv1p30_LPC17xx" and "CMSISv1p30_LPC13xx". Each of the libraries contains the CMSIS sources appropriate for that MCU family, plus the CMSIS documentation.

The appropriate CMSIS library project must exist in the workspace your new project is being created in. The CMSIS library project may already exist in the workspace if you have imported appropriate example projects. But if not, you can import the appropriate library project into your workspace using the "Import Example project(s)" entry of the IDE's Quickstart Panel, and selecting the appropriately named CMSIS zip example file.

Note that when you create a new CMSIS using project, if the appropriate CMSIS library does not exist in the workspace, you will get a project dependency warning as the wizard creates your project, informing you that your project will not build. However once you have imported the appropriate CMSIS library project, your own project will then build correctly.

Using CMSIS functionality

One thing that CMSIS provides is a set of headers defining the peripheral set of the MCU family that you are using. For example, the following code taken from an LPC1768 example enables the A/D converter

    #include "LPC17xx.h"

    // PCADC / PCAD
    #define ADC_POWERON (1 << 12)

    #define PCLK_ADC 24
    #define PCLK_ADC_MASK (3 << 24)

    // AD0.0 - P0.23, PINSEL1 [15:14] = 01
    #define SELECT_ADC0 (0x1<<14)
     :
    // Turn on power to ADC block
    LPC_SC->;PCONP |=  ADC_POWERON;

    // Turn on ADC peripheral clock
    LPC_SC->;PCLKSEL0 &= ~(PCLK_ADC_MASK);
    LPC_SC->;PCLKSEL0 |=  (3 << PCLK_ADC);

    // Set P0.23 to AD0.0 in PINSEL1
    LPC_PINCON->;PINSEL1        |= SELECT_ADC0;
      :

It also provides access to functionality contained within the Cortex-M processor core. For example, the below code snippet enables the SysTick timer built into the Cortex-M3 used by the LPC17xx and LPC13xx.

    // Setup SysTick Timer to interrupt at 1 msec intervals
    if (SysTick_Config(SystemCoreClock / 1000)) {
       while (1);  // Capture error
    }

For more information and example code, please see the examples provided with the tools suite, together with the CMSIS documentation contained within the CMSIS library projects.



头文件就是CMSIS标准














Undefined reference to `xxx` when linkingIf you are using functions from the C library and get errors about undefined references when linking, it is possible that you may need to change which variant of the C library you are linking with.
库接口不对. 编程基础知识.

For example if your code calls printf, but you are linking with the Redlib(none) C library variant, you will see a number of errors, including:
undefined reference to `_Csys_tmpnam_'
undefined reference to `_Csyscall1'

嵌入式编程有这个printf么....
In order to successfully link, you will need to change your project to link with the Redlib (semihost) C library variant. For more details please see the Knowledgebase entry  C library support.
这个semihost只能调试不能release, 个人认为嵌入式编程用printf就是典型的脑残行为. 当然用串口打印和这个不同.

The other reason for seeing undefined references of course is that there is a problem with your own code base. For example, you may have mispelt the name of one of the functions that you call, or you may not have linked in a library project.

另外可能的原因就是写错调用的函数名了----恩...这篇**写得真没水平....






Linker scripts and C libraries库文件列表

If you are providing your own linker script, you will need to add one of the following entries before the SECTION line in your linker script:
  • Newlib (None), add
      GROUP(libgcc.a libc.a)
  • Newlib (Nohost), add  GROUP(libgcc.a libc.a libcr_newlib_nohost.a)
  • Newlib (Semihost), add  GROUP(libgcc.a libc.a libcr_newlib_semihost.a)
  • Redlib (None), add  GROUP(libcr_c.a libcr_eabihelpers.a)
  • Redlib (Nohost), add  GROUP(libcr_c.a libcr_nohost.a libcr_eabihelpers.a)
  • Redlib (Semihost), add
      GROUP(libcr_c.a libcr_semihost.a libcr_eabihelpers.a)

使用特权

评论回复
6
sinanjj|  楼主 | 2010-8-7 16:44 | 只看该作者
本帖最后由 sinanjj 于 2010-8-7 17:11 编辑

Post-processing your linked application
link完事以后执行的命令

In this example we are going to carry out three post-link steps:
下边这个例子我们在link完事以后执行3命令
    * displaying the size of the application 显示大小
    * generate an interleaved C / assembler listing 生成内部的C/汇编 列表
    * create a hex version of the application image. 生成hex文件

To do this:
   1. "Project -> Properties".
   2. "C/C++ Build" select "Settings".
   3. Select the "Build steps" tab
   4. In the "Post-build steps - Command" field, enter:

      arm-none-eabi-size ${BuildArtifactFileName};
      arm-none-eabi-objdump -S ${BuildArtifactFileName} >${BuildArtifactFileBaseName}.lss;
      arm-none-eabi-objcopy -O ihex ${BuildArtifactFileName} ${BuildArtifactFileBaseName}.hex;
   5. Click apply
   6. reBuild


注: binary文件的这样一句:

arm-none-eabi-objcopy -O binary ${BuildArtifactFileName} ${BuildArtifactFileBaseName}.bin;

使用特权

评论回复
7
hotpower| | 2010-8-7 18:32 | 只看该作者
本帖最后由 hotpower 于 2010-8-7 18:34 编辑

俺玩过SWT Java串口助手结业作(程序源码)

使用特权

评论回复
8
sinanjj|  楼主 | 2010-8-7 21:37 | 只看该作者
俺玩过SWT Java串口助手结业作(程序源码)

hotpower 发表于 2010-8-7 18:32


中间件是重点. UI可以用web的. (web的UI比这个代码量什么的都少. 而且好维护. 而且能发布..而且好改...)


swt或者这种pc端程序并不是重点. (也并不值钱.......随便找个人就能做.....调试可以)

不要弄错重点.

这种结构的:

浏览器----->串口中间件服务程序----->串口---->板子
这个也不难改.

使用特权

评论回复
9
sinanjj|  楼主 | 2010-8-8 21:18 | 只看该作者
一会弄个IO的例子.


今天就鼓捣明白了CMSIS......

这个lpcxpresso IDE确实不如keil好用.....因为是gcc的, 就用它吧....

使用特权

评论回复
10
sinanjj|  楼主 | 2010-8-9 12:20 | 只看该作者
本帖最后由 sinanjj 于 2010-8-10 22:35 编辑

/* GPIO */
            /* basic */
#include "LPC11xx.h"
int main(void)
{
    SystemInit();
    LPC_IOCON->PIO2_6 = 0xc0;    // Hi-Z
    LPC_GPIO3->DIR = 0x30;    // GPIO3_4, GPIO3_5 output
    LPC_GPIO3->MASKED_ACCESS[((1<<5)|(1<<4))] = 0x00;    // GPIO3_5, GPIO3_4 output 0
    for (;;) {
        if (LPC_GPIO2->MASKED_ACCESS[(1<<6)] == 0x00) LPC_GPIO3->MASKED_ACCESS[(1<<4)] = 0xff;    // GPIO3_4 output 1
        else LPC_GPIO3->MASKED_ACCESS[(1<<4)] = 0x00;    // GPIO3_4 output 0
    }

使用特权

评论回复
11
sinanjj|  楼主 | 2010-8-10 22:37 | 只看该作者
本帖最后由 sinanjj 于 2010-8-11 20:50 编辑

精简后的CMSIS和stargup文件.
lpc11xx.zip (16.74 KB)




简单程序编译出来2khex 比原有的6khex减少3倍

使用特权

评论回复
12
sinanjj|  楼主 | 2010-8-11 20:50 | 只看该作者
状态机思路的uart处理

无等待延时


/* UART */
#include "LPC11xx.h"
#define BAUDRATE 115200
void uart_init (void)
{
        NVIC_DisableIRQ(UART_IRQn);
        LPC_IOCON->;PIO1_6 = 0xc1;        // UART RXD
        LPC_IOCON->;PIO1_7 = 0xc1;        // UART TXD
        LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);        // Enable UART clock
        LPC_SYSCON->UARTCLKDIV = 0x1;                // divided by 1
        LPC_UART->LCR = 0x83;        // 8 bits, no Parity, 1 Stop bit
        uint32_t Fdiv;
        Fdiv = (((SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/LPC_SYSCON->UARTCLKDIV)/16)/BAUDRATE;
        LPC_UART->DLM = Fdiv / 256;
        LPC_UART->DLL = Fdiv % 256;
        LPC_UART->LCR = 0x03;                // DLAB = 0
        LPC_UART->FCR = 0x07;                // Enable and reset TX and RX FIFO.
        Fdiv = LPC_UART->LSR;                // Read to clear the line status.
}

int main(void)
{
        SystemInit();
        uart_init ();
        unsigned char tx_buf[256];
        unsigned char rx_buf[256];
        unsigned char tx_count = 0;
        unsigned char rx_count = 0;
        for (;;) {
                if (LPC_UART->LSR & 0x01) {        // RBR contains valid data
                        if (rx_count == 255) {        // rx_buf full
                                // Overrun Error: The overrun error condition is set as soon as it occurs. A U0LSR read clears U0LSR[1]. U0LSR[1] is set when UART RSR has a new character assembled and the UART RBR FIFO is full. In this case, the UART RBR FIFO will not be overwritten and the character in the UART RSR will be lost.
                        } else {        // receive data to rx_buf
                                rx_buf[rx_count] = LPC_UART->RBR;
                                rx_count++;
                        }
                }
                if (tx_count != 0) {
                        if (LPC_UART->LSR & 0x20) {        // Transmitter Holding Register Empty (THRE)
                                LPC_UART->THR = tx_buf[tx_count];        // UART Transmitter Holding Register
                                tx_count--;
                        }
                }
                if (rx_count != 0) {        // handle rx_buf
                        for (;;) {
                                tx_buf[tx_count] = rx_buf[rx_count];
                                if ((rx_count ==0) || (tx_count == 255)) break;
                                rx_count--; tx_count++;
                        }
                }
        }
}

使用特权

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

本版积分规则

个人签名:In God We Trust 独立的个人,体赖科学技术工具提供针对个人的产品与服务,是通向幸福的唯一道路 工程师,设计师等可以个人创业的群体,将逐步瓦解官僚体制公司,成为中国中产。(重复劳动,工厂等,将逐步机械化) seacer.co

456

主题

6300

帖子

25

粉丝