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 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中。
文章评论(0条评论)
登录后参与讨论