si551x时钟芯片linux下调试笔记

news/2024/10/22 22:28:01/

目录

    • 前言
    • 一、依赖文档、工具
    • 二、让芯片工作的流程
    • 三、以上步骤的SOC下代码实现

前言

本文总结调试SKYWORKS芯片厂商Si5512时钟芯片时的笔记,基于linux5.10.xxx内核,在arm64架构的SOC上验证;

一、依赖文档、工具

文档名说明下载链接
Si5518/12/10/08 Reference Manual参考手册厂家技术支持
Si 5512 Data Sheet数据手册https://www.skyworksinc.com/-/media/SkyWorks/SL/documents/public/data-shorts/si5512-datashort.pdf
AN1360: Serial Communications and API Programming Guide for Si536x, Si540x, and Si55xx Devicesapi使用手册https://www.skyworksinc.com/-/media/SkyWorks/SL/documents/public/application-notes/an1360-si55xx-540x-536x-serial-comm-api-prog-guide.pdf

PC工具

ClockBuilder-Pro-4.13.0.2.exe,简称CBPro用于生成配置时钟芯片的bin文件;
可以从参考文档中找到下载链接;
下载链接 https://www.skyworksinc.com/en/Application-Pages/Clockbuilder-Pro-Software

二、让芯片工作的流程

见api手册章节

在这里插入图片描述

步骤解释

1、使用CBPro生成用于可以下载到芯片ram中的配置文件prod_fw.boot.bin和user_config.boot.bin,软件的使用方法参照软件内置的参考工程,具体bin文件配置按照实际硬件设计的时钟输出需求配置后导出以上文件;
2、给芯片上电,并通过SOC拉低芯片的复位脚保持低电平一段时间大约1s后拉高复位引脚,对芯片进行一次复位;
3、SOC使用SIO_TEST命令验证串行通信接口通信链路是否正常,芯片支持I2C和SPI接口,这里以SPI 四线为例;
4、SOC使用SIO_INFO命令获取时钟芯片串行通信时一次支持的传输的数据量大小;
5、SOC使用RESTART命令对时钟芯片进行重启,这里可以理解成软重启;
6、SOC通过HOST_LOAD命令下载prod_fw.boot.bin文件到时钟芯片的ram中;
7、SOC通过HOST_LOAD命令下载user_config.boot.bin文件到时钟芯片的ram中;
8、SOC通过BOOT命令对芯片进行boot,可以理解成使下载到ram中的文件进行配置生效;
9、SOC通过REFERENCE_STATUS命令检查时钟是否锁定;

三、以上步骤的SOC下代码实现

1、配置设备树
根据芯片所连接SOC的spi外设的情况配置设备树节点

&spiXXX {num-cs = <1>; //假设此spi下有一个需要驱动处理的片选设备cs-gpios = <填写gpio配置>;status = "okay";#addres-cells = <1>;#size-cells = <0>;spidev0: si5512@0 { compatible = "rohm,dh2228fv";spi-max-frequency = <1000000>;reg = <0>;};
};

2、设备节点生成
linux5.10.xxx内核驱动会解析设备树匹配后生成设备节点/dev/spidevX.X;

3、设备树中引脚配置
主要对与时钟芯片相连的spi、reset复位脚、cs片选脚进行配置;

4、linux C的应用实现

api文档中是C#实现的,这里写下C代码的实现

4.1、打开初始化spi设备节点

struct spi_ioc_transfer transfer;
transfer.bits_per_word = 8;
uint32_t  spispeed = 1000000uint8_t   spimode = 3; //0或者3模式
uint8_t   spibits = 8;
char *devicename = "/dev/spidev1.0"int fd_spi = -1;
//全局命令数组
uint8_t check_for_CTS_request[2] = { 0xD0, 0x00 };
uint8_t sio_test_request[4] = { 0xC0, 0x01, 0xAB, 0xCD };
uint8_t sio_test_response[5] = { 0xD0, 0x00, 0x00, 0x00, 0x00 };
uint8_t sio_info_request[2] = { 0xC0, 0x02 };
uint8_t sio_info_response[6] = { 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t restart_request[3] = { 0xC0, 0xF0, 0x00 };
uint8_t restart_response[2] = { 0xD0, 0x00 };
uint8_t boot_request[2] = { 0xC0, 0x07 };
uint8_t boot_response[2] = { 0xD0, 0x00 };
uint8_t reference_status_request[2] = { 0xC0, 0x16 };
uint8_t reference_status_response[6] = { 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t host_load_command[1024] = { 0xC0, 0x05 };
uint8_t host_load_response[2] = { 0xD0, 0x00 };
uint8_t sysref_request[2] = { 0xC0, 0x22 };
uint8_t sysref_response[3] = { 0xD0, 0x00,0x00 };
uint8_t response[20]={0};
unsigned char buffer[40960]; // 存储文件数据
unsigned char buffer_1k[1024];
const char *file1path = "prod_fw_pps.boot.bin";
const char *file2path = "user_config.boot.bin";
uint8_t spi_init()
{fd_spi = open(devicename, O_RDWR);if (fd_spi < 0){printf("Unable to open '%s'", devicename);return 0;}else{if (ioctl(fd_spi , SPI_IOC_WR_MODE, &spimode) == -1){printf("can not set spi mode\n");return 0;}if (ioctl(fd_spi , SPI_IOC_RD_MODE, &spimode) == -1){printf("can not get spi mode\n");return 0;}if (ioctl(fd_spi , SPI_IOC_WR_BITS_PER_WORD, &spibits) == -1){printf("can not set bits per word.");return 0;}if (ioctl(fd_spi , SPI_IOC_RD_BITS_PER_WORD, &spi.bits) == -1){printf("can not get bits per word.");return 0;}if (ioctl(fd_spi , SPI_IOC_WR_MAX_SPEED_HZ, &spispeed) == -1){printf("can not set max speed HZ");return 0;}if (ioctl(fd_spi , SPI_IOC_RD_MAX_SPEED_HZ, &spispeed) == -1){printf("can not get max speed HZ");return 0;}}return 1;
}

4.2、读写通用函数

uint8_t send_data[2048]={0};
uint8_t recv_data[2048]={0};
uint8_t spi_stransfer(uint8_t *in,uint32_t len, uint8_t *out)
{memset(recv_data,0x00,2048);if (fd_spi >= 0){if(in[0] == 0xC0) //write{memcpy(send_data,in,len);printf("send write data:");for(uint32_t i=0;i<len;i++){//printf("%02X ",send_data[i]);     }printf("\n");transfer.tx_buf = (unsigned long)send_data;transfer.len = len;int ret = ioctl(fd_spi , SPI_IOC_MESSAGE(1), &transfer);if (ret == 1){printf("Error in writing in SPI");return 0xFF;}return 0x00;}else  //read{memcpy(send_data,in,len);printf("send read data:");for(uint32_t i=0;i<len;i++){printf("%02X ",send_data[i]);  }printf("\n");transfer.tx_buf = (unsigned long)send_data;transfer.rx_buf = (unsigned long)recv_data;transfer.len = len;int ret = ioctl(fd_spi , SPI_IOC_MESSAGE(1), &transfer);printf("read data ret:");for(uint32_t i=0;i<len;i++){   printf("%02X ",recv_data[i]);    }printf("\n");if (ret != 1){memcpy(out,recv_data,len);return out[1]; // return data alone to driver}else{printf("Error in read in SPI");return 0xFF;}}}else{printf("not initialized spi\n");return 0xFF;}  
}

4.3、check CTS函数
api文档的流程框图中没有这一步,示例代码中有此函数调用

void check_for_CTS()
{printf("check_for_CTS\n");				spi_stransfer(check_for_CTS_request,sizeof(check_for_CTS_request)/sizeof(check_for_CTS_request[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){sleep(1);spi_stransfer(check_for_CTS_request,sizeof(check_for_CTS_request)/sizeof(check_for_CTS_request[0]),response);printf("ret:%02X,\n",response[1]);}
}

4.4、SIO_TEST命令函数

void SIO_TEST()
{printf("SIO_TEST\n");				spi_stransfer(sio_test_request,sizeof(sio_test_request)/sizeof(sio_test_request[0]),response);memset(response,0x00,20);spi_stransfer(sio_test_response,sizeof(sio_test_response)/sizeof(sio_test_response[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){sleep(1);spi_stransfer(sio_test_response,sizeof(sio_test_response)/sizeof(sio_test_response[0]),response);printf("ret:%02X,\n",response[1]);}
}

4.5、SIO_INFO命令函数

uint32_t SIO_INFO()
{printf("SIO_INFO\n");				spi_stransfer(sio_info_request,sizeof(sio_info_request)/sizeof(sio_info_request[0]),response);memset(response,0x00,20);spi_stransfer(sio_info_response,sizeof(sio_info_response)/sizeof(sio_info_response[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){sleep(1);spi_stransfer(sio_info_response,sizeof(sio_info_response)/sizeof(sio_info_response[0]),response);printf("ret:%02X,\n",response[1]);}uint32_t CMD_BUFFER_SIZE = (ret[3] << 8) + ret[2];return CMD_BUFFER_SIZE ;
}

4.6、RESTART命令函数

void RESTART()
{printf("RESTART\n");				spi_stransfer(restart_request,sizeof(restart_request)/sizeof(restart_request[0]),response);memset(response,0x00,20);spi_stransfer(restart_response,sizeof(restart_response)/sizeof(restart_response[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){sleep(1);spi_stransfer(restart_response,sizeof(restart_response)/sizeof(restart_response[0]),response);printf("ret:%02X,\n",response[1]);}}

4.7、HOST_LOAD命令函数

void HOST_LOAD(const char *filepath, uint32_t CMD_BUFFER_SIZE) 
{FILE *fp;unit32_t  buffer_size =0;buffer_size = CMD_BUFFER_SIZE;size_t bytes_read;int ret = 0;struct stat st;memset(buffer,0x00,40960);memset(buffer_1k,0x00,1024);// 打开文件printf("open filename:%s\n",filepath);fp = fopen(filepath, "rb");if (fp == NULL) {perror("Error opening file");}//get file lenret = stat(filepath, &st);if (ret != 0) {perror("stat");}printf("File size: %ld bytes\n", st.st_size);//read fileif ( (bytes_read = fread(buffer, 1, st.st_size, fp)) > 0 ){printf("read bytes:%ld\r\n",bytes_read);}uint32_t i;for(i =0;i<(bytes_read/(buffer_size-2));i++){printf("part%d\n",i);memcpy((void *)buffer_1k,&buffer[i*(buffer_size-2)],(buffer_size-2));//logfor(uint32_t j=0;j<(buffer_size-2);j++){//printf("%02X ",buffer_1k[j]);}printf("\n");//writehost_load_command[0] = 0xC0;host_load_command[1] = 0x05;memcpy((void *)(&host_load_command[2]),(void *)buffer_1k,(buffer_size-2));spi_stransfer(host_load_command,buffer_size,response);  //readspi_stransfer(host_load_response,sizeof(host_load_response)/sizeof(host_load_response[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){sleep(1);spi_stransfer(host_load_response,sizeof(host_load_response)/sizeof(host_load_response[0]),response);printf("ret:%02X,\n",response[1]);}}//文件大小不是完整的buffersize-2的整数单独处理printf("end part%d\n",i);memcpy((void *)buffer_1k,&buffer[i*(buffer_size-2)],bytes_read%(buffer_size-2));for(uint32_t j=0;j<bytes_read%1022;j++){//printf("%02X ",buffer_1k[j]);}printf("\n");//writehost_load_command[0] = 0xC0;host_load_command[1] = 0x05;memcpy((void *)(&host_load_command[2]),(void *)buffer_1k,bytes_read%(buffer_size-2));spi_stransfer(host_load_command,bytes_read%(buffer_size-2)+2,response);//readspi_stransfer(host_load_response,sizeof(host_load_response)/sizeof(host_load_response[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){sleep(1);spi_stransfer(host_load_response,sizeof(host_load_response)/sizeof(host_load_response[0]),response);printf("ret:%02X,\n",response[1]);}// 关闭文件fclose(fp);}

4.8、BOOT命令实现函数

void BOOT()
{printf("BOOT\n");				spi_stransfer(boot_request,sizeof(boot_request)/sizeof(boot_request[0]),response);memset(response,0x00,20);spi_stransfer(boot_response,sizeof(boot_response)/sizeof(boot_response[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){sleep(1);spi_stransfer(boot_response,sizeof(boot_response)/sizeof(boot_response[0]),response);printf("ret:%02X,\n",response[1]);}}

4.9、获取锁定状态函数

bool REFERENCE_STATUS()
{printf("REFERENCE_STATUS\n");				spi_stransfer(reference_status_request,sizeof(reference_status_request)/sizeof(reference_status_request[0]),response);memset(response,0x00,20);spi_stransfer(reference_status_response,sizeof(reference_status_response)/sizeof(reference_status_response[0]),response);printf("ret:%02X,\n",response[1]);while(response[1]!=0x80){if (response[1] == 0x90) {printf("FWERR triggered. See text under Common Errors.");}sleep(1);printf("again read\n");spi_stransfer(reference_status_response,sizeof(reference_status_response)/sizeof(reference_status_response[0]),response);printf("ret:%02X,\n",response[1]);}return ( (response[1] == 0x80) & (response[2] == 0x00) & (response[3] == 0) & (response[4] == 0) & (response[5] == 0) ); }

4.10、复位时钟芯片的函数

void hardware_reset()
{//拉低链接时钟芯片的复位脚sleep(1);//拉高链接时钟芯片的复位脚
}

4.11、整体设置芯片的函数

void  config_si5512()
{uint32_t  cmd_buffer_size = 0;hardware_reset();check_for_CTS();SIO_TEST();cmd_buffer_size = SIO_INFO();RESTART();HOST_LOAD(file1path,cmd_buffer_size);HOST_LOAD(file2path,cmd_buffer_size);BOOT();sleep(2);uint8_t reference_locked = REFERENCE_STATUS();while (reference_locked == false) {printf("waiting lock\n");reference_locked = REFERENCE_STATUS();}if(reference_locked==true){printf("clock is locked\n");}
}

http://www.ppmy.cn/news/1541169.html

相关文章

第 4 章:Vue 中的 ajax

1. 解决开发环境 Ajax 跨域问题 vue脚手架配置代理 原理图&#xff1a; 1.1 方法一 在vue.config.js中添加如下配置&#xff1a; devServer:{proxy:"http://localhost:5000" // 这个5000 是请求目标的端口号 }说明&#xff1a; 优点&#xff1a;配置简单&…

已发布金融国家标准目录(截止2024年3月)

已发布金融国家标准目录2024年3月序号标准编号标准名称

pikachu靶场CSRF-get测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、抓包使用burp生成csrf脚本 四、源代码分析 五、结论 一、测试环境 1、系统环境 渗透机&#xff1a;本机(127.0.0.1) 靶 机&#xff1a;本机(127.0.0.1) 2、使用工具/软件 Burp sui…

Unity开发Hololens项目

Unity打包Hololens设备 目录Visual Studio2019 / Visual Studio2022 远端部署设置Visual Studio2019 / Visual Studio2022 USB部署设置Hololens设备如何查找自身IPHololens设备门户Unity工程内的打包设置 目录 记录下自己做MR相关&#xff1a;Unity和HoloLens设备的历程。 Vi…

请求的crossDomain和withCredentials字段

场景 axios请求头种不携带withCredentials字段会出现跨域错误。 分析 1. crossDomain: true crossDomain 是一个配置选项&#xff0c;用来表示即将发出的请求是否是一个跨域请求。 当 crossDomain 设置为 true 时&#xff0c;axios 会使用 XMLHttpRequest 的 withCredentials …

【v5.3.0】修复订单批量发货提示 isPicUpload is not defined

使用订单批量发货的时候&#xff0c;没有反应&#xff0c;控制台提示 ReferenceError: isPicUpload is not defined 修改文件src/pages/order/orderList/components/tableList.vue 把isPicUpload改成isFileUpload&#xff0c;然后重新打包admin后台上传即可

Oracle里面,with ... as 用法介绍

在Oracle数据库中&#xff0c;WITH AS 子句&#xff08;也称为公用表表达式&#xff0c;CTE, Common Table Expression&#xff09;是一种在查询中定义临时结果集的方法。这个临时结果集可以在后续的查询中被引用&#xff0c;就像是一个临时的表或视图一样。使用 WITH AS 子句可…

【C#】在 WinForms 中使用 MVVM(Model-View-ViewModel) 设计模式

结合当前的 DevExpress 项目&#xff0c;在 WinForms 中使用 MVVM&#xff08;Model-View-ViewModel&#xff09; 设计模式。这个例子将通过数据绑定、命令绑定来展示 MVVM 模式的运用。 1. 项目结构 假设我们要实现一个简单的应用程序&#xff0c;它有一个文本框和一个按钮&…