si551x时钟芯片linux下调试笔记

devtools/2024/10/21 16:45:02/

目录

    • 前言
    • 一、依赖文档、工具
    • 二、让芯片工作的流程
    • 三、以上步骤的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/devtools/127613.html

相关文章

基于stm32的楼宇照明控制系统设计

基于stm32的楼宇照明控制系统设计 项目说明一、绪论1.1 研究背景1.2 研究意义1.4 研究内容 二、系统方案设计2.1 微控制器方案选择2.2 信息检测模块方案选择2.3 WiFi模块选择2.4 终端显示2.5 WiFi无线通信实现方法 三、系统硬件电路图设计3.1 整体电路图设计3.2 主控制器设计3.…

电脑格式化了还能恢复数据吗?

许多人在使用电脑时可能会误操作或出于需要对电脑硬盘进行格式化&#xff0c;格式化会迅速清空数据。问题是格式化后的数据还能恢复吗&#xff1f;答案是&#xff1a;在某些情况下&#xff0c;格式化后的数据是可以恢复的。不过&#xff0c;恢复的成功率取决于格式化的类型和后…

【进阶OpenCV】 (17)-- Dlib库 --实现人脸检测

文章目录 Dlib库一、Dlib库安装二、实现人脸检测1. 生成人脸检测器2. 检测人脸3. 显示人脸 总结 Dlib库 Dlib提供了丰富的图像处理和计算机视觉工具&#xff0c;如面部特征检测、物体检测、图像变换等&#xff0c;这些工具使得开发者能够轻松地进行各种图像处理任务。 一、Dl…

java版Spring Cloud+Mybatis+Oauth2+分布式+微服务+实现工程管理系统

鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;公司对内部工程管…

[C编程入门] 第七章:C语言中的文件操作

&#x1f496;&#x1f496;⚡️⚡️专栏&#xff1a;C编程入门-轻松入门/系统总结⚡️⚡️&#x1f496;&#x1f496; [C编程入门] 专为C语言初学者设计&#xff0c;提供轻松易懂的入门教程与系统的知识总结。本专栏将带你从零开始&#xff0c;循序渐进地掌握C语言的核心概念…

创客项目秀 | 基于XIAO ESP32S3 Sense 的最小 DIY 相机

作者&#xff1a;Md. Khairul Alam 故事背景 我一直对间谍小工具和微型电子产品非常着迷。我一直想创造一个可以装在口袋里的微型相机&#xff0c;能够悄无声息地捕捉精彩瞬间。随着技术的进步和像 Xiao ESP32S3 Sense 这样功能强大的微控制器的出现&#xff0c;我终于有机会实…

webstorm 编辑器配置及配置迁移

1.下载地址 WebStorm&#xff1a;JetBrains 出品的 JavaScript 和 TypeScript IDE 其他版本下载地址 2.安装 点击下一步安装&#xff0c;可根据需要是否删除已有版本 注意&#xff1a; 完成安装后需要激活 3.设置快捷键 以下为个人常用可跳过或根据需要设置 如&#xff1a…

ONLYOFFICE 文档8.2版本已发布:PDF 协作编辑、改进界面、性能优化等更新

ONLYOFFICE 在线编辑器最新版本已经发布&#xff0c;其中包含30多个新功能和500多个错误修复。阅读本文了解所有更新。 关于 ONLYOFFICE 文档 ONLYOFFICE 是一个开源项目&#xff0c;专注于高级和安全的文档处理。坐拥全球超过 1500 万用户&#xff0c;ONLYOFFICE 是在线办公领…