当前位置:   article > 正文

Beagleboneblack 中DDS模块驱动源码(AD9833)_ad9833 源码

ad9833 源码

参考博客:基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write

https://blog.csdn.net/u014281970/article/details/82145664

  1. /*ad9833.c*/
  2. /*
  3. * AD9833 of ADI driver code for Beagleboneblack debian9.5 kernel 4.14.79
  4. *
  5. * Copyright (C) 2018 Wei Haochen 2019/1/21 modify by wangsong
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * MULTIBEANS, NPU Youyi West Ave, Beilin District, Xi'an, China.
  20. */
  21. #include <linux/module.h> /* Every Linux kernel module must include this head */
  22. #include <linux/init.h> /* Every Linux kernel module must include this head */
  23. #include <linux/kernel.h> /* printk() */
  24. #include <linux/fs.h> /* struct fops */
  25. #include <linux/errno.h> /* error codes */
  26. #include <linux/cdev.h> /* cdev_alloc() */
  27. #include <linux/ioport.h> /* request_mem_region() */
  28. #include <linux/delay.h>
  29. #include <linux/moduleparam.h>
  30. #include <linux/types.h>
  31. #include <linux/gpio.h>
  32. #include <linux/device.h>
  33. #include <linux/types.h>
  34. #include <linux/miscdevice.h> //必须有
  35. #include <asm/uaccess.h>
  36. #include <asm/div64.h>
  37. #include <asm/atomic.h>
  38. #include <asm/unistd.h>
  39. #include <asm/io.h>
  40. #define DRV_AUTHOR "Wei haochen Wangsong"
  41. #define DRV_DESC "AD9833 on AM335X beaglebone"
  42. #define DRV_NAME "AD9833-ADI" //设备名称
  43. #define AD9833_SIZE 0x1000
  44. #define MEM_CLEAR 0x1
  45. #define AD9833_MAJOR 230 //主设备号
  46. #define AD9833_REG_RESET 0x0100 //根据AD9833寄存器设定的重启
  47. #define AD9833_FREQ0_REG 0
  48. #define AD9833_FREQ1_REG 1
  49. //AD9833_MAGIC ioctl命令需要的参数,描述了ioctl命令的类型,8位。每种设备或系统都可以指定自己的一个类型号
  50. //ioctl用这个类型来表示ioctl命令所属的设备或驱动,一般用ASCII码字符来表示,如‘a’/.
  51. #define AD9833_MAGIC 'k'
  52. #define CMD_PARA_FREQ 0x10
  53. #define CMD_PARA_PHASE 0x11
  54. #define CMD_PARA_TYPE 0x12
  55. //_IO(type,nr):无数据传输。幻数(type)\序号(nr)
  56. #define CMD_TYPE_SIN _IO( AD9833_MAGIC, 0) //命令选择正弦波
  57. #define CMD_TYPE_TRI _IO( AD9833_MAGIC, 1) //命令选择三角波
  58. #define CMD_TYPE_SQE _IO( AD9833_MAGIC, 2) //命令选择方波
  59. #define CMD_FREQ_SET(X) _IO( CMD_PARA_FREQ, X)
  60. #define CMD_PHASE_SET(X) _IO( CMD_PARA_PHASE, X )
  61. #define CMD_TYPE_SET(X) _IO( CMD_PARA_TYPE,X )
  62. #define IO_HIGH 1
  63. #define IO_LOW 0
  64. //对应的beaglebone这个板子的GPIO
  65. #define AD9833_FSY_IO 30 //P9header 11
  66. #define AD9833_CLK_IO 48 //P9header 15
  67. #define AD9833_DAT_IO 49 //P9header 23
  68. //下面三个函数都仅仅在模拟SPI时序时候使用
  69. #define io_clk(x) gpio_set_value( AD9833_CLK_IO,x )
  70. #define io_fsy(x) gpio_set_value( AD9833_FSY_IO,x )
  71. #define io_dat(x) gpio_set_value( AD9833_DAT_IO,x )
  72. typedef struct ad9833_t AD9833;
  73. enum ad9833_wavetype_t{
  74. SIN,SQU,TRI
  75. };
  76. struct ad9833_hw_t {
  77. unsigned int clk;
  78. unsigned int sdi;
  79. unsigned int fsy;
  80. };
  81. struct ad9833_t {
  82. struct ad9833_hw_t hw;
  83. struct ad9833_t *self;
  84. enum ad9833_wavetype_t wave_type;
  85. struct cdev cdev;
  86. unsigned char mem[ AD9833_SIZE ];
  87. unsigned int delay;
  88. void (*write_reg) ( AD9833 *self, unsigned int reg_value);
  89. void (*init_device) ( AD9833 *self );
  90. void (*set_wave_freq)( AD9833 *self , unsigned long freqs_data);
  91. void (*set_wave_type)( AD9833 *self, enum ad9833_wavetype_t wave_type );
  92. void (*set_wave_phase)( AD9833 *self, unsigned int phase );
  93. void (*set_wave_para)( AD9833 *self, unsigned long freqs_data, unsigned int phase, enum ad9833_wavetype_t wave_type );
  94. };
  95. static void ad9833_set_wave_type( AD9833 *dev, enum ad9833_wavetype_t wave_type );
  96. static void ad9833_set_phase( AD9833 *dev, unsigned int phase_value );
  97. static void ad9833_set_freq( AD9833 *dev, unsigned long freq );
  98. static void ad9833_set_para( AD9833 *dev, unsigned long freqs_value, unsigned int phase_value, enum ad9833_wavetype_t wave_type );
  99. static void ad9833_init_device( AD9833 *dev ) ;
  100. static void ad9833_write_reg( AD9833 *dev, unsigned int reg_value );
  101. static long ad9833_ioctl(struct file *file, unsigned int cmd, unsigned long arg );
  102. AD9833 *ad9833;
  103. static int ad9833_major = AD9833_MAJOR; //主设备号
  104. module_param( ad9833_major, int, S_IRUGO );
  105. static const short ad9833_gpios[] = {
  106. AD9833_FSY_IO,
  107. AD9833_CLK_IO,
  108. AD9833_DAT_IO,
  109. };
  110. AD9833 *ad9833_dev_new(void)
  111. {
  112. AD9833 *dev = (AD9833*)kcalloc(1, sizeof(AD9833), GFP_ATOMIC);
  113. dev->hw.fsy = AD9833_FSY_IO;
  114. dev->hw.sdi = AD9833_DAT_IO;
  115. dev->hw.clk = AD9833_CLK_IO;
  116. dev->set_wave_para = &ad9833_set_para;
  117. dev->init_device = &ad9833_init_device;
  118. dev->write_reg = &ad9833_write_reg;
  119. dev->set_wave_freq = &ad9833_set_freq;
  120. dev->set_wave_phase = &ad9833_set_phase;
  121. dev->set_wave_type = &ad9833_set_wave_type;
  122. dev->init_device( dev );
  123. return dev;
  124. }
  125. static long ad9833_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  126. {
  127. printk(DRV_NAME "\tRecv cmd: %u\n", cmd);
  128. printk(DRV_NAME "\tRecv arg: %lu\n", arg);
  129. switch( cmd ) {
  130. case CMD_TYPE_SIN:
  131. ad9833->set_wave_freq(ad9833, 1500);
  132. ad9833->set_wave_type(ad9833, SIN);
  133. printk( DRV_NAME " set wave is sine wave! arg = %lu\n" , arg );
  134. break;
  135. case CMD_TYPE_TRI:
  136. ad9833->set_wave_freq(ad9833, 1500);
  137. ad9833->set_wave_type(ad9833, TRI);
  138. printk( DRV_NAME " set wave is tri wave! arg = %lu\n" , arg );
  139. break;
  140. case CMD_TYPE_SQE:
  141. ad9833->set_wave_freq(ad9833, 1500);
  142. ad9833->set_wave_type(ad9833, SQU);
  143. printk( DRV_NAME " set wave is sw wave! arg = %lu\n" , arg );
  144. break;
  145. }
  146. return 0;
  147. }
  148. //写入数据,模拟的3线SPI写入时序
  149. static void ad9833_write_reg( AD9833 *dev, unsigned int reg_value )
  150. {
  151. unsigned short i;
  152. io_clk(IO_HIGH); //需要修改为为beaglebone的设置方式
  153. io_fsy(IO_HIGH);
  154. ndelay(10);
  155. io_fsy(IO_LOW);
  156. for ( i = 0; i < 16; i++ ) {
  157. if ( reg_value & 0x8000 )
  158. io_dat(IO_HIGH);
  159. else
  160. io_dat(IO_LOW);
  161. ndelay(10);
  162. io_clk(IO_LOW);
  163. ndelay(10);
  164. reg_value = reg_value << 1;
  165. ndelay(10);
  166. io_clk(IO_HIGH);
  167. }
  168. io_fsy(IO_HIGH);
  169. io_dat(IO_HIGH);
  170. }
  171. //ad9833初始化
  172. static void ad9833_init_device( AD9833 *dev )
  173. {
  174. dev->write_reg( dev, AD9833_REG_RESET );
  175. dev->set_wave_para( dev,1500, 0 ,SIN );
  176. }
  177. //设置相位
  178. static void ad9833_set_para( AD9833 *dev, unsigned long freqs_value, unsigned int phase_value, enum ad9833_wavetype_t wave_type )
  179. {
  180. unsigned long dds_frequence_data;
  181. unsigned int dds_frequence_low;
  182. unsigned int dds_frequence_high;
  183. unsigned int phase_data;
  184. phase_data = phase_value | 0xC000;
  185. dds_frequence_data = freqs_value * 10;
  186. dds_frequence_low = dds_frequence_data & 0x3FFF;
  187. dds_frequence_low |= 0x4000;
  188. dds_frequence_data = dds_frequence_data >> 14;
  189. dds_frequence_high = dds_frequence_data & 0x3FFF;
  190. dds_frequence_high |= 0x4000;
  191. // reset device
  192. dev->write_reg( dev, 0x0110 );
  193. dev->write_reg( dev, 0x2100 );
  194. dev->write_reg( dev,dds_frequence_low );
  195. dev->write_reg( dev,dds_frequence_high );
  196. dev->write_reg( dev, phase_data );
  197. if( wave_type == TRI ) {
  198. dev->write_reg( dev, 0x2002 );
  199. }else if( wave_type == SQU ) {
  200. dev->write_reg( dev, 0x2028);
  201. }else {
  202. dev->write_reg( dev, 0x2000 );
  203. }
  204. }
  205. //设置频率,寄存器28位,分两次写入
  206. static void ad9833_set_freq( AD9833 *dev, unsigned long freq )
  207. {
  208. unsigned long dds_frequence_data;
  209. unsigned long dds_frequence_low;
  210. unsigned long dds_frequence_high;
  211. dds_frequence_data = freq;
  212. dds_frequence_low = dds_frequence_data & 0x3FFF;
  213. dds_frequence_low |= 0x4000;
  214. dds_frequence_data = dds_frequence_data >> 14;
  215. dds_frequence_high = dds_frequence_data & 0x3FFF;
  216. dds_frequence_high |= 0x4000;
  217. dev->write_reg( dev, dds_frequence_low );
  218. dev->write_reg( dev, dds_frequence_high );
  219. }
  220. static void
  221. ad9833_set_phase( AD9833 *dev, unsigned int phase_value )
  222. {
  223. unsigned int phase_temp;
  224. phase_temp = phase_value | 0xC000;
  225. dev->write_reg( dev, phase_temp );
  226. }
  227. //选择产生波的类型:TRI三角波;SQU方波;SIN正弦波
  228. static void ad9833_set_wave_type( AD9833 *dev, enum ad9833_wavetype_t wave_type )
  229. {
  230. if( wave_type == TRI ) {
  231. dev->write_reg( dev, 0x2002 );
  232. }else if( wave_type == SQU ) {
  233. dev->write_reg( dev, 0x2028);
  234. }else {
  235. dev->write_reg( dev, 0x2000 );
  236. }
  237. }
  238. static ssize_t ad9833_driver_read( struct file *filp, char __user *buffer, size_t size, loff_t *f_pos )
  239. {
  240. unsigned long p = *f_pos;
  241. unsigned int count = size;
  242. int ret = 0;
  243. if ( p >= AD9833_SIZE ) //p为读的位置相对稳健开头的偏移
  244. return 0;
  245. if ( count > AD9833_SIZE - p )
  246. count = AD9833_SIZE - p;
  247. if ( raw_copy_to_user( buffer, ad9833->mem + p, count) ) {
  248. //从内核空间拷贝数据到用户目录,buffer:目标地址: ad9833->mem + p;count:拷贝的字节数
  249. //copy_to_user()成功返回0;失败返回1.
  250. ret = -EFAULT;
  251. }else {
  252. *f_pos += count;
  253. ret = count;
  254. printk( DRV_NAME "\tread %u bytes from %lu\n", count, p );
  255. }
  256. return ret;
  257. }
  258. //从用户目录往内核空间写入数据
  259. static ssize_t ad9833_driver_write( struct file *filp, const char __user *buffer, size_t size, loff_t *f_pos )
  260. {
  261. unsigned long p = *f_pos;
  262. unsigned int count = size;
  263. int ret = 0;
  264. char * endp="str";
  265. if ( p >= AD9833_SIZE )
  266. return 0;
  267. if ( count > AD9833_SIZE - p )
  268. count = AD9833_SIZE - p;
  269. memset( ad9833->mem,0, AD9833_SIZE ); //用于对内存空间的初始化
  270. if ( raw_copy_from_user( ad9833->mem + p, buffer, count) ) {
  271. ret = -EFAULT;
  272. }else {
  273. *f_pos += count;
  274. ret = count;
  275. printk( DRV_NAME "\twrite %u bytes from %lu\n", count, p );
  276. printk( DRV_NAME "\tRecv: %s \n", ad9833->mem + p );
  277. printk( DRV_NAME "\tSet freq is: %ld \n", simple_strtol(ad9833->mem + p,&endp,0));
  278. //将一个字符串转换成unsigend long long型数据
  279. ad9833->set_wave_freq(ad9833, simple_strtol(ad9833->mem + p,&endp,0) );
  280. }
  281. return ret;
  282. }
  283. //用户进程利用在对设备文件进行诸如read/write操作的时候,系统调用通过设备文件的主设备号找
  284. //到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数,这是
  285. //Linux的设备驱动程序工作的基本原理。
  286. static struct file_operations ad9833_fops = {
  287. .owner = THIS_MODULE,
  288. .read = ad9833_driver_read,
  289. .write = ad9833_driver_write,
  290. .unlocked_ioctl = ad9833_ioctl,
  291. };
  292. static struct miscdevice ad9833_miscdev = {
  293. .name = DRV_NAME,
  294. .fops = &ad9833_fops,
  295. };
  296. dev_t devno;
  297. static int __init ad9833_dev_init( void ) //入口函数
  298. {
  299. int i,ret;
  300. int index_minor = 0; //次设备号
  301. int mk_major;
  302. /*
  303. * cdev alloc and release device code.
  304. * */
  305. //返回值:成功执行返回dev_t类型的设备编号
  306. //ad9833_major:主设备号
  307. devno = MKDEV( ad9833_major, index_minor ); //获取设备在设备表中的位置
  308. mk_major = MKDEV(ad9833_major, 0);
  309. if( ad9833_major ) {
  310. //主设备:devno:要分配的设备编号范围的初始值(次设备号常设为0);
  311. //1:连续编号范围.
  312. //DRV_NAME:编号相关联的设备名称.
  313. ret = register_chrdev_region( devno, 1, DRV_NAME ); //注册模块
  314. }else { //如果没有设备号,则动态申请一个设备号
  315. //alloc_chrdev_region() 函数用于动态申请设备编号范围
  316. ret = alloc_chrdev_region( &devno, 0, 1, DRV_NAME );
  317. ad9833_major = MAJOR(devno);
  318. }
  319. if( ret < 0 ) {
  320. printk(DRV_NAME "\t cdev alloc space failed.\n");
  321. return ret;
  322. }
  323. /*
  324. * AD9833 new device
  325. * */
  326. printk( DRV_NAME "\tApply memory for AD9833.\n" );
  327. ad9833 = ad9833_dev_new();
  328. if( !ad9833 ) {
  329. ret = -ENOMEM;
  330. printk(DRV_NAME "\tad9833 new device failed!\n" );
  331. goto fail_malloc;
  332. }
  333. /*
  334. * AD9833 init gpios.
  335. * */
  336. printk( DRV_NAME "\tInititial GPIO\n" );
  337. for ( i = 0; i < 3; i ++ ) {
  338. //ad9833_gpios[i]:则为你要申请的哪一个管脚;"AD9833 GPIO":为其取一个名字
  339. ret = gpio_request( ad9833_gpios[i], "AD9833 GPIO" ); //GPIO申请注册
  340. //返回值为0表示申请成功
  341. if( ret ) {
  342. printk("\t%s: request gpio %d for AD9833 failed, ret = %d\n", DRV_NAME,ad9833_gpios[i],ret);
  343. return ret;
  344. }else {
  345. printk("\t%s: request gpio %d for AD9833 set succussful, ret = %d\n", DRV_NAME,ad9833_gpios[i],ret);
  346. }
  347. gpio_direction_output( ad9833_gpios[i],1 );
  348. gpio_set_value( ad9833_gpios[i],0 );
  349. }
  350. /*
  351. * cdev init.
  352. * */
  353. cdev_init( &ad9833->cdev, &ad9833_fops );//静态内存定义初始化
  354. ad9833->cdev.owner = THIS_MODULE;
  355. ret = cdev_add( &ad9833->cdev, mk_major,1 );
  356. if( ret ) {
  357. printk( KERN_NOTICE "Error %d adding ad9833 %d", ret, 1 );
  358. return ret;
  359. }
  360. ret = misc_register( &ad9833_miscdev );
  361. printk( DRV_NAME "\tinitialized\n" );
  362. return 0;
  363. fail_malloc:
  364. unregister_chrdev_region( mk_major,1 );
  365. return ret;
  366. }
  367. static void __exit ad9833_dev_exit( void ) //出口函数
  368. {
  369. int i;
  370. for( i = 0; i < 3; i++) {
  371. gpio_free( ad9833_gpios[i] );
  372. }
  373. misc_deregister( &ad9833_miscdev );
  374. unregister_chrdev_region( devno,1 );
  375. }
  376. module_init( ad9833_dev_init );
  377. module_exit( ad9833_dev_exit );
  378. MODULE_AUTHOR( DRV_AUTHOR );
  379. MODULE_DESCRIPTION(DRV_DESC);
  380. MODULE_LICENSE("GPL");

编译模块的Makefile:

  1. #Makefile for ad9833.c
  2. ARCH=arm
  3. CROSS_COMPILE=arm-linux-gnueabihf-
  4. ifneq ($(KERNELRELEASE),)
  5. obj-m := ad9833.o
  6. else
  7. KERNELDIR ?= /home/ws/4.14/linux-4.14/
  8. PWD := $(shell pwd)
  9. default:
  10. make -C $(KERNELDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
  11. clean:
  12. $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
  13. rm -rf modules.order
  14. endif

测试用的源码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/ioctl.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <string.h>
  9. #define AD9833_MAGIC 'k'
  10. #define CMD_TYPE_SIN _IO( AD9833_MAGIC, 0)
  11. #define CMD_TYPE_TRI _IO( AD9833_MAGIC, 1)
  12. #define CMD_TYPE_SQE _IO( AD9833_MAGIC, 2)
  13. const char dev_path[]="/dev/AD9833-ADI";
  14. int main(int argc , char *argv[])
  15. {
  16. int fd = -1, i = 0;
  17. printf("ad9833 test program run....\n");
  18. fd = open(dev_path, O_RDWR|O_NDELAY); // 打开设备
  19. if (fd < 0) {
  20. printf("Can't open /dev/AD9833-ADI\n");
  21. return -1;
  22. }
  23. printf("open device.\n");
  24. if( strcmp(argv[1],"1") == 0 ) {
  25. ioctl(fd, CMD_TYPE_SIN, 5);
  26. printf("argc = %d,sine wave = %s \n", CMD_TYPE_SIN, argv[1]);
  27. }else if( strcmp(argv[1],"2") == 0 ) {
  28. ioctl(fd, CMD_TYPE_TRI, 1);
  29. printf("argc = %d,tri wave = %s \n", CMD_TYPE_TRI,argv[1]);
  30. }else{
  31. ioctl(fd, CMD_TYPE_SQE, 1);
  32. printf("argc = %d,sqe wave = %s \n", CMD_TYPE_SQE, argv[1]);
  33. }
  34. write(fd, argv[2], strlen(argv[2]));
  35. printf("argc = %d\n", argc);
  36. close(fd);
  37. return 0;
  38. }

编译测试代码的Makefile:

  1. CROSS=arm-linux-gnueabihf-
  2. all: ad9833_test
  3. ad9833_test: ad9833_test.c
  4. $(CROSS)gcc -o ad9833_test.o ad9833_test.c -static
  5. clean:
  6. @rm -rf ad9833_test *.o

在调试原作者源码时遇到的问题:

1、 error: implicit declaration of function ‘copy_to_user’; did you mean‘raw_copy_to_user’? [-Werror=implicit-function-declaration]
  if ( copy_to_user( buffer, ad9833->mem + p, count) ) {
       ^~~~~~~~~~~~
       raw_copy_to_user
原因:linux4.14的内核取消了copy_to_user,改为了raw_copy_to_user

2、/home/ws/beaglebone_ad9833/driver/ad9833.c:149:9: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
 AD9833 *ad9833_dev_new()
         ^~~~~~~~~~~~~~
原因:函数中传参为空的时候使用void,修改源码*ad9833_dev_new(void)


3、/home/ws/beaglebone_ad9833/driver/ad9833.c:310:25: warning: passing argument 1 of ‘raw_copy_to_user’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
  if ( raw_copy_to_user( buffer, ad9833->mem + p, count) ) {

原因:传参的第一个函数将不是const定义
修改:
static ssize_t ad9833_driver_read( struct file *filp, const char __user *buffer, size_t size, loff_t *f_pos )

static ssize_t ad9833_driver_read( struct file *filp, char __user *buffer, size_t size, loff_t *f_pos )

4、/home/ws/beaglebone_ad9833/driver/ad9833.c:345:74: error: passing argument 2 of ‘simple_strtol’ from incompatible pointer type [-Werror=incompatible-pointer-types]
   printk( DRV_NAME "\tSet freq is: %d \n", simple_strtol(ad9833->mem + p,"str",0));
In file included from ./include/linux/list.h:9:0,
                 from ./include/linux/module.h:9,
                 from /home/ws/beaglebone_ad9833/driver/ad9833.c:21:
./include/linux/kernel.h:438:13: note: expected ‘char **’ but argument is of type ‘char *’
 extern long simple_strtol(const char *,char **,unsigned int);
原因:
        printk( DRV_NAME "\tSet freq is: %d \n", simple_strtol(ad9833->mem + p,"str",0));
        ad9833->set_wave_freq(ad9833, simple_strtol(ad9833->mem + p,"str",0) );

修改为:
        char * endp="str";

        printk( DRV_NAME "\tSet freq is: %d \n", simple_strtol(ad9833->mem + p,&endp,0));
        ad9833->set_wave_freq(ad9833, simple_strtol(ad9833->mem + p,&endp,0) );


5、/home/ws/beaglebone_ad9833/driver/ad9833.c:363:15: error: variable ‘ad9833_miscdev’ has initializer but incomplete type
 static struct miscdevice ad9833_miscdev  = {
原因:缺少头文件

#include <linux/miscdevice.h>


6、/home/ws/beaglebone_ad9833/driver/ad9833.c:362:25: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
   .unlocked_ioctl   =   ad9833_ioctl,
                         ^~~~~~~~~~~~
原因:内核版本变迁,现在ioctl函数的返回值应该定义为long型。
修改为:
static long ad9833_ioctl(struct file  *file, unsigned int cmd, unsigned long arg)

测试步骤说明:

  1. 将ad9833.c的源码和Makefile拷贝到一个文件夹下,在PC端的终端进入文件夹下,执行make命令,则可以编译成模块,其中Makefile中需要修改依赖的linux编译过得内核路径,也许交叉编译链用的也不一样,也需要修改。
  2. 将编译过的整个文件夹通过TFTP传输到与其相连的Beaglebone中。
  3. 登录到beaglebone上,使用insmod命令挂载模块,lsmod查看挂载状态,rmmod卸载模块。
  4. 接着回到PC端复制测试文件的源码和Makefile,放在一个文件夹下,将文件传输到Beaglebone中,通过串口(minicom)登录到Beaglebone上。在Beaglebone的该文件夹下执行make命令,生成可执行文件。
  5. root权限执行命令。
    sudo ./ad9833 1 2000

    第一个参数表示选择正弦波,第二个参数表示设置频率。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/540059
推荐阅读
相关标签
  

闽ICP备14008679号