刚刚把zynq的CAN调成功。那么现在就要把程序移植到fmql了。
老规矩,Procise导入vivado的.bd和.xci文件。
Procise下create block也可以,但是不能自动约束引脚,只能手动写代码。
PeripheralTest
CanExample中用到了CAN0和CAN1:回环模式下,CAN0发送,CAN1接收。
但是开发板上只有一个CAN,因此注释CAN1的内容,添加CAN0接收中断。实现接收报文后发送报文。
以下为代码:
u8 main()
{
u8 Status=FMSH_SUCCESS;
int i = 0;
TRACE_OUT(DEBUG_OUT, " FMQL Peripheral Test Version: 20211210 \r\n");
Status=ps_init();
if(Status!=PS_INIT_SUCCESS)
{
TRACE_OUT(DEBUG_OUT, " PS Initial Failed!\r\n");
return Status;
}
#if PSOC_CACHE_ENABLE
dcache_enable();
#endif
Status = FGicPs_SelfTest(&IntcInstance);
if(Status!=GIC_SUCCESS)
TRACE_OUT(DEBUG_OUT, " GIC Setup Failed!\r\n");
else
TRACE_OUT(DEBUG_OUT, " GIC Setup pass!\r\n");
#if defined(CANPS_0_DEVICE_ID)
Status = FCanPs_example();
if(Status == 0)
TRACE_OUT(DEBUG_OUT,"CAN example test pass!\n");
else
TRACE_OUT(DEBUG_OUT,"CAN example test failed,please check!\n");
#endif
}
u8 FCanPs_example(void)
{
u32 i;
u8 ret=FMSH_SUCCESS;
u32 tr_val[11];
u8 buf_send[8];
u8 buf_recv[8];
u32 timeout_cnt = CAN_LOOP_TIMEOUT;
// FSlcrPS_setCanLoop(1);
for(i = 0; i < 8; i++)
buf_send[i] = 0x11 + i; //发送data
FCanPs_Config* Config=NULL;
Config= FCanPs_LookupConfig(FPAR_CANPS_0_DEVICE_ID);
if(Config==NULL)
return FMSH_FAILURE;
ret=FCanPs_init(&g_CAN0, Config);
if(ret!=FMSH_SUCCESS)
return FMSH_FAILURE;
CAN0 发送
FCanPs_setBaudRate(&g_CAN0, CAN_BUAD_1MHZ);
FCanPs_setStdSingleACR(&g_CAN0, CAN_0_ID, data_frame, 0x00, 0x00);
FCanPs_setAMR(&g_CAN0, 0xff, 0xff, 0xff, 0xff);
g_can_recv_intr_flag = 0;
FCanPs_standardFrameTransmit(&g_CAN0, CAN_0_ID, buf_send, 8, data_frame);
FCanPs_transmissionRequest(&g_CAN0); 发送
while(FCanPs_getTransmissionCompleteStatus(&g_CAN0) == 0)
{
delay_1us();
timeout_cnt--;
if(timeout_cnt == 0)
return FMSH_FAILURE;
}
Delay_us_for(1000);
///
CAN0 接收
while(1){
can_setHanlder(&g_CAN0, CAN0_INT_ID, (FMSH_InterruptHandler)CAN0_interrupt_hanlder);
FCanPs_setReceiveInterrupt(&g_CAN0, CAN_set);
if(g_can_recv_intr_flag == 1)//接收到
{
g_can_recv_intr_flag = 0;
for(i = 0; i < 11; i++)
{
buf_recv[i] = g_can0rbuf[i+3];
}
//CAN0 发送接收到的数据
发送的ID 接收的数据
0x100 (0x)08, 20, 00, data
0x5 08, 00, A0, data
0x6 08, 00, C0, data
0x88 08, 11, 00, data
//推测:08是报头
// 第2和第3个数据是ID(ID << 5)
FCanPs_standardFrameTransmit(&g_CAN0, CAN_0_ID, buf_recv, 8, data_frame);
FCanPs_transmissionRequest(&g_CAN0);发送
Delay_us_for(1000);
}
else
TRACE_OUT(DEBUG_OUT,"CAN_receive failed\r\n"); //等待接收
//return FMSH_FAILURE;
}
return FMSH_SUCCESS;
}
移植程序
Launch IAR后,导入相应的头文件。
注释xparameters.h中的 #include xparameters_ps.h ,用 #include "fmsh_ps_parameters.h" 代替;
修改xcanps_hw.h:注释 #include "xil_io.h" ,用 #include "fmsh_common_io.h" 代替;
修改xcanps_hw.h:
宏定义
报错:(没有如下宏定义)
#define CAN_DEVICE_ID XPAR_XCANPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define CAN_INTR_VEC_ID XPAR_XCANPS_0_INTR
fmql只有:
#define SGI_ID 0U /* fmsh_gic_selftest.c */
#define CPU_ID 1U
所以SCU GIC是什么?(之后再学习)
但是推测 SGI_ID等价于INTC_DEVICE_ID ,CAN0_INT_ID等价于CAN_INTR_VEC_ID。
修改xil_printf:
#define xil_printf fmsh_print
gic
GIC的头文件定义冲突了(但是gic.h的内容大致相同 )
gic.h基本相同;gic.c大致相同(个别地方不一样)
fmq多了:
#define FMSH_CPU_ID = 0U; //定义默认的CPU ID号
/***** 以下函数zynq没有 *******/
s32 FGicPs_registerInt(FGicPs *InstancePtr, u32 Int_Id,
FMSH_InterruptHandler Handler, void *CallBackRef)
{
s32 Status;
Status = FGicPs_Connect(InstancePtr, Int_Id, Handler, CallBackRef);
if (Status != GIC_SUCCESS)
{
return Status;
}
FGicPs_Enable(InstancePtr, Int_Id);
return GIC_SUCCESS;
}
/******Interrupt Setup********/
u32 FGicPs_SetupInterruptSystem(FGicPs *InstancePtr)
{
u32 RegValue1 = 0U;
u32 Index;
u32 Status;
static FGicPs_Config* GicConfig;
GicConfig = FGicPs_LookupConfig(GIC_DEVICE_ID);
if (NULL == GicConfig) {
return GIC_FAILURE;
}
InstancePtr->Config = GicConfig;
/*
* Read the ID registers.
*/
for(Index=0U; Index<=3U; Index++) {
RegValue1 |= FGicPs_DistReadReg(InstancePtr,
((u32)FGicPs_PCELLID_OFFSET + (Index * 4U))) << (Index * 8U);
}
if(FGicPs_PCELL_ID != RegValue1){
return GIC_FAILURE;
}
/*
FGicPs_DistWriteReg(InstancePtr,
FGicPs_INT_CFG_OFFSET_CALC(32U),
0U);
*/
{
//int Status;
Status = FGicPs_CfgInitialize(InstancePtr, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != GIC_SUCCESS) {
return GIC_FAILURE;
}
}
//FMSH_ExceptionEnable();
return Status;
}
/******Enable interrupt Group********/
void FGicPs_EnableSelGroup(FGicPs *InstancePtr)
{
FGicPs_DistWriteReg(InstancePtr, FGicPs_DIST_EN_OFFSET,
0x03);
FGicPs_CPUWriteReg(InstancePtr, FGicPs_CONTROL_OFFSET, 0x1FU);
}
/******Set interrupt Group********/
void FGicPs_SetGroup(FGicPs *InstancePtr, u32 Int_Id, u8 groupNo)
{
u32 RegValue;
RegValue = FGicPs_DistReadReg(InstancePtr,
FGicPs_SECURITY_OFFSET_CALC(Int_Id));
/*
* Enable the selected interrupt source by setting the
* corresponding bit in the Enable Set register.
*/
RegValue &= ~(0x00000001 << (Int_Id%32U));
RegValue |= ((u32)groupNo <<(Int_Id%32U));
FGicPs_DistWriteReg(InstancePtr,(u32)FGicPs_SECURITY_OFFSET +
((Int_Id / 32U) * 4U), RegValue);
}
u32 FMSH_In32(u32 Addr)
{
return *(volatile u32 *) Addr;
}
void FMSH_Out32(u32 Addr, u32 Value)
{
u32 *LocalAddr = (u32 *)Addr;
*LocalAddr = Value;
}
有差别的函数:
static void CPUInitialize(FGicPs *InstancePtr)
void FGicPs_InterruptMaptoCpu(FGicPs *InstancePtr, u8 Cpu_Id, u32 Int_Id)
XScuGic
XScuGic等价于FGicPs
因此helloworld.c中涉及到的都要改:(后面添加了宏定义,这里就不用改了)
添加宏定义:
#define XScuGic_CfgInitialize FGicPs_CfgInitialize
#define XScuGic_Connect FGicPs_Connect
#define XScuGic_Enable FGicPs_Enable
#define XScuGic_Config FGicPs_Config
#define XScuGic_LookupConfig FGicPs_LookupConfig
#define XScuGic FGicPs
还在报错:
把gic相关的头文件删除,只保留fmql原来的。
已经include了xil_exception.h,为什么undefined
添加宏定义试试看:
#define XScuGic_InterruptHandler FGicPs_InterruptHandler_IRQ
exception.c
XExc_VectorTable重复定义:
xil_exception.c和exception_handler.c有相同的定义,但是不一样的地方不少,所以决定把exception_handler.c中的XExc_VectorTable注释掉。
xparameters.h和xcanps_hw.h明明已经改过了,但是再打开工程又要重新改。。。
不能注释XExc_VectorTableEntry,因为.c文件下其他的函数等需要用到这个。
那么两个.c文件重复定义结构体的解决方法是?
解决C语言重复定义:multiple definition of“xxx”问题-CSDN博客
百度安全验证
结构体定义 typedef struct 用法详解和小结-CSDN博客
mtcpsr在xil_exception.h中用到,在xpseudo_asm_gcc.h中定义。也就是说xil_exception.h必须要#include了。
exception头文件的作用是:
Xilinx zynq嵌入式vitis使用之中断设计_xilinx vitis 2021.2 嵌入式-CSDN博客
选择了比较笨的办法:(改名称)
还是报错:
有个疑问,以下代码到底要不要?
#ifndef TESTAPP_GEN
#endif
总结
添加的头文件:
删除的头文件:
fmsh的头文件都没删。也没修改内容。
添加的宏定义:
因为gic的头文件内容差不多,所以zynq的头文件就没添加,用fmsh本来的,把函数名称修改成fmsh对应的(上面的宏定义)。
用到了xparameters_ps.h中的宏定义,对应在fmsh_gic_hw.h中。(所以如果要用zynq的gic头文件的话,就要添加相关的宏定义。)
本来是想用xil_exception.h代替exception_handler.h的,因为两者的内容差别会比gic的差别大一些。
但是编译总报错(__asm__:但是fmsh中也有用到__asm__),目前以自己的水平不足以看懂这些,所以就用fmsh的exception代替了。虽然函数中的内容会有差别,但至少现在用到的函数都是fmsh中有的。比如:
运行
既然编译不报错了,就下载进去看看能不能行吧。
在CAN_SelfTest出问题:
因为zynq定义的CAN地址为0xE0008000,而fmsh为0xE0005000
但是LookupConfig()还是读取到0xE0008000。单步调试发现需要修改这里:(xcanps_g.c)
或者修改这里:
还是不行。
看以下fmsh配置CAN的流程:LookupConfig --> init --> set : Baudrate & ...
要修改寄存器配置?还是程序移植时头文件里内容的影响?
下周再继续思考吧