我的软件驱动一个在TI DSP TMS320f2812上运行C代码的嵌入式设备。
通过USB串口仿真完成通信。
在某些时候,在设备方面,我需要解析一条消息,这意味着"用给定的参数调用给定地址的函数"。 该消息包含:
这里是我目前使用的代码:
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;
}
我想知道是否有办法让它更通用并避免切换,例如:
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)();
目标函数也很多并且嵌入代码使用,我无法更改其签名。
答案 0 :(得分:1)
您可以使用libffi(如果它支持您的目标处理器体系结构,调用约定和ABI),这使您能够模拟"一个arbirary电话。
但是,您应该传递指向数据的指针,而不是数据本身。
答案 1 :(得分:0)
可以使用内联汇编在堆栈上推送var:
__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()
并按位操作,您可以删除开关案例。
int32 param = 0;
for (int i = 0; i < sizeIn; i++)
param |= (HW_Usb_Read_1Byte() << (i * 8));
每次迭代得到的字节向左移动了我们到目前为止读取的位数,并附加到整数。
然而,这仅在读取的数据来自小端系统时才有效。如果您的API为每种数据大小提供方法,则情况可能并非如此。
答案 2 :(得分:0)
正如Riley Avron所说,使用一些汇编代码是一种解决方案。
为此我需要知道如何接口C和汇编语言 用我使用的DSP。
这称为Calling convention。我找不到关于它的文档,this one与TMS320系列有关,但与FPU有关,而TMS320f2812并非如此。
我记得我使用的代码编辑工作室版本允许在连接JTAG时混合源代码和ASM代码。
这是我在当前代码中看到的内容:
// 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
两次,并从两个UInt32
撰写UInt16
。
TMS320C28x具有RPT (§2.5.3)操作,允许执行单个指令倍数。
我们可以想象这样的解决方案:
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
实际上有一些限制要做到这一点:
address
位于XAR2
。