fmql之CAN调试

刚刚把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 & ...

要修改寄存器配置?还是程序移植时头文件里内容的影响?

下周再继续思考吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/666732.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

重生之 SpringBoot3 入门保姆级学习(11、日志的进阶使用)

重生之 SpringBoot3 入门保姆级学习&#xff08;11、日志的进阶使用&#xff09; 3.2.4 文件输出3.2.5 日志文档的归档与切割 3.2.4 文件输出 配置 application.properties # 日志文件名 如果不写路径默认就是在项目根路径建立 demo.log 文件 推荐写法 D:\\demo.log 路径 文…

虚拟机Ubuntu 22.04上搭建GitLab操作步骤

GitLab是仓库管理系统&#xff0c;使用Git作为代码管理工具。GitLab提供了多个版本&#xff0c;包括社区版(Community Edition)和企业版(Enterprise Edition)。实际应用场景中要求CPU最小4核、内存最小8GB&#xff0c;非虚拟环境。 以下是在虚拟机中安装社区版步骤&#xff1a;…

R语言ggplot2包绘制高端堆积柱状图

数据和代码获取&#xff1a;请查看主页个人信息&#xff01;&#xff01;&#xff01; 关键词“高端堆积柱状图” 大家好&#xff0c;今天我将介绍如何使用ggplot2包绘制高端堆积柱状图。 本次绘图灵感来源于下面这篇文章&#xff0c;之所以复现这张图&#xff0c;有这么几个原…

查看docker中各个容器所占的资源

要查看Docker中的每个容器占用的资源&#xff0c;可以使用docker stats命令。这个命令提供了容器的实时资源使用统计&#xff0c;包括内存使用情况。以下是如何使用docker stats命令的示例&#xff1a; docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsa…

Nginx企业级负载均衡:技术详解系列(14)—— 账户认证功能

你好&#xff0c;我是赵兴晨&#xff0c;97年文科程序员。 你有没有听说过Nginx的账户认证功能&#xff1f;这可不只是一个技术问题&#xff0c;它关系到我们上网时的安全和便利。就像家里需要一把钥匙才能进们一样&#xff0c;Nginx的账户认证功能就是确保有只有授权的人才能…

Linux-在centos7中为普通用户配置sudo认证

目录 前言一、sudo是什么&#xff1f;二、配置sudo三、测试 前言 本篇文章介绍如何在centos7中为普通用户配置sudo认证 一、sudo是什么&#xff1f; sudo是一个命令&#xff0c;其作用是为普通用户以临时管理员&#xff08;root&#xff09;的身份去执行一条命令。 例如&…

ConvNeXt(CVPR 2022)论文解读

paper&#xff1a;A ConvNet for the 2020s official implementation&#xff1a;https://github.com/facebookresearch/ConvNeXt third-party implementation&#xff1a;https://github.com/huggingface/pytorch-image-models/blob/main/timm/models/convnext.py 背景 在…

面试杂谈k8s

其实看我之前的博客&#xff0c;k8s刚有点苗头的时候我就研究过&#xff0c;然后工作的时候间接接触 也自己玩过 但是用的不多就忘记了&#xff0c;正苦于不知道写什么&#xff0c;水一篇 用来面试应该是够了 支持云应用开发、运行与运维一体化的云应用平台软件应运而生 k8s核…

JVM 指针压缩

运用java内存对齐填充&#xff0c;对java内存进行8字节划分&#xff0c;java对象指针映射到每个划分区域上&#xff0c;使得4个字节&#xff08;32位&#xff09;表示2^32个地址&#xff0c;从而使4个字节指针映射32G内存空间。 1.为什么进行指针压缩&#xff1a; jvm从32位变…

【DSP】xDAIS算法标准

1. 简介 在安装DSP开发支持包时&#xff0c;有名为 “xdais_7_21_01_07”文件夹。xDAIS全称: TMS320 DSP Algorithm Standard(算法标准)。39条规则&#xff0c;15条指南。参考文档。参考文章。 2. 三个层次 3.接口 XDAIS Digital Media。编解码引擎。VISA&#xff08;Video&…

18.Redis之哨兵

1.哨兵机制的介绍 通过自动化的手段,来解决主节点挂了的问题~~ 哨兵机制, 是通过独立的 进程 来体现的.和之前 redis-server 是不同的进程!! redis-sentine| 不负责存储数据,只是对其他的 redis-server 进程起到监控的效果~~ 通常哨兵节点,也会搞一个集合~~(多个哨兵节点构成的…

汽车MCU虚拟化--对中断虚拟化的思考(2)

目录 1.引入 2.TC4xx如何实现中断虚拟化 3.小结 1.引入 其实不管内核怎么变&#xff0c;针对中断虚拟化无非就是上面两种&#xff0c;要么透传给VM&#xff0c;要么由Hypervisor统一分发。汽车MCU虚拟化--对中断虚拟化的思考(1)-CSDN博客 那么&#xff0c;作为车规MCU龙头…

基于ES安装IK分词插件

前言 IK分词器插件是为Elasticsearch设计的中文分词插件&#xff0c;由Elasticsearch的官方团队之外的开发者medcl开发。它主要针对中文文本的分词需求&#xff0c;提供了较为准确的中文分词能力。以下是IK分词器插件的一些特点&#xff1a; 智能分词&#xff1a;IK分词器采用基…

thinkphp6 自定义的查询构造器类

前景需求&#xff1a;在查询的 时候我们经常会有一些通用的&#xff0c;查询条件&#xff0c;但是又不想每次都填写一遍条件&#xff0c;这个时候就需要重写查询类&#xff08;Query&#xff09; 我目前使用的thinkphp版本是6.1 首先自定义CustomQuery类继承于Query <?p…

戴尔科技:一盆冷水浇醒了AIPC

这年头&#xff0c;只要沾上英伟达的公司&#xff0c;不论美股还是大A,都跟着鸡犬升天几轮过&#xff0c;但昨晚英伟达蒸发1064亿美元&#xff0c; 跟着遭罪的也不少&#xff0c;有没有一夜惊魂梦醒的感觉&#xff1f; 今天我们来说说——戴尔科技。 昨晚戴尔科技大跌5.18%&a…

R语言ggplot2包绘制网络地图

重要提示&#xff1a;数据和代码获取&#xff1a;请查看主页个人信息&#xff01;&#xff01;&#xff01; 载入R包 rm(listls()) pacman::p_load(tidyverse,assertthat,igraph,purrr,ggraph,ggmap) 网络节点和边数据 nodes <- read.csv(nodes.csv, row.names 1) edges…

网页截图并添加美观外壳:无需PS轻松实现的方法

在日常生活和工作中&#xff0c;我们经常需要截取网页的屏幕快照&#xff0c;以便于分享、保存或用于其他用途。尽管许多人认为使用Photoshop&#xff08;PS&#xff09;是最佳选择&#xff0c;但实际上&#xff0c;有许多更简单、快捷的方法可以帮助我们实现这一目标&#xff…

时间控件,开始时间和结束时间限制

****开始时间必须小于结束时间 如果选择了结束时间&#xff0c;开始时间必须小于结束时间 //开始时间<el-date-pickerstyle"width:190px;"v-model"searchForm.clsjdate"placeholder"请选择日期"type"date"value-format"yyyy-…

【学习笔记】数据结构(二)

线性表 文章目录 线性表1、线性结构2、线性表2.1 线性表定义2.2 类型定义2.2 顺序存储结构&#xff08;Sequence List&#xff09;2.3 链式存储结构2.3.1 单链表2.3.2 循环链表2.3.3 双链表2.3.4 单链表、循环链表、双向链表的时间效率比较2.3.5 链式存储结构优缺点 2.4 顺序表…

可用于嵌入式的解释器调研对比,及lua解释器介绍

嵌入式不一定只能用C! ---------------------------------------------------------------------------------------手动分割线-------------------------------------------------------------------------------- 本文章参考了以下文章&#xff1a; 这里是引用 ------------…