首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将N个参数字节传递给指针调用的函数

如何将N个参数字节传递给指针调用的函数
EN

Stack Overflow用户
提问于 2015-04-01 16:09:27
回答 3查看 425关注 0票数 2

我的软件驱动一个在TI DSP TMS320f2812上运行C代码的嵌入式设备。

通信是通过USB串口仿真完成的。

在某个时候,设备端,我需要解析一条消息,意思是“用给定的参数调用给定地址的函数”。该信息包括:

  • 函数地址的4个字节。
  • 参数大小为1字节(以字节为单位)。
  • 参数数据的n个字节。

在这里,我目前使用的代码:

代码语言:javascript
复制
typedef void    (*void_fct_void)    (void);
typedef void    (*void_fct_int16)   (int16);
typedef void    (*void_fct_int32)   (int32);
typedef void    (*void_fct_2int32)  (int32, int32);

...

Uint32 address;
Uint16 sizeIn;

address = HW_Usb_Read_4Bytes();
sizeIn = HW_Usb_Read_1Byte();

switch(sizeIn) {
    case 0:
        ((void_fct_void) address)();
        break;              
    case 2:
        ((void_fct_int16) address)(HW_Usb_Read_2Bytes());
        break;
    case 4:
        ((void_fct_int32) address)(HW_Usb_Read_4Bytes());
        break;
    case 8:
        ((void_fct_2int32) address)(HW_Usb_Read_4Bytes(), HW_Usb_Read_4Bytes());
        break;
}

我想知道是否没有办法使其更加通用,并避免切换,例如:

代码语言:javascript
复制
Uint32 address;
Uint16 sizeIn;

address = HW_Usb_Read_4Bytes();
sizeIn = HW_Usb_Read_1Byte();

putNbytesOnParamsStack(sizeIn); // magic function, will call HW_Usb_Read_1Byte 'sizeIn' times.
((void_fct_void) address)();

的目标函数也很多,并且被嵌入式代码使用,我不能更改它们的签名.

EN

回答 3

Stack Overflow用户

发布于 2015-04-01 17:33:58

您可以使用利布菲 (如果它支持您的目标处理器体系结构、调用约定和ABI),它使您能够“模拟”一个arbirary调用。

但是,您应该传递一个指向数据的指针,而不是数据本身。

票数 1
EN

Stack Overflow用户

发布于 2015-04-01 16:37:26

可以使用内联程序集在堆栈上推送var:

代码语言:javascript
复制
__asm {
    push sizeIn
    ; You can also call your fp using asm:
    call address
    ; But it's not very safe because your compiler may not 
    ; have saved its registries before the call
}

然而,我想知道推动sizeIn如何能帮助您,难道您不需要推动HW_Usb_Read_NBytes()的结果吗?

编辑:

通过多次调用HW_Usb_Read_1Byte()并使用按位操作,您可以删除开关大小写。

代码语言:javascript
复制
int32 param = 0;
for (int i = 0; i < sizeIn; i++)
   param |= (HW_Usb_Read_1Byte() << (i * 8));

每次迭代得到的字节都会被我们读取到的位数移到左边,并附加到整数中。

但是,只有当读取的数据来自一个小的endian系统时,这才能起作用。如果您的API为每个数据大小提供了一个方法,则可能不是这样。

票数 0
EN

Stack Overflow用户

发布于 2015-04-02 10:11:16

正如莱利·阿夫隆所说,使用一些汇编代码是一种解决方案。

为此,我需要知道如何与我使用的DSP接口C和汇编语言。

这被称为呼叫约定。我发现关于它的文档很少,这一个是关于TMS320家族的,但是关于FPU的,TMS320f2812不是这样的。

我记得在连接JTAG时,我使用的版本可以混合源代码和ASM代码。

在这里,我可以从我当前的代码中看到:

代码语言:javascript
复制
// Case 0:
MOVL    XAR7,@XAR2          ; put address in XAR7
LCR     *XAR7               ; call the function
...

// Case 1:
LCR     HW_Usb_Read_2Bytes  ; get the data
MOVL    XAR7,@XAR2          ; put address in XAR7
LCR     *XAR7               ; call the function
...

// Case 2:
LCR     HW_Usb_Read_4Bytes  ; get the data
MOVL    XAR7,@XAR2          ; put address in XAR7
LCR     *XAR7               ; call the function
...

我们可以看到,对HW_Usb_Read_{2|4}Bytes的调用所收回的数据没有得到处理。我认为被调用的函数将把它放在放置它们的堆栈上。

正如我所说的,HW_Usb_Read_4Bytes只调用HW_Usb_Read_2Bytes两次,并从两个UInt16组成一个UInt32

TMS320C28x有一个RPT (第2.5.3节)操作,它允许执行单个指令多次。

我们可以想象出这样的解决方案:

代码语言:javascript
复制
RPT #N−1                        ; Where #N is sizeIn/2
||LCR     HW_Usb_Read_2Bytes    ; get the data
MOVL    XAR7,@XAR2              ; put address in XAR7
LCR     *XAR7                   ; call the function

实际上,要做到这一点有一些制约因素:

  • 我不知道如何确定addressXAR2中。
  • 数据端点是否适合多参数情况?
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29395665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档