嵌入式开发者社区

标题: DSP与ARM通信的奇怪问题 [打印本页]

作者: wwfdzh2012    时间: 2017-4-16 13:54
标题: DSP与ARM通信的奇怪问题
本帖最后由 wwfdzh2012 于 2017-4-17 12:09 编辑
  J- H! D% M7 }0 L8 Y
9 S1 d2 k! P9 z3 {1 w
项目要求DSP不跑操作系统,arm核上linux3.3,在做双核通信的linux设备驱动时候遇到了一个诡异的问题,只要DSP通过CHIPSIG_INT0触发ARM中断,ARM中的linux内核的其他很多驱动都停止了工作,连自己的led控制驱动都失去了响应,流水灯也失去了闪烁,LCD显示也停止了刷新,但是运行GUI还是可以显示界面,就是界面不能刷新,触摸屏也不懂了。好像是其他驱动都阻塞了!!!!
我的linux设备驱动是这样实现的:使用Tasklet实现软中断,只要DSP的数据一准备好就通过CHIPSIG_INT0触发ARM中断,这时候驱动的tasklet顶半部会立刻响应中断去读取数据,然后调度tasklet的底半部,这样的流程一般是没问题才对,但是现象就是只要顶半部被触发了,其他驱动就异常了,linux也没有任何提示,而且无法恢复,触发重启内核,但是唯独这个驱动完全正常运行,数据照样读取也不丢帧,还有一个现象是DSP触发一次CHIPSIG_INT0中断,ARM核会响应两次,也就是顶半部会触发两次调用!!我的驱动实现如下,麻烦帮忙看下。
  1. //头文件省略
    , s$ q6 N" o0 E& d8 B4 ^& w3 w! W

  2. * s5 b1 Y" D. r8 C/ ?
  3. //引入其他模块函数和变量
    8 I5 |: P5 f' g
  4. extern Ping_Pong_Buffer res_buff;
    : i4 q0 d, E: J$ B) y
  5. ; m8 q' |, |5 R1 I8 M2 |
  6. extern char k_linkQueue_create(linkQueue *queue, unsigned int dataType, unsigned int blockNumber, unsigned int blockSize);//创建链队列
    0 e2 o8 C! m$ S, G' c" m4 K
  7. extern void k_linkQueue_release(linkQueue *queue);//释放链队列$ M% s/ s: C* b
  8. extern unsigned int k_linkQueue_insertData(linkQueue *queue, void *data, int force);//链队列插入数据
    ) c: O6 w- Y  l8 R
  9. extern unsigned int k_linkQueue_getData(linkQueue *queue, void *r_buff);//获取队列的数据
    3 N* O) {% a( j2 v) l( }7 k, a
  10. 3 B- w, H6 t8 ]4 `& l9 D( u3 I" `
  11. extern void SHM_ARM_Init(unsigned char* const mem_base);//共享内存初始化
    7 Y: O0 n8 ?; Y6 \
  12. 2 c& k/ ~6 B+ p/ c3 m  W/ v+ B
  13. static int read_quest = 0;//如果有读取数据请求且链队列无数据可读,则置1# k7 [1 e! a6 F
  14. //设置主从设备号$ G, D: J! \# p, O  q- t; \1 n$ W
  15. #define PROTOCOL_MAJOR      1
    5 J% Q' ]+ C8 V4 J, f  j5 J
  16. #define PROTOCOL_MINOR      0
    . y8 J; q' p7 \

  17. 5 T( R% M7 g0 V& x& m

  18. 6 n/ w% h! h4 G' t9 X% k

  19. ! X* O' j( H5 e" d7 \3 q/ K
  20. //定义设备驱动的名字或设备节点的名字3 T  s. _7 Z7 R2 a
  21. #define     DEVICE_NAME         "protocol_driver"; g+ w7 ~0 s3 c" N1 ?, P5 N
  22. / G8 E- O! }; T

  23. 3 k" r$ R* _# o6 o4 z6 w4 |8 [3 T
  24. //定义全局的循环队列作为数据缓冲区  X# Z3 U7 A" s6 q( P' D
  25. k_linkQueue queue;' E9 t3 ?. T$ t& o  Y2 v8 |0 E
  26. 4 l; d+ t' r) s3 K' _; r1 m* q& f
  27. //寄存器地址映射全局变量
    & {$ C* _8 U* n. D# q& `
  28. unsigned int *R_CHIPSIG = NULL;//CHIPSIG寄存器8 S. R- z% ^1 D6 O4 t0 R
  29. unsigned int *R_CHIPSIG_CLR = NULL;//CHIPSIG_CLR寄存器
      d( V+ T$ ]' g3 z' U9 j

  30. 5 G- |5 `- N6 X. F; B
  31. //物理内存映射全局变量
    8 ]! |5 s$ N$ H1 ^8 K, G& g3 [
  32. volatile void *mem_base = NULL;
    1 F. g$ o, k# N! O/ N& o, p! A
  33. volatile unsigned char *cur_buf_ptr = NULL;8 S5 {9 H7 H3 n+ w1 z4 g0 F
  34. volatile unsigned char *data_ready_ptr = NULL;6 x& R9 W6 H; o
  35. , u: t5 l) f3 D* g& ?* Z
  36. + \* P0 M0 |/ i* J, _4 e, @

  37. 7 o3 W' B: `( ^( C" e3 v5 b
  38. //定义读数据等待队列头,IO阻塞  E& h- H0 B: A- U- H9 H( {/ }9 d
  39. DECLARE_WAIT_QUEUE_HEAD(wait_queue_head);
    / t" y! I0 f5 R( O: d8 u( o

  40. 9 Z' ~( b5 ]* w
  41. //定义原子变量
    / V1 E; J5 }' |+ o2 @
  42. static atomic_t dev_available = ATOMIC_INIT(1);//原子变量的值为1,即只能一个进程打开此设备: W; w/ p/ t+ n

  43. % d  y" _) V' H* h8 z1 Y
  44. ) m# B1 ]( b% @& \. U2 ?0 N' |
  45. //定义设备类+ L$ |  d' H* ?" b) d- x! [
  46. static struct class *protocol_class;1 g/ w8 s4 {$ o8 O+ o# B' Q- ~: r
  47. struct cdev *protocol_cdev;
    ) J( H& o/ P% X# |4 x, x3 T
  48. dev_t protocol_dev_no;+ Q0 t4 i' D8 Z! U, a# V
  49. ) ^! I8 E, h% Q/ k3 ?0 |
  50. /*定义tasklet和声明底半部函数并关联*/
    ( @9 o, y. @. A. U" Y: u( d* @8 Q
  51. void read_data_tasklet(unsigned long);/ R& R! L& B' x, Q0 H4 m2 \
  52. : U2 ?" E! z! C7 a6 S
  53. DECLARE_TASKLET(CHIPINT0_tasklet,read_data,0);" i0 Y' g/ i  G$ T! F2 V/ H5 d/ [
  54. //将CHIPINT0_tasklet与read_data绑定,传入参数0
    # y1 c$ E' o7 `+ c% o

  55. ) [' o( g( X0 L5 A
  56. /*中断处理底半部, 拷贝内存*/
    5 F1 K3 B7 f9 z% j# t1 i
  57. void read_data(unsigned long a)
    ) v) x/ y7 T& O9 M
  58. {# `/ X9 C* v, j3 g8 L: g( C
  59.     if(read_quest == 1)//如果进程调用了此驱动的read函数且链队列没有数据可读,read_quest将会被赋值为13 g2 K9 \4 q/ ^
  60.     {
      @) ^1 a( k! v( E
  61.         read_quest = 0;
    " o( G. b" c' v* J  k
  62.         wake_up_interruptible(&wait_queue_head);//唤醒读等待队列* [& M( o  D  h$ V2 Q. r
  63.     }9 r; v' ?; F  ~0 J

  64. & |! B0 y8 ?5 R: [0 y: f1 A6 v
  65. }$ i% k( A5 n. @5 |, A+ O( w
  66. ! N- _* H7 S+ K/ a7 q( K
  67. /*中断处理顶半部*/; a' }) R; }* E' \
  68. irqreturn_t CHIPINT0_interrupt(int irq,void *dev_id)" R/ D0 ?0 n, s3 u' |9 b8 ]) |
  69. {. E! D' N4 g" p3 e
  70.     //只要一触发进入这个程序,其他驱动会出问题,即使这个程序什么都不做也会这样
    ( m% e" @+ g! \
  71.     volatile Buffer_Type *next_read;8 ?1 e$ \9 v0 N5 q: X
  72.     //如果DSP数据已经ready
    & o/ M" A: F$ z3 Q, ]
  73.     if(*(res_buff.cur_buffer->data_ready) == 1)& D& B6 N; g8 k) }5 d/ y0 k0 ]
  74.     {
    - R# l7 {4 o/ A* V, J( e: g( H
  75.         if(*(res_buff.bufferID_ptr) == BUFF_ID_PING)//切换读buffer
    ; K- G" `6 G: K8 D; U$ n
  76.         {3 h5 h8 y$ [1 s& J7 h7 z
  77.             next_read = &res_buff.pong_buffer;//下一次中断读pong buffer
    # A2 B$ k5 ?+ r6 e+ m% t
  78.             //printk(KERN_ALERT"read ping\n");4 L- F# {( g* I9 F
  79.         }& o- U# g) O4 [, x$ ?
  80.         else
    * k/ ?2 c8 b2 B# N: m$ v
  81.         {/ |4 O) W8 d/ w
  82.             next_read = &res_buff.ping_buffer;//下一次中断读ping buffer5 g8 r0 Z, v, t$ L5 P# e  h6 E& N
  83.             //printk(KERN_ALERT"read pong\n");/ P2 O! D' s4 i2 G3 i' h
  84.         }' K4 x% _* W- R. q
  85.         *(res_buff.bufferID_ptr) ^= BUFF_ID_PING;//切换DSP写另一个buffer
    . ~* @7 q1 i( k: v5 Z9 p3 s
  86.         //将数据插入链队列8 T+ n  C  D8 z. \
  87.         k_linkQueue_insertData(&queue, res_buff.cur_buffer->buf_ptr, 0);) u. |8 a/ w& D. z' B+ W% U
  88.         //标识位都重置$ ~+ W  y" u2 k8 m
  89.         *(res_buff.cur_buffer->data_ready) = 0;+ s# G$ S3 ?/ ?4 y4 J8 a% L
  90.         *(res_buff.cur_buffer->data_size) = 0;/ G, {8 Y6 ~7 b% B( z1 l- A
  91.         res_buff.cur_buffer = next_read;
    7 h/ T4 R: ?( j6 W# l& |* N. a
  92.     }
    * v% p9 d1 m: q
  93.     //清楚中断标识' t% Q& w0 d" e- U( k, Z7 C& L6 C
  94.     *R_CHIPSIG_CLR = 1 << 0;//clear chipint0 status
    ( d# R* o" x& x, q: u# ^' ^" s3 {
  95.     tasklet_schedule(&CHIPINT0_tasklet);//调度底半部     ) [: Z' i4 {7 o
  96. " B* \# ?- z: ~; u1 ~
  97. + L+ Z5 `  c4 q
  98.     return IRQ_HANDLED;. g4 W7 V0 J4 J) n0 g9 {6 ?  T
  99. 5 g; A- I' g* j2 Y, {6 S0 L+ {
  100. }
    + Y6 C) K* B$ w3 n, S! n

  101. ' E7 L$ K( S' D' p4 f3 c( U
  102. //文件打开函数
    ; N2 V. s8 y/ z
  103. static int protocol_open(struct inode *inode, struct file *file)
    1 ~8 \1 x# L$ g2 R
  104. {& L% D: e0 N8 w) V
  105.     int result = 0;4 l6 ~' \; ]! q, X/ N# U- [
  106.     if(!atomic_dec_and_test(&dev_available))! U! D& J- U) d. z
  107.     {
    - F/ K# L- v6 l" o6 b
  108.         atomic_inc(&dev_available);
    1 h: o+ d' D' E1 m2 [( v
  109.         return -EBUSY;//设备已经被打开. {+ Q, D2 {; D" n( }
  110.     }
    # c# n# K( z- A5 l
  111.     printk (KERN_ALERT "\nprotrol driver open\n");
    ' G. R4 j2 ]1 m
  112.     return 0;
    - d) n3 ^2 f9 V+ ?. a
  113. }
    - ]8 ?) m2 c6 i, g

  114. : y2 r$ I9 |/ Z; y' W3 Q& b% t  L
  115. //文件释放函数
    $ q: ]2 w% l0 p, J, k# X! d. X; Q
  116. static int protocol_release(struct inode *inode, struct file *filp)
      X1 L% u' S  q4 A: l% ^, @$ k- l& i
  117. {/ j& i) s8 [. X1 n2 c. q, J
  118.     atomic_inc(&dev_available);//释放设备,原子变量加1
    % n7 a( i4 n) H, J/ B; U0 S
  119.     printk (KERN_ALERT "device released\n");
    . p: x/ W/ {2 F
  120.     return 0;
    9 u( p& Z. q; b: t4 G/ `
  121. }
    2 I2 E/ v$ L$ [
  122. + g; B# V; E# z5 j
  123. //文件读函数
    8 }# K  I6 C9 K0 |# U
  124. static int protocol_read(struct file *filp, char *dst, size_t size, loff_t*offset)
    - U. Q8 L) x8 `$ j6 ~
  125. {
    3 k  I- Y  O3 p) j. S. T
  126.     int ret = 0;  K* S0 e/ x  c4 G( c
  127.     //定义等待队列( S+ U' n) u" [5 `: c
  128.     DECLARE_WAITQUEUE(wait_queue, current);//定义等待队列
    7 P9 H& M, k1 e) ?$ n
  129.     add_wait_queue(&wait_queue_head, &wait_queue);//添加等待队列: P( |* P4 r6 X2 }) ^8 j8 @
  130.     if(queue.remainNumber == queue.blockNumber)//当前buffer没数据8 \. N7 U- h& [* ]4 H" ^( O/ b
  131.     {7 k  s& n: \; w6 j  a9 t% N
  132.         //printk(KERN_ALERT"\nbuffer no data\n");
    # r) u. E1 O$ I8 w
  133.         //如果是非阻塞方式读取,则直接跳出
    . Y! }" ^3 D1 w$ S3 U  ^
  134.         if(filp->f_flags & O_NONBLOCK)
      l$ `6 T2 ~* k) u7 i
  135.         {
    - T8 x8 w& Z/ N5 B
  136.             ret = -EAGAIN;
    ; P) S$ B' W' J% C+ Q- T7 z5 l
  137.             goto out;
    2 Q# r0 z- ?3 e6 ]' g
  138.         }3 R% A- Q$ e6 j7 J, f. E- l
  139.         //阻塞当前进程,放弃cpu资源
    + z& S  o- q. I& h1 _
  140.         read_quest = 1;# U  U: ]  y; i5 Z8 \& }
  141.         __set_current_state(TASK_INTERRUPTIBLE);//改变进程状态为睡眠
    3 ?# j  ^% c$ T0 v
  142.         schedule();//调度其他进程运行
    9 {# I7 k4 a. P- k. P" M. B
  143.         if(signal_pending(current))# P+ @# [! a5 m5 \+ i
  144.         {/ e' a, J  k( l) u- f) r( M1 L/ a( [
  145.             //如果是因为信号被唤醒,则返回到系统调用之前的地方. n% b0 M4 L' ]4 Y
  146.             ret = -ERESTARTSYS;
    9 ~8 S( ^4 J; U" v
  147.             goto out;) `4 `/ Z" r% ?& E$ V0 Q
  148.         }
    6 I4 F) v9 e: J6 w% n) [8 }
  149.     }
    3 `/ Z3 l& a9 @% F- |
  150.     //将数据拷贝到用户空间
    $ C  N- {6 r6 i  h9 d$ h; v  `
  151.     ret = k_linkQueue_getData(&queue, dst);5 v5 s6 a3 w7 f5 g; u: L% }' k  A
  152.     if(ret == 0)
    ( K/ ]5 m. |) P# k
  153.     {
    ( d2 c& t. M1 [3 M
  154.         //printk(KERN_ALERT"\ncopy data to user space failed :%d\n", ret);
    1 N" G+ d$ w* C$ a) o: \) O- c# g( z
  155.     }; [  O4 h1 X/ e3 j+ I
  156. out:$ F9 ~! T  }6 k2 {8 h( b
  157.     remove_wait_queue(&wait_queue_head, &wait_queue);//移除等待队列0 t" ]9 R4 o3 n) \! w
  158.     set_current_state(TASK_RUNNING);//设置当前进程为运行状态
    ; Y8 }. d: o9 h6 \
  159.     return ret;1 X3 U- b7 k9 l7 j4 F
  160. }- D7 h9 Z4 D3 x2 I# l

  161. " y  O. f; Z& w$ H, U; {

  162. ! L! L) A0 Z+ j$ }0 y
  163. static long protocol_ioctl(struct file *file, unsigned int cmd, unsigned long value)
    4 v  y7 L! x5 a2 L/ J
  164. {' W; V: Y6 q8 \* c. \' l4 ~9 T
  165.     return 0;
    " d; ?) h8 W+ h. F$ g; @
  166. }
    # a1 j* s+ n1 b$ G5 z. i
  167. /*驱动文件操作结构体,file_operations结构体中的成员函数会在应用程序进行
    ; \8 |! k( t2 W
  168. open()、release()、ioctl()协同调用时被调用*/) c( e/ [( [) K5 n/ @& I3 Q
  169. static const struct file_operations protocol_fops =# G% S* i7 y, q0 i2 J+ W
  170. {7 y0 o) V6 A0 a" F; }
  171.   .owner    = THIS_MODULE,
    3 P- W6 p( j6 J; L0 u, ]  i* [- z
  172.   .open     = protocol_open,
    # E4 @7 g7 B$ p& e, x8 k6 g
  173.   .release  = protocol_release,
    / l9 L! R- R- b& R, T2 b
  174.   .read     = protocol_read," \$ p, V% i5 T& d; S) z
  175. //  .write  = protocol_write,6 n; `. x3 w- L8 `+ [7 F' O
  176.   .unlocked_ioctl=protocol_ioctl,9 S7 B; V* R! ^1 F
  177. };/ }- q& D, d. b2 y% ?% t; P& {

  178. - U/ J$ k1 k& Y8 q( K) R' G0 x
  179. /*设备驱动模块加载函数*/4 X) l, O6 x; B' Z7 o1 N
  180. int __init protocol_init(void)7 o+ p" Y& {9 {9 Y8 h4 M
  181. {  y( Y* @0 r& Q
  182.     int ret = 0;
    + _% C! \, L6 Z5 B/ S" B0 \( {, Y
  183.     int result = 0;
    ( X0 U: T$ k( ^7 E
  184.     //申请注册设备号(动态)8 R/ m4 M* ]( S- [
  185.     ret=alloc_chrdev_region(&protocol_dev_no, PROTOCOL_MINOR, 1, DEVICE_NAME); - u$ X, p3 z  c2 v! ^+ R& P
  186.     if(ret < 0)" O* c$ V1 {1 C& L5 x
  187.     {
    ) l" R3 M% E5 D
  188.             printk(KERN_EMERG "alloc_chrdev_region failed\n");
    5 ?& r: S+ h/ b" C
  189.             return 0;3 Z3 g) g) q6 g2 H3 v$ o' K, ]  `1 Y
  190.     }9 r; j3 \( Y' b; w# y1 \9 g
  191.     //分配cdev
    % Z2 N# a9 s* F# i* b0 x
  192.     protocol_cdev = cdev_alloc();
    + `$ g( i3 B/ x& M5 O. B/ h
  193.     if(protocol_cdev == NULL)9 b+ N. o2 A. r# [4 p9 H4 w
  194.     {
    # G0 \) E' r, Q, F/ K2 z- G# Q/ k
  195.             printk(KERN_EMERG "Cannot alloc cdev\n");- F% A/ i& ?& P5 b
  196.             return 0;  o( T3 {2 B8 T" G) F* \
  197.     }% t+ |/ u, X1 W. h3 T
  198.     //初始化cdev' R2 o7 }  Z" Z) o) D/ H
  199.     cdev_init(protocol_cdev,&protocol_fops);8 A+ D" t# m" x- F8 J& @3 L
  200.     protocol_cdev->owner=THIS_MODULE;- h  u* @% g4 e$ i
  201.     //注册cdev
    + F; R5 ]0 D% D: ^* k. F5 l3 V' L
  202.     cdev_add(protocol_cdev, protocol_dev_no, 1);
    ! R0 K9 x9 L, n+ w( R. S
  203.     //创建一个类
    4 p) u2 C# n% j
  204.     protocol_class = class_create(THIS_MODULE, DEVICE_NAME);% c& ^) K7 b9 f+ o" |
  205.     //创建设备节点3 L. I$ O3 h" m3 U) j8 D
  206.     device_create(protocol_class, NULL, protocol_dev_no, NULL, DEVICE_NAME);7 _3 g, [$ n/ S0 d( w# U6 r. p7 \
  207.    
    ; C  m, S. P" p8 s1 I& v( ^  x8 W
  208.    
    ! o* N& [5 Z0 H7 d; G6 c
  209.     //申请链式循环队列作为缓冲区DSP数据帧的缓冲区
    3 Q5 s; ~3 c9 K5 g! g. W
  210.     k_linkQueue_create(&queue, sizeof(double), 1000, DATA_BLOCK_SIZE);//申请1000个blocksize的队列空间作为帧缓冲区
    - E/ a* \9 [* `) `- f7 g

  211.   e  B7 c" _$ m6 V7 J- G# z
  212. //映射ARM的核间通讯寄存器
    # ~& \( _7 }7 k6 y, |  n
  213.     R_CHIPSIG = ioremap(SOC_SYSCFG_0_REGS + SYSCFG0_CHIPSIG, 4);
    ' N$ U( A: d# F1 N4 ^
  214.     R_CHIPSIG_CLR = ioremap(SOC_SYSCFG_0_REGS + SYSCFG0_CHIPSIG_CLR, 4);
      u, f6 b/ D2 T# `
  215.     //将物理地址映射到内核空间4 T+ o$ t, F4 C3 R. X& L8 R, Y
  216.     mem_base = ioremap(SHARED_BUFFER_ADDR, SHARED_BUFFER_SIZE);
    5 e; k4 w* h, E7 i) }5 o' J  l
  217.     //共享内存初始化
    ' [+ _7 }+ J6 N" T+ q% v1 f
  218.     SHM_ARM_Init((unsigned char *)mem_base);+ m& b) @( ~% F! [. j8 j2 _' v
  219.     /*申请中断*/& Y8 F7 Z% {' J% {/ E

  220. , k/ m! E( ]* j" q
  221.     result = request_irq(IRQ_DA8XX_CHIPINT0, CHIPINT0_interrupt,IRQF_SHARED,"DSP Signal",&protocol_cdev);1 R" ?( x+ f7 \! D/ _
  222.     if(result != 0)! }. ~4 O# {; t" M# P! I% ]
  223.     {* N4 C+ \" w0 k/ |7 @, j: R
  224.         if(result == -EINVAL)3 p0 o; U6 U" c( P3 o0 v  h
  225.         {5 ^3 f: D0 s- E! I6 l
  226.             printk(KERN_ALERT "irq request err:-EINVAL\n");: w( f/ ^$ e% U
  227.         }
    1 _1 U8 x& w: f8 D8 T3 P' k
  228.         else if(result == -EBUSY)3 a- \# c) H1 U2 y/ F0 O9 W' k
  229.         {
    + \) }7 {9 J' Q$ h% a1 p
  230.             printk(KERN_ALERT "irq request err:--EBUSY\n");: w7 d- m( m2 r: U! @4 A
  231.         }
    8 I; Z7 ^8 R3 _
  232.         else
    0 [- n  e$ ]* T+ T6 _
  233.         {. |! x0 ^3 s$ H: q! z
  234.             printk(KERN_ALERT "irq request err: unknown\n");1 h( |+ D3 t1 ^$ ~
  235.         }8 N3 |: G! K# F& j- Q" s3 z
  236.         return result;4 Z, M7 P) m) _: X. L! k' _
  237.     }
    # G( z8 X- l3 v, z7 w* [4 {
  238.     return 0;
    : }5 h3 d9 c2 I9 {% }6 X+ t# I
  239. }1 \% M8 b2 X+ X

  240. 8 a, n1 V* x4 V" n4 A- m; z
  241. /*设备驱动模块卸载函数*/1 h& \" v3 }  \7 l8 V1 k
  242. void __exit protocol_exit(void)/ Z0 _# C8 s1 N6 u: `
  243. {2 U9 [# \' a& B' w
  244.         /*释放中断*/. ?/ x. B! ?  \: I. H8 A( i
  245.     free_irq(IRQ_DA8XX_CHIPINT0, NULL);8 U( A& s0 r$ Q; q! Z% L2 ?; W
  246.     //释放帧缓冲的内存3 e+ `6 S8 z6 b; M2 ^) n6 v
  247.     k_linkQueue_release(&queue);
    $ O% D; |/ h5 }( e9 x
  248.     //释放寄存器映射
    0 D7 n7 T6 m$ e
  249.     iounmap(R_CHIPSIG);0 `% `6 y2 a( c, c2 l) z9 m0 }
  250.     iounmap(R_CHIPSIG_CLR);2 A5 ^7 j# g2 b& }  H
  251.     cdev_del(protocol_cdev);                            //删除cdev
    1 w) i0 q6 S2 |* ~5 O$ K' K
  252.     unregister_chrdev_region(protocol_dev_no, 1);   //注销设备号
    , H, z/ ~% D5 k+ i" _7 Z
  253.     device_destroy(protocol_class, protocol_dev_no);            //销毁设备节点5 D( H8 L8 j/ @
  254.     class_destroy(protocol_class);                      //销毁设备类
    9 H! Y; W+ H4 A
  255.     printk(KERN_ALERT "exit success\n");9 @; q/ E+ t2 R% X; ?* E# V! }# U/ i3 e

  256. 1 n% x! U1 ^: H6 r
  257. }& Q+ b$ n8 x7 B" K) k. V
  258. //驱动其他部分省略
复制代码
; p& `, Z8 ~+ X; s3 L# I

+ S+ J& s- `+ A# t; }3 y( Z
作者: wwfdzh2012    时间: 2017-4-16 13:54
没有人遇到这个问题吗
作者: human    时间: 2017-4-16 18:19
可以参考一下TL_IPC双核通信例程。
$ N8 \/ v0 A3 @+ y& ^2 u0 G) XTL_IPC是广州创龙独立开发的一种双核通讯协议。ARM核上运行Linux程序,DSP核上运行裸机或SYS/BIOS程序。基于TL_IPC的开发是指在两个处理间采用以直接触发中断进行异步事件通知,以直接读写共享内存进行数据交换,并结合创龙提供的c674x_irq_events内核模块(用于ARM端程序捕获由DSP触发的中断)实现双核通信的一种双核开发方式。
作者: wwfdzh2012    时间: 2017-4-16 21:23
human 发表于 2017-4-16 18:196 x# A" P  T+ s2 j
可以参考一下TL_IPC双核通信例程。
. B8 U, f2 K& y8 D/ F* T. q0 PTL_IPC是广州创龙独立开发的一种双核通讯协议。ARM核上运行Linux程序,D ...
  z+ m) ~2 p* h7 f9 b: H
@human 您好,请问有c674x_irq_events模块的源码吗,光盘没有附带,只提供模块,这个模块还不能满足我的需求,但是我想参考他的中断实现。谢谢
作者: wwfdzh2012    时间: 2017-4-17 10:12
human 发表于 2017-4-16 18:19
6 r, J8 U7 x% I" o9 j' b可以参考一下TL_IPC双核通信例程。+ O3 d6 J0 F- [/ ?
TL_IPC是广州创龙独立开发的一种双核通讯协议。ARM核上运行Linux程序,D ...
: {1 N5 o9 S7 R6 `5 T( P
请问有c674x_irq_events模块的源码吗
作者: wwfdzh2012    时间: 2017-4-17 12:08
问题已解决,驱动没有任何问题,而是DSP端调用了DelayTimerSetup()这个函数导致定时器的状态被改变,从而导致arm端的定时器驱动无法正常工作,而依赖此定时器的其他驱动也就无法正常工作了,这也是双核的弊端吧,两个核共用一些资源,如果一个核在没有告知其他核的情况下改变了一些资源的寄存器就会导致出问题。
作者: wwfdzh2012    时间: 2017-4-17 13:07
至于DSP触发ARM中断两次的问题,这是由于linux的中断机制导致的,可以参考https://e2e.ti.com/support/embedded/linux/f/354/t/2345103 g" _8 O' _' j% Q
解决方法:在dsp端触发后立即将clr标志位置1清除中断线,即可解决触发两次的问题
作者: human    时间: 2017-4-17 15:41
加陈工的QQ2942385389获取资料




欢迎光临 嵌入式开发者社区 (https://www.51ele.net/) Powered by Discuz! X3.4