原创 对Luminary提供的interrupt.c中(void (*) (void))的理解

2009-3-28 22:08 3573 6 6 分类: MCU/ 嵌入式

interrupt.c中有这样一行代码:g_pfnRAMVectors[ulIdx] = (void (*)(void))HWREG(ulIdx * 4);

为简单,分析下面的代码

void func(void) {} //假设该函数位于内存地址0x1000

void main(void)

{

    /*语句1*/ void (*p)(void); //定义指向函数的指针p,其指向的函数是无参数且无返回的。

    /*语句2*/ p = func; //正确

    /*语句3*/ printf("p = %x",p); //错误

   /*语句4*/ printf("p = %x",(long)p); //正确,结果p = 0x1000

    /*语句5*/ p = 0x1000; //错误

    /*语句6*/ p = (void (*) (void)) 0x1000; //正确

}

    语句3在编译的时候出错,提示p的类型与printf()要求的类型不兼容。因为此时p为指针类型,强制转换为long即可,如语句4。

    语句5在编译的时候出错,提示不能用整型数据作为(void (*) (void))类型的入口地址。因为此时p为指针类型,需要将常数转换强制转换为指针(地址)类型,如语句6。

    从语句3可以看到,虽然指针类型代表的是一个地址值,但是我们不可以直接将他作为数值处理。此时一定要将指针类型强制转换为数值才能作为数值使用。

    从语句5可以看到,虽然指针类型代表的是一个地址值,但是我们不可以直接将数值直接传递给他(即使这个数值就是指针要指向的准确地址)。此时一定要将数值强制转换为指针类型才能进行传递。这个规则不但适合函数指针,其他指针类型也适合。例如,int *p; p = 10 /* 编译报错 */ ; p = (int *)10 /* 成功 */;。





IAR Embeded Workbench的C变量段分配 -- Cortex-M3(LM3S618)



开发环境为IAR Embeded Workbench IDE

启动代码startup.c如下:

//*****************************************************************************
//
// startup.c - Boot code for Stellaris.
//
// Copyright (c) 2005-2008 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2752 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************

//*****************************************************************************
//
// Enable the IAR extensions for this source file.
//
//*****************************************************************************
#pragma language="extended"

//*****************************************************************************
//
// Forward declaration of the default fault handlers.
//
//*****************************************************************************
void ResetISR(void);
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);

//*****************************************************************************
//
// The entry point for the application.
//
//*****************************************************************************
extern int main(void);

//*****************************************************************************
//
// Reserve space for the system stack.
//
//*****************************************************************************
#ifndef STACK_SIZE
#define STACK_SIZE                              256
#endif
static unsigned long pulStack[STACK_SIZE];

//*****************************************************************************
//
// A union that describes the entries of the vector table. The union is needed
// since the first entry is the stack pointer and the remainder are function
// pointers.
//
//*****************************************************************************
typedef union
{
    void (*pfnHandler)(void);
    unsigned long ulPtr;
}
uVectorEntry;

//*****************************************************************************
//
// The minimal vector table for a Cortex M3. Note that the proper constructs
// must be placed on this to ensure that it ends up at physical address
// 0x0000.0000.
//
//*****************************************************************************
__root const uVectorEntry g_pfnVectors[] @ "INTVEC" =
{
    { .ulPtr = (unsigned long)pulStack + sizeof(pulStack) },
                                            // The initial stack pointer
    ResetISR,                               // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    IntDefaultHandler,                      // The MPU fault handler
    IntDefaultHandler,                      // The bus fault handler
    IntDefaultHandler,                      // The usage fault handler
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // SVCall handler
    IntDefaultHandler,                      // Debug monitor handler
    0,                                      // Reserved
    IntDefaultHandler,                      // The PendSV handler
    IntDefaultHandler,                      // The SysTick handler
    IntDefaultHandler,                      // GPIO Port A
    IntDefaultHandler,                      // GPIO Port B
    IntDefaultHandler,                      // GPIO Port C
    IntDefaultHandler,                      // GPIO Port D
    IntDefaultHandler,                      // GPIO Port E
    IntDefaultHandler,                      // UART0 Rx and Tx
    IntDefaultHandler,                      // UART1 Rx and Tx
    IntDefaultHandler,                      // SSI Rx and Tx
    IntDefaultHandler,                      // I2C Master and Slave
    IntDefaultHandler,                      // PWM Fault
    IntDefaultHandler,                      // PWM Generator 0
    IntDefaultHandler,                      // PWM Generator 1
    IntDefaultHandler,                      // PWM Generator 2
    IntDefaultHandler,                      // Quadrature Encoder
    IntDefaultHandler,                      // ADC Sequence 0
    IntDefaultHandler,                      // ADC Sequence 1
    IntDefaultHandler,                      // ADC Sequence 2
    IntDefaultHandler,                      // ADC Sequence 3
    IntDefaultHandler,                      // Watchdog timer
    IntDefaultHandler,                      // Timer 0 subtimer A
    IntDefaultHandler,                      // Timer 0 subtimer B
    IntDefaultHandler,                      // Timer 1 subtimer A
    IntDefaultHandler,                      // Timer 1 subtimer B
    IntDefaultHandler,                      // Timer 2 subtimer A
    IntDefaultHandler,                      // Timer 2 subtimer B
    IntDefaultHandler,                      // Analog Comparator 0
    IntDefaultHandler,                      // Analog Comparator 1
    IntDefaultHandler,                      // Analog Comparator 2
    IntDefaultHandler,                      // System Control (PLL, OSC, BO)
    IntDefaultHandler,                      // FLASH Control
    IntDefaultHandler,                      // GPIO Port F
    IntDefaultHandler,                      // GPIO Port G
    IntDefaultHandler,                      // GPIO Port H
    IntDefaultHandler,                      // UART2 Rx and Tx
    IntDefaultHandler,                      // SSI1 Rx and Tx
    IntDefaultHandler,                      // Timer 3 subtimer A
    IntDefaultHandler,                      // Timer 3 subtimer B
    IntDefaultHandler,                      // I2C1 Master and Slave
    IntDefaultHandler,                      // Quadrature Encoder 1
    IntDefaultHandler,                      // CAN0
    IntDefaultHandler,                      // CAN1
    IntDefaultHandler,                      // CAN2
    IntDefaultHandler,                      // Ethernet
    IntDefaultHandler,                      // Hibernate
    IntDefaultHandler,                      // USB0
    IntDefaultHandler,                      // PWM Generator 3
    IntDefaultHandler,                      // uDMA Software Transfer
    IntDefaultHandler                       // uDMA Error
};

//*****************************************************************************
//
// The following are constructs created by the linker, indicating where the
// the "data" and "bss" segments reside in memory. The initializers for the
// for the "data" segment resides immediately following the "text" segment.
//
//*****************************************************************************
#pragma segment="DATA_ID"
#pragma segment="DATA_I"
#pragma segment="DATA_Z"

//*****************************************************************************
//
// This is the code that gets called when the processor first starts execution
// following a reset event. Only the absolutely necessary set is performed,
// after which the application supplied main() routine is called. Any fancy
// actions (such as making decisions based on the reset cause register, and
// resetting the bits in that register) are left solely in the hands of the
// application.
//
//*****************************************************************************
void
ResetISR(void)
{
    unsigned long *pulSrc, *pulDest, *pulEnd;

    //
    // Copy the data segment initializers from flash to SRAM.
    //
    pulSrc = __segment_begin("DATA_ID");
    pulDest = __segment_begin("DATA_I");
    pulEnd = __segment_end("DATA_I");
    while(pulDest < pulEnd)
    {
        *pulDest++ = *pulSrc++;
    }

    //
    // Zero fill the bss segment.
    //
    pulDest = __segment_begin("DATA_Z");
    pulEnd = __segment_end("DATA_Z");
    while(pulDest < pulEnd)
    {
        *pulDest++ = 0;
    }

    //
    // Call the application's entry point.
    //
    main();
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives a NMI. This
// simply enters an infinite loop, preserving the system state for examination
// by a debugger.
//
//*****************************************************************************
static void
NmiSR(void)
{
    //
    // Enter an infinite loop.
    //
    while(1)
    {
    }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives a fault
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
FaultISR(void)
{
    //
    // Enter an infinite loop.
    //
    while(1)
    {
    }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives an unexpected
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
IntDefaultHandler(void)
{
    //
    // Go into an infinite loop.
    //
    while(1)
    {
    }
}

main.c源代码如下:

#define MY_IAR_ICC //使用ICCARM编译器

// 包含必要的头文件
#include "my_lm3s618.h" //根据IAR提供的头文件iolm3s618.h和io_macros.h修改得到

// 主函数(程序入口)
int a[2];
int b[2] = {10};
__no_init int c;
int d = 10;
int main(void)
{
    int e[50] = {10};
    int f[100];
}

make后这些变量的段分配如下:

变量    所在段

a[2]     DATA_Z

b[2]    DATA_I

c        DATA_N

d        DATA_I

e[50] DATA_Z

f[100] DATA_Z

说明:

1)DATA_Z 存储零初始化的静态和全局变量

    DATA_I 存储初始化的静态和全局变量

    DATA_N 存储由__no_init修饰的的静态和全局变量

    (关于各种类型段定义参考《ARM IAR C/C++ Compiler Reference Guide》P217)

2)为什么e[50]和f[100]存储在DATA_Z中?

    e[50]和f[100]是在main.c中定义的局部变量,C编译器规定了局部变量从栈中分配空间。

    从启动代码中下面语句

    __root const uVectorEntry g_pfnVectors[] @ "INTVEC" =
    {
       { .ulPtr = (unsigned long)pulStack + sizeof(pulStack) },

        ……

    可知芯片的栈顶被设置在地址(unsigned long)pulStack + sizeof(pulStack)处。

    又从启动代码中下面语句

    static unsigned long pulStack[STACK_SIZE];

    可知栈空间的开辟是通过定义静态数组pulStack[STACK_SIZE]实现的,而这个数组被分配在DATA_Z段中(没有显式初始化的静态变量默认用0初始化)。既然C编译器规定了e[50]和f[100]必须从栈取得空间(即从pulStack[STACK_SIZE]中取得空间),那么自然e[50]和f[100]存储在DATA_Z中。 如果我们改写栈定义语句static unsigned long pulStack[STACK_SIZE] 为 __no_init static unsigned long pulStack[STACK_SIZE]重新MAKE后可以看到e[50]和f[100]存储在DATA_N中。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条