函数指针问题

时间:2014-09-08 12:18:47

标签: c gcc atmel cortex-m

我试图在Atmel数据表中实现一些代码。我已经从下面的数据表中直接复制了它。

 (unsigned int) (*IAP_Function)(unsigned long);
    void main (void)
{
    unsigned long FlashSectorNum = 200; //
    unsigned long flash_cmd = 0;
    unsigned long flash_status = 0;
    unsigned long EFCIndex = 0; // 0:EEFC0, 1: EEFC1

    /* Initialize the function pointer (retrieve function address from NMI vecto*/
    IAP_Function = ((unsigned long) (*)(unsigned long))0x00800008;
    /* Send your data to the sector here */
    /* build the command to send to EEFC */
    flash_cmd = (0x5A << 24) | (FlashSectorNum << 8) | AT91C_MC_FCMD_EWP;
    /* Call the IAP function with appropriate command */
    flash_status = IAP_Function (EFCIndex, flash_cmd);
    }

这使我能够调用ROM中的函数来编程运行微代码中的代码的闪存。

我正在使用ARM Cortex的gcc并在第一行收到错误:

  

预期标识符或'(''无符号'之前的

现在,我只是改为:

unsigned int (*IAP_Function)(unsigned long);

因为它看起来不对(不确定为什么函数的返回值应该在brwackets中)并且该错误消失了。

然而,这一行:

IAP_Function = ((unsigned long) (*)(unsigned long))0x00800008;

引发错误:

  

')'令牌

之前的预期表达式

光标位于*旁边。

不出所料,我也得到了错误:

  

函数'IAP_Function'

的参数太多了

对于这一行:

flash_status = IAP_Function (EFCIndex, flash_cmd);

我怀疑数据表在最后一个错误方面写得不好,实际上是第一个错误。

但是,行:

IAP_Function = ((unsigned long) (*)(unsigned long))0x00800008;

我不明白。我相信,它试图获取0x00800008的内容,并将其用作指向该函数的指针。如果这是正确的,我该怎么写那条线?

另外,对于从函数返回的值,忽略第一行中unsigned int周围的括号,我的其他假设是否正确?另外,我假设我应该改变第一行:

unsigned int (*IAP_Function)(unsigned long, unsigned long);

由于函数调用需要两个值?

非常感谢:)

4 个答案:

答案 0 :(得分:1)

IAP_Function = ((unsigned long) (*)(unsigned long))0x00800008;将整数转换为函数指针地址并将其分配给IAP_Function。需要强制转换,因为如果尝试在没有强制转换的情况下将整数分配给指针,任何自尊的编译器都应该抛出警告。

但正如您所指出的那样,返回类型并不匹配,并且由于某种原因,它周围有括号。所以适当的演员会看起来像:

IAP_Function = (unsigned int (*)(unsigned long))0x00800008;

如果您需要其他参数,请同时添加。数据表代码示例通常都是谎言,因此请仔细阅读手册中有关函数参数的内容。

你应该考虑声明函数指针的typedef来理解这种疯狂:

typedef unsigned (*FuncType)(unsigned long, unsigned long);
FuncType IAP_Function;
...
IAP_Function = (FuncType)0x00800008; // Nice and simple

答案 1 :(得分:0)

实际上,IAP_Function = ((unsigned long) (*)(unsigned long))0x00800008;不使用0x00800008的内容作为指向函数的指针。它使用0x00800008作为地址本身。

在你的定义中,你将IAP_Function声明为一个返回unsigned int的函数,但是,当你将你强制转换为返回unsigned long的函数时。

此外,函数只需要一个参数,而你传递的是两个。你应该改变你的演员和函数声明,或者只传递一个参数。

答案 2 :(得分:0)

要匹配底部的调用,顶部的函数指针声明应为

unsigned long (*IAP_Function)(unsigned long, unsigned long);

但是,正确的做法取决于分配给指针的功能,你没有描述过。

答案 3 :(得分:-1)

这不是主要的主题,但是我报告了我的结果,因为我首先在这个页面中找到了IAP_Function()的原始问题。 经过一些尝试后,我成功地使用了SAM3A8C的IAP_Function()(一个明确的GPNVM位操作),方法如下。地址不是0x00800008,而是0x00100008(我在其他地方找到了这个提示),而IAP_Function()只需要一个长参数,如Atmel手册第20.5.2节所述。我不知道0x00800008地址是否类似,但有两个参数(使用EFCIndex),或者这些是手册中的错误输入。