【RK3588开发】SPI回环
SPI回环1内核SPI子系统使能修改内核配置需要先加载默认配置然后图形界面修改后需保存配置在以下目录下勾选图中的选项****Device Drivers — -[*] SPI support—至少勾选以下选项Rockchip SPI controller driverRockschip SPI controller misc devicesUser mode SPI device driver support2设备树spi0{statusokay;assigned-clockscru CLK_SPI1;assigned-clock-rates200000000;num-cs2;pinctrl-0spi0m2_cs0spi0m2_cs1spi0m2_pins;max-freq48000000;/* spi internal clk, dont modify */spi_dev0{compatiblerockchip,spidev;reg0;spi-max-frequency12000000;spi-lsb-first;};};这样写设备树系统会有个/dev/spidev0_0的设备这里0_0,代表第一个SPI总线0和片选03应用程序①SPI 驱动数据缓存机制在spidev驱动中有一个模块参数bufsiz可以设置每次传输的最大字节数默认值通常是一个内存页大小比如4096字节当需要传输大于缓存区大小的数据时需要多次传输。②程序源码字符串回环#includestdio.h#includestdlib.h#includestdint.h#includestring.h#includefcntl.h#includeunistd.h#includesys/ioctl.h#includelinux/spi/spidev.h#defineSPI_DEV_PATH/dev/spidev0.0intfd;staticunsignedmodeSPI_MODE_0;staticuint8_tbits8;staticuint32_tspeed1000000;// 设置SPI速度为1MHzstaticuint16_tdelay;voidtransfer(intfd,uint8_tconst*tx,uint8_t*rx,size_tlen){intret;structspi_ioc_transfertr{.tx_buf(unsignedlong)tx,.rx_buf(unsignedlong)rx,.lenlen,.delay_usecsdelay,.speed_hzspeed,.bits_per_wordbits,.cs_change0,// 设置为1以在每次传输前切换片选这里不切换片选};retioctl(fd,SPI_IOC_MESSAGE(1),tr);if(ret1){perror(SPI transfer failed);}}voidspi_init(void){intret;// 打开 SPI 设备fdopen(SPI_DEV_PATH,O_RDWR);if(fd0){perror(Cant open SPI device);exit(1);}// 设置 SPI 工作模式retioctl(fd,SPI_IOC_WR_MODE,mode);if(ret-1){perror(Cant set SPI mode);exit(1);}// 设置位数retioctl(fd,SPI_IOC_WR_BITS_PER_WORD,bits);if(ret-1){perror(Cant set bits per word);exit(1);}// 设置SPI速度retioctl(fd,SPI_IOC_WR_MAX_SPEED_HZ,speed);if(ret-1){perror(Cant set max speed);exit(1);}// 打印设置printf(SPI mode: 0x%x\n,mode);printf(Bits per word: %d\n,bits);printf(Max speed: %d Hz\n,speed);}intmain(intargc,char*argv[]){if(argc!2){printf(Usage: %s string_to_send\n,argv[0]);return1;}char*tx_bufferargv[1];// 获取要发送的字符串作为命令行参数// 初始化SPI接口spi_init();// 设置要接收数据的缓冲区unsignedcharrx_buffer[strlen(tx_buffer)1];// 执行SPI数据传输transfer(fd,tx_buffer,rx_buffer,strlen(tx_buffer));// 打印发送和接收的数据printf(Sent: %s\n,tx_buffer);printf(Received: %s\n,rx_buffer);// 关闭SPI设备close(fd);return0;}③程序源码文件回环#includestdio.h#includestdlib.h#includestdint.h#includestring.h#includefcntl.h#includeunistd.h#includesys/ioctl.h#includelinux/spi/spidev.h#includesys/stat.h#defineSPI_DEV_PATH/dev/spidev0.0#defineCHUNK_SIZE4096// 4KB 块大小适合大多数SPI控制器#defineFILE_SIZE(8*1024*1024)// 8MBintfd;staticunsignedmodeSPI_MODE_0;staticuint8_tbits8;staticuint32_tspeed12000000;staticuint16_tdelay;// SPI 传输函数voidtransfer(intfd,uint8_tconst*tx,uint8_t*rx,size_tlen){intret;structspi_ioc_transfertr{.tx_buf(unsignedlong)tx,.rx_buf(unsignedlong)rx,.lenlen,.delay_usecsdelay,.speed_hzspeed,.bits_per_wordbits,.cs_change0,};retioctl(fd,SPI_IOC_MESSAGE(1),tr);if(ret1){perror(SPI transfer failed);}}// SPI 初始化voidspi_init(void){intret;// 打开 SPI 设备fdopen(SPI_DEV_PATH,O_RDWR);if(fd0){perror(Cant open SPI device);exit(1);}// 设置 SPI 工作模式retioctl(fd,SPI_IOC_WR_MODE,mode);if(ret-1){perror(Cant set SPI mode);exit(1);}// 设置位数retioctl(fd,SPI_IOC_WR_BITS_PER_WORD,bits);if(ret-1){perror(Cant set bits per word);exit(1);}// 设置SPI速度retioctl(fd,SPI_IOC_WR_MAX_SPEED_HZ,speed);if(ret-1){perror(Cant set max speed);exit(1);}// 打印设置printf(SPI mode: 0x%x\n,mode);printf(Bits per word: %d\n,bits);printf(Max speed: %d Hz\n,speed);}// 检查文件大小off_tget_file_size(constchar*filename){structstatst;if(stat(filename,st)0){returnst.st_size;}perror(Cannot get file size);return-1;}// 传输文件并回环存储inttransfer_file(constchar*input_file,constchar*output_file){FILE*in_fp,*out_fp;uint8_t*tx_buffer,*rx_buffer;size_ttotal_bytes0;size_tbytes_read,chunk_size;// 打开输入文件in_fpfopen(input_file,rb);if(!in_fp){perror(Cannot open input file);return-1;}// 打开输出文件out_fpfopen(output_file,wb);if(!out_fp){perror(Cannot open output file);fclose(in_fp);return-1;}// 分配缓冲区tx_buffermalloc(CHUNK_SIZE);rx_buffermalloc(CHUNK_SIZE);if(!tx_buffer||!rx_buffer){perror(Memory allocation failed);fclose(in_fp);fclose(out_fp);return-1;}printf(Starting file transfer...\n);printf(Input file: %s\n,input_file);printf(Output file: %s\n,output_file);printf(Chunk size: %d bytes\n,CHUNK_SIZE);// 分块传输文件while((bytes_readfread(tx_buffer,1,CHUNK_SIZE,in_fp))0){// 执行 SPI 传输transfer(fd,tx_buffer,rx_buffer,bytes_read);// 将接收到的数据写入输出文件fwrite(rx_buffer,1,bytes_read,out_fp);total_bytesbytes_read;// 显示进度if(total_bytes%(1024*1024)0){printf(Transferred: %zu/%d MB (%.1f%%)\n,total_bytes/(1024*1024),FILE_SIZE/(1024*1024),(double)total_bytes/FILE_SIZE*100);}// 如果达到 8MB停止传输if(total_bytesFILE_SIZE){break;}}printf(Transfer completed: %zu bytes\n,total_bytes);// 清理资源free(tx_buffer);free(rx_buffer);fclose(in_fp);fclose(out_fp);returntotal_bytes;}// 验证文件内容是否相同intverify_files(constchar*file1,constchar*file2){FILE*fp1,*fp2;uint8_tbuf1[CHUNK_SIZE],buf2[CHUNK_SIZE];size_tbytes_read1,bytes_read2;size_ttotal_bytes0;intdifferences0;fp1fopen(file1,rb);fp2fopen(file2,rb);if(!fp1||!fp2){perror(Cannot open files for verification);if(fp1)fclose(fp1);if(fp2)fclose(fp2);return-1;}printf(Verifying files...\n);do{bytes_read1fread(buf1,1,CHUNK_SIZE,fp1);bytes_read2fread(buf2,1,CHUNK_SIZE,fp2);if(bytes_read1!bytes_read2){printf(File size mismatch!\n);differences;break;}for(size_ti0;ibytes_read1;i){if(buf1[i]!buf2[i]){if(differences10){// 只显示前10个差异printf(Difference at offset %zu: 0x%02X ! 0x%02X\n,total_bytesi,buf1[i],buf2[i]);}differences;}}total_bytesbytes_read1;}while(bytes_read10bytes_read20);fclose(fp1);fclose(fp2);if(differences0){printf(Files are identical! Verification passed.\n);}else{printf(Found %d differences in %zu bytes.\n,differences,total_bytes);}returndifferences;}intmain(intargc,char*argv[]){if(argc!3){printf(Usage: %s input_bin_file output_bin_file\n,argv[0]);printf(Example: %s input_8mb.bin output_8mb.bin\n,argv[0]);return1;}constchar*input_fileargv[1];constchar*output_fileargv[2];// 检查输入文件大小off_tfile_sizeget_file_size(input_file);if(file_size!FILE_SIZE){printf(Warning: Input file size is %ld bytes, expected %d bytes\n,file_size,FILE_SIZE);printf(Continue anyway? (y/n): );charresponsegetchar();if(response!yresponse!Y){return1;}}// 初始化SPI接口spi_init();// 传输文件size_ttransferredtransfer_file(input_file,output_file);if(transferred0){printf(File transfer successful!\n);// 验证文件verify_files(input_file,output_file);}else{printf(File transfer failed!\n);}// 关闭SPI设备close(fd);return0;}4验证用杜邦线把MISO和MOSI短接测试结果如下