DSP与ARM通信的奇怪问题 - OMAP-L138 - 嵌入式开发者社区 - 51ele.net
设为首页收藏本站

嵌入式开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 6003|回复: 7
打印 上一主题 下一主题

[已解决] DSP与ARM通信的奇怪问题

[复制链接]

5

主题

24

帖子

95

积分

注册会员

Rank: 2

积分
95
跳转到指定楼层
楼主
发表于 2017-4-16 13:54:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 wwfdzh2012 于 2017-4-17 12:09 编辑 $ M5 [7 l1 z1 J4 g4 {4 A7 {

( z. P9 F7 g9 K% L8 z4 k
项目要求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. //头文件省略0 S3 v3 w2 {( U& E- t
  2. 7 Q3 r1 M4 V% J, Y4 \* r( f
  3. //引入其他模块函数和变量8 j+ F: ?( ~) [6 t2 Q8 H4 C
  4. extern Ping_Pong_Buffer res_buff;
    7 e' {) S) X6 e- O) B$ Q. j$ j
  5. / D# Z8 }8 }; y2 Z+ W
  6. extern char k_linkQueue_create(linkQueue *queue, unsigned int dataType, unsigned int blockNumber, unsigned int blockSize);//创建链队列
    : U0 a- g( \/ s- D
  7. extern void k_linkQueue_release(linkQueue *queue);//释放链队列- C" ^( H" x' d- A5 r! Q" x
  8. extern unsigned int k_linkQueue_insertData(linkQueue *queue, void *data, int force);//链队列插入数据* \1 u! ^* c% Q5 n
  9. extern unsigned int k_linkQueue_getData(linkQueue *queue, void *r_buff);//获取队列的数据+ a( V7 L5 F* s" t/ @
  10. 5 i* G4 @7 H1 K+ \2 }/ J8 R
  11. extern void SHM_ARM_Init(unsigned char* const mem_base);//共享内存初始化% C" j; X$ n/ Q7 y' z
  12. 7 {7 I1 k0 S8 ^1 n- k6 Z. Z" A6 B
  13. static int read_quest = 0;//如果有读取数据请求且链队列无数据可读,则置10 J1 f  n: [9 {
  14. //设置主从设备号/ s" S9 G! b  \) i$ M- ?1 I
  15. #define PROTOCOL_MAJOR      1
    ! ~, B2 v4 a+ l; m: Q( K: m0 d
  16. #define PROTOCOL_MINOR      09 H; s* T% o/ v( D- K1 k% s- p5 N; w

  17. 2 w" J" t( s% Z0 [1 y
  18. 7 N' b2 r6 n. I  b
  19. 5 f- `- a8 G& d" Y  k2 P' B) k
  20. //定义设备驱动的名字或设备节点的名字: }; q' l& W; j  [) L5 ~0 h7 }
  21. #define     DEVICE_NAME         "protocol_driver"/ }! S0 O& K( C

  22. ) k' @3 j% q) H6 f# U

  23. 6 C# S* [: k$ N+ @
  24. //定义全局的循环队列作为数据缓冲区" Z- _+ N& q/ u$ `# O7 \) ^
  25. k_linkQueue queue;
    . m4 z% D/ X; m# Y, C3 E( n/ l7 k
  26. * }; s% g1 l1 S2 M8 b
  27. //寄存器地址映射全局变量
    5 [8 T, n% a5 z4 R* C( E
  28. unsigned int *R_CHIPSIG = NULL;//CHIPSIG寄存器
    7 H$ `4 Y, _) m+ P. Y
  29. unsigned int *R_CHIPSIG_CLR = NULL;//CHIPSIG_CLR寄存器. |) ^  q+ {8 M; L8 k+ n8 b
  30. / c( b+ |% @1 \7 D. b
  31. //物理内存映射全局变量
    ; n8 I7 s! M/ Z$ S0 B
  32. volatile void *mem_base = NULL;
    ( u9 ~$ p5 n" Q" c( J. L* x
  33. volatile unsigned char *cur_buf_ptr = NULL;! C0 f  j7 X2 m6 m: L
  34. volatile unsigned char *data_ready_ptr = NULL;
    % V: w2 U* a5 }" D

  35. 2 b+ E0 k$ S  H; ~
  36. 9 H! m( ?% M8 K4 e3 C

  37. 7 b2 n9 _/ B3 W4 ], h0 P
  38. //定义读数据等待队列头,IO阻塞
    0 E* u9 C8 ?# r  j5 w( S" N4 |$ h9 h
  39. DECLARE_WAIT_QUEUE_HEAD(wait_queue_head);
    * T) d6 U# P; L, F
  40. 5 W+ `% j: m* _; U& v' D4 A
  41. //定义原子变量
    ' F. O' ?  w2 `6 u0 ]
  42. static atomic_t dev_available = ATOMIC_INIT(1);//原子变量的值为1,即只能一个进程打开此设备
    2 E+ v% t  D6 b, y9 t0 A
  43. + [# v6 l  ~. E( ?' l  [3 \- B7 O
  44. 5 }8 B5 Z# [4 H# |* h
  45. //定义设备类. t  J% c  u+ G( z
  46. static struct class *protocol_class;
    / S1 W" i/ @' n- j( l/ z
  47. struct cdev *protocol_cdev;" C) u' d( X, D4 ]  `8 c
  48. dev_t protocol_dev_no;
    $ y  j4 C# e  R9 f$ {3 ~
  49. 4 ^0 G' J+ M# b, v2 ?* _
  50. /*定义tasklet和声明底半部函数并关联*/
    # f+ ~9 T# J) p, k  z( T! ^
  51. void read_data_tasklet(unsigned long);- T7 d7 Z* ^; L; [* N

  52. - m( m: v6 t+ |$ h0 m5 t
  53. DECLARE_TASKLET(CHIPINT0_tasklet,read_data,0);
    & I5 |: s$ s5 T, L6 `
  54. //将CHIPINT0_tasklet与read_data绑定,传入参数0+ q  G' t4 c' q. _& |: J

  55. 5 W! E* ~/ c( o8 L5 E6 w& i2 z
  56. /*中断处理底半部, 拷贝内存*/
    1 s  \/ ~8 D4 }2 t: k1 T- H) {
  57. void read_data(unsigned long a)' |5 H8 F# e- f4 v
  58. {
    " `5 W9 o2 w8 \7 G4 e
  59.     if(read_quest == 1)//如果进程调用了此驱动的read函数且链队列没有数据可读,read_quest将会被赋值为15 x$ G! i. u, E3 C2 n/ H
  60.     {
    : w! ]6 c# M) K- E( Z; m
  61.         read_quest = 0;7 C& L; w& E; ~1 K6 ~2 @) a0 _0 K
  62.         wake_up_interruptible(&wait_queue_head);//唤醒读等待队列
    ) m( j$ |# H' B
  63.     }( f  y9 d- K8 X, r, N# C

  64. 7 D% x: d' \; @5 `% J$ S
  65. }
    3 b, r. Y6 R; A2 [: q4 O3 L1 ?
  66. 6 w- ^# ?( h+ _3 P& a/ c  |9 Z
  67. /*中断处理顶半部*/- V* F4 u* Q# ^! H% y
  68. irqreturn_t CHIPINT0_interrupt(int irq,void *dev_id)
    % i. R# t( r4 G& [5 ?
  69. {
      C8 }  g" d, [, f
  70.     //只要一触发进入这个程序,其他驱动会出问题,即使这个程序什么都不做也会这样" Z9 t2 O% f! b4 Y6 e% ?
  71.     volatile Buffer_Type *next_read;
    ' j. \1 i, `# Y/ L3 x6 s
  72.     //如果DSP数据已经ready2 ~9 W' s+ g% z
  73.     if(*(res_buff.cur_buffer->data_ready) == 1)
    ) Y9 u1 l8 v" B+ O9 Q  M0 d; R
  74.     {
    5 d( w' ~2 O" q' ^0 |! {5 [
  75.         if(*(res_buff.bufferID_ptr) == BUFF_ID_PING)//切换读buffer
    5 m# G, k9 R$ r6 ~
  76.         {7 }" `! J9 w& h, I% Q
  77.             next_read = &res_buff.pong_buffer;//下一次中断读pong buffer
    2 M/ ^' D' R8 W
  78.             //printk(KERN_ALERT"read ping\n");
    3 s% S+ G+ y7 H/ e
  79.         }0 `3 |9 |# b9 N9 i' Y! z
  80.         else
    + ]' T  x- J: w! J
  81.         {$ ?5 H2 _/ J7 S  v
  82.             next_read = &res_buff.ping_buffer;//下一次中断读ping buffer
    8 Y+ w6 C  q7 _1 M5 j% U
  83.             //printk(KERN_ALERT"read pong\n");
    : _  p5 j1 S% s. }" v: u
  84.         }
    0 B5 D/ H3 ^# G. q
  85.         *(res_buff.bufferID_ptr) ^= BUFF_ID_PING;//切换DSP写另一个buffer
    ; R3 I! w. m$ s6 j2 a1 u
  86.         //将数据插入链队列$ N: F9 E0 q5 R* j
  87.         k_linkQueue_insertData(&queue, res_buff.cur_buffer->buf_ptr, 0);/ T, }- s# L2 j- E, ?
  88.         //标识位都重置
    $ a9 R1 d$ H  Q8 X5 U
  89.         *(res_buff.cur_buffer->data_ready) = 0;
    ; T: m; @9 G% f- ^2 o
  90.         *(res_buff.cur_buffer->data_size) = 0;
    . o& V4 b; ?3 U' P
  91.         res_buff.cur_buffer = next_read;& t& T! U3 C( @1 i7 |2 v
  92.     }- |( k) v2 [, Z  }8 W* o
  93.     //清楚中断标识
    * a9 Q. \* p4 y* G5 R8 T
  94.     *R_CHIPSIG_CLR = 1 << 0;//clear chipint0 status0 g% m! t6 v5 M1 A& w
  95.     tasklet_schedule(&CHIPINT0_tasklet);//调度底半部     % q8 S# g0 [' g1 ]1 `8 M" K

  96. " \0 @- I4 |3 N; V$ e
  97. + `) V; m/ V: l
  98.     return IRQ_HANDLED;6 [2 i  q5 d. F+ U0 f$ ?
  99. 8 F( a" y9 k2 w4 w/ |
  100. }$ K- o" x8 V$ @; D
  101. 4 D* p- _5 T; }2 X. {4 }  t
  102. //文件打开函数
    . m' v; K0 D4 a" D
  103. static int protocol_open(struct inode *inode, struct file *file)
    " Q6 U6 g8 m. i6 `$ B
  104. {2 g+ l3 K0 ]' A: \
  105.     int result = 0;  T9 [/ g/ r  N
  106.     if(!atomic_dec_and_test(&dev_available))
    , J! E$ L9 w3 P* b" K$ N
  107.     {
    % W( ~5 s* l0 C$ Z/ M5 n
  108.         atomic_inc(&dev_available);
    7 T5 [7 M) Q4 P3 a/ G4 ]# f
  109.         return -EBUSY;//设备已经被打开
    3 x) ?) E/ I/ F" _' |
  110.     }& N( R% o' s3 C4 g* C
  111.     printk (KERN_ALERT "\nprotrol driver open\n");
    - @# p2 A! P9 s. g( c: O5 ^
  112.     return 0;4 j1 e: ]3 I" p) ]( t
  113. }
    , C% w6 Y+ F' \6 h( O. s

  114. ) S" K4 g! w, P* z% z
  115. //文件释放函数/ c* p; A4 r) d* e4 W/ i  a
  116. static int protocol_release(struct inode *inode, struct file *filp)# g) c0 U2 _8 V* E# X# R% q
  117. {
    : ?8 G: f3 o$ j# k
  118.     atomic_inc(&dev_available);//释放设备,原子变量加15 s5 ]: m5 f$ C9 a5 V& r; w: Q, A9 ~
  119.     printk (KERN_ALERT "device released\n");
    % L& e# ^& D6 ]4 W! g+ H* p( H
  120.     return 0;5 {7 N+ T. e6 ~  R' w+ e
  121. }
    - C' ?2 x  M9 C: E
  122. 6 D5 o* y- u' [: R
  123. //文件读函数
    $ Y1 w. ~0 }- x, v- `% I  n9 G; J* ^: D
  124. static int protocol_read(struct file *filp, char *dst, size_t size, loff_t*offset)) [1 S" k! }- d0 G% d) H
  125. {
    $ ]$ V2 u! t. I" L
  126.     int ret = 0;; _& h2 o- D4 M7 M# |- M
  127.     //定义等待队列
    ( ^6 e, {1 `" f! T( ^
  128.     DECLARE_WAITQUEUE(wait_queue, current);//定义等待队列
    8 h) s3 ]5 i) y9 c0 A" }
  129.     add_wait_queue(&wait_queue_head, &wait_queue);//添加等待队列
    1 X" t1 x0 s$ q( |
  130.     if(queue.remainNumber == queue.blockNumber)//当前buffer没数据0 e& ^) _) R! z1 `
  131.     {" z) F0 A; j% E" v8 x
  132.         //printk(KERN_ALERT"\nbuffer no data\n");" P& ?5 h$ v( \7 ?4 Y
  133.         //如果是非阻塞方式读取,则直接跳出/ Q8 ~1 B0 T  r3 W
  134.         if(filp->f_flags & O_NONBLOCK)$ n2 @# y) W4 d6 O9 x6 S
  135.         {) I  f. H4 r( M! [
  136.             ret = -EAGAIN;+ @9 h' D0 ?& J) t+ J7 v
  137.             goto out;# J, Z, B0 A% h
  138.         }
    . p, x4 S7 |0 q) }" C
  139.         //阻塞当前进程,放弃cpu资源3 l7 j+ r) c& d! l6 ?8 p& W  x2 I0 K
  140.         read_quest = 1;& G7 ]( f. |" ^/ ~
  141.         __set_current_state(TASK_INTERRUPTIBLE);//改变进程状态为睡眠: f; n& ?2 p' T  I) Z; M2 k
  142.         schedule();//调度其他进程运行  g$ A4 Y( Q& J' o3 Q8 L- ~* ?) d
  143.         if(signal_pending(current))
    : R- I; K  z/ ]
  144.         {
    ' q, I1 |" v2 G- C# ]
  145.             //如果是因为信号被唤醒,则返回到系统调用之前的地方
    8 h. u/ [' ?4 ?8 E
  146.             ret = -ERESTARTSYS;
    " x7 v8 ?8 s* X) ~: j& I+ C
  147.             goto out;
    7 s! n7 `, R# R1 L7 I
  148.         }
    ! G+ ]9 b5 Z* j9 S
  149.     }0 X1 V8 R- \- s. e; E
  150.     //将数据拷贝到用户空间( f; D, L' _8 ?2 D/ }, }( \
  151.     ret = k_linkQueue_getData(&queue, dst);/ ^4 n7 F+ g  ~/ d/ k6 X
  152.     if(ret == 0)
    4 B4 J8 v4 G- }* D7 I
  153.     {
    5 Y7 ^# ^. g% S2 U
  154.         //printk(KERN_ALERT"\ncopy data to user space failed :%d\n", ret);
    * @5 ]5 e9 Z" F4 p+ S4 Z/ N$ w
  155.     }6 w' T0 H7 _& ^: a4 G1 k1 F
  156. out:
    5 J1 Y: y  x, |( F) }
  157.     remove_wait_queue(&wait_queue_head, &wait_queue);//移除等待队列
    ) b( [& F" x3 t
  158.     set_current_state(TASK_RUNNING);//设置当前进程为运行状态
      c) l% c( `0 [0 [/ S
  159.     return ret;
    # ]$ v& [. ~( B
  160. }
    1 l' ?/ c0 l' K4 b7 o

  161. 1 Q. n+ z0 }% p& R4 F

  162. + {( z. D" n) R0 R- z) U' ]. L. ^
  163. static long protocol_ioctl(struct file *file, unsigned int cmd, unsigned long value)
    . D' x' z- B- G' F: \
  164. {
    7 `: o1 s2 C& ]6 ?0 U* z0 ]
  165.     return 0;
    0 C# G$ Q8 Y  A
  166. }
    : q; g  q' ^& p) c& `4 \  j& z
  167. /*驱动文件操作结构体,file_operations结构体中的成员函数会在应用程序进行
    ; w& ^1 j: O+ Q5 \
  168. open()、release()、ioctl()协同调用时被调用*/
      A  A0 B4 J# [( N  Z
  169. static const struct file_operations protocol_fops =0 V' w. {0 N* t$ k( E
  170. {
    9 F& P6 p& Z; N; S: Y* b
  171.   .owner    = THIS_MODULE,
    * w+ l* h9 U" G( P' g; R* z) G+ L% k8 p# {$ B
  172.   .open     = protocol_open,0 ^4 S, R% J0 ^. h0 G
  173.   .release  = protocol_release,
    3 ~3 Z& e# l/ j( u
  174.   .read     = protocol_read,: i- u2 r! p2 H$ k% T% k2 t0 ^
  175. //  .write  = protocol_write,0 D4 N4 n4 b0 n; l
  176.   .unlocked_ioctl=protocol_ioctl,  b& b- A! }3 k3 m5 m' q& Y2 w
  177. };
    " A2 V% ]& \0 b& B
  178. % \8 J0 a. X7 X  s1 O' P$ p8 ^9 _
  179. /*设备驱动模块加载函数*/; T! m1 Z& F% A; F. c
  180. int __init protocol_init(void)
    ) A) R" v) L$ M: P- k4 E! a" P
  181. {1 d/ A9 D  K" \
  182.     int ret = 0;
    " e6 L# Y. l( A
  183.     int result = 0;
    + Q& [" r: f* P. q: Q; _
  184.     //申请注册设备号(动态)' g7 t! {6 R+ E; m' ?# V& D
  185.     ret=alloc_chrdev_region(&protocol_dev_no, PROTOCOL_MINOR, 1, DEVICE_NAME); + \: \! I* N. O  Q6 ], k4 Z
  186.     if(ret < 0); C; J# ?* E8 B. A0 T
  187.     {
    - o1 q  e- e' x8 q  J6 Y, Q
  188.             printk(KERN_EMERG "alloc_chrdev_region failed\n");3 s* v# j6 L% `& {
  189.             return 0;+ u  u$ t$ g, s  I: M4 m1 ~  K
  190.     }
    ; A5 C& m+ v7 @: R
  191.     //分配cdev
      d: A0 X& e, A! R
  192.     protocol_cdev = cdev_alloc();5 w% R* \! s/ Q$ U
  193.     if(protocol_cdev == NULL)
    7 \) v8 t" d7 r1 |7 D
  194.     {$ P1 }& H$ t4 u; G' G, i9 z# s- {0 r. ?
  195.             printk(KERN_EMERG "Cannot alloc cdev\n");
    2 ?+ }- c. r7 I
  196.             return 0;
    2 h1 d& ^7 ^2 @& W, S# `" o
  197.     }
    & A- E! {8 ?* b( Y6 ^: y: S
  198.     //初始化cdev
    $ w) N$ L9 T! r/ w+ t" p2 A
  199.     cdev_init(protocol_cdev,&protocol_fops);
    * \. g7 Z0 X. W- {) h: L
  200.     protocol_cdev->owner=THIS_MODULE;
    ) j3 V$ `# ~7 d  M/ S$ H  H' [7 j
  201.     //注册cdev
      i" Z. `8 e1 x- B/ S2 R7 k
  202.     cdev_add(protocol_cdev, protocol_dev_no, 1);
    1 F7 z% x- }$ N) f7 y. d
  203.     //创建一个类
      G, ~' N7 r: B; o; ^
  204.     protocol_class = class_create(THIS_MODULE, DEVICE_NAME);0 a; s( t& |% Z' _5 e3 }. g
  205.     //创建设备节点' E4 P* b. K- c, y- J( Z6 V2 x
  206.     device_create(protocol_class, NULL, protocol_dev_no, NULL, DEVICE_NAME);
    8 e- X) b2 o, i  T  S
  207.     5 Y9 p7 n( g9 K
  208.    
    4 F1 z& ^" ~5 ]
  209.     //申请链式循环队列作为缓冲区DSP数据帧的缓冲区6 i1 S/ D! K8 g" I
  210.     k_linkQueue_create(&queue, sizeof(double), 1000, DATA_BLOCK_SIZE);//申请1000个blocksize的队列空间作为帧缓冲区; o  E& b2 Y! H5 x- P: e
  211. ( _2 A. q' u1 X: J" w# D) d; x
  212. //映射ARM的核间通讯寄存器0 O: h: |0 z' l9 D
  213.     R_CHIPSIG = ioremap(SOC_SYSCFG_0_REGS + SYSCFG0_CHIPSIG, 4);* A* [( I" V, Y2 Y
  214.     R_CHIPSIG_CLR = ioremap(SOC_SYSCFG_0_REGS + SYSCFG0_CHIPSIG_CLR, 4);
    " s* Z% e6 c! |3 k
  215.     //将物理地址映射到内核空间
    ( b0 V& P7 e) |6 G% E
  216.     mem_base = ioremap(SHARED_BUFFER_ADDR, SHARED_BUFFER_SIZE);5 ^2 }2 f  U3 a2 k9 y0 J) D
  217.     //共享内存初始化
    9 p; v8 d2 }# }7 B
  218.     SHM_ARM_Init((unsigned char *)mem_base);) n) |, q' _, ~: s
  219.     /*申请中断*/: v9 _$ J+ q# Y

  220. ) d& A* @0 z. D- g
  221.     result = request_irq(IRQ_DA8XX_CHIPINT0, CHIPINT0_interrupt,IRQF_SHARED,"DSP Signal",&protocol_cdev);
    9 p' k8 s. p2 Q! s# V
  222.     if(result != 0)
    5 e8 k5 d3 q6 R6 Z' j7 [& f' C
  223.     {, \! L$ X2 }$ {3 e( y$ [# k
  224.         if(result == -EINVAL)
      R# \% B4 a! w
  225.         {) B: ~3 z+ f: z& p9 {
  226.             printk(KERN_ALERT "irq request err:-EINVAL\n");
    * v9 n; {4 ], g# M2 v/ a& a2 K# A
  227.         }  `" J& {. D$ T3 w6 _1 m
  228.         else if(result == -EBUSY)8 Q2 M0 O, t3 H. I  c
  229.         {( h# W2 X: n( M. b; O8 R' r
  230.             printk(KERN_ALERT "irq request err:--EBUSY\n");
    5 ~$ T0 t- M  G0 Y+ p  G0 W
  231.         }0 ~' ~. _( t; C/ Z5 e1 j6 C
  232.         else( B, q2 t% `; {- m" J
  233.         {
    ( `6 e2 x8 J( R+ p$ W" |/ M
  234.             printk(KERN_ALERT "irq request err: unknown\n");; |' b$ i' \9 w% a* n% A2 ]( W
  235.         }
    % V. D& j2 r% [. R
  236.         return result;  I% @8 z- r0 h  P; E2 b% C" G4 |
  237.     }
    * v3 t0 y5 L1 ], V9 m
  238.     return 0;" g$ C- M4 K" i! h9 Z
  239. }
    6 ]2 W. @3 G; ?' p: d
  240. 7 C$ `. w  t2 R1 K; y' q# p- A
  241. /*设备驱动模块卸载函数*/
    : ?1 n/ C8 x# h5 u
  242. void __exit protocol_exit(void)
    2 s: q) m8 x2 [6 M; ~. T
  243. {
    6 [/ h9 f$ W9 }; m* \- O
  244.         /*释放中断*/
      ^. V6 C9 _5 x) q& o
  245.     free_irq(IRQ_DA8XX_CHIPINT0, NULL);3 l+ i8 K2 M. l/ d" H& l3 f7 f! _
  246.     //释放帧缓冲的内存& @6 M; G. Q6 Z# ^
  247.     k_linkQueue_release(&queue);
    9 x. W6 B: S+ L$ i
  248.     //释放寄存器映射
    $ n$ i) D+ {% \( o  D" B
  249.     iounmap(R_CHIPSIG);9 t" u' h# Q' a: t& Q7 s' \. }
  250.     iounmap(R_CHIPSIG_CLR);
    & \4 v5 W4 F8 u
  251.     cdev_del(protocol_cdev);                            //删除cdev
    8 e- |! Y: \- }3 ]$ l
  252.     unregister_chrdev_region(protocol_dev_no, 1);   //注销设备号& E8 T1 D& M' w( z0 z  Y5 x
  253.     device_destroy(protocol_class, protocol_dev_no);            //销毁设备节点( b. N6 w9 [3 R, S$ @7 a
  254.     class_destroy(protocol_class);                      //销毁设备类
    % u' l) G0 g3 Z$ V
  255.     printk(KERN_ALERT "exit success\n");
    0 M1 J( Y6 F0 `, J1 K( u

  256. % p; y# W9 t* Q8 l+ k) ^
  257. }
    ; r2 f% J+ V9 x
  258. //驱动其他部分省略
复制代码

- E& ]$ ~" @4 b
5 ?2 `( D* G7 l  {- T
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖
回复

使用道具 举报

5

主题

24

帖子

95

积分

注册会员

Rank: 2

积分
95
沙发
 楼主| 发表于 2017-4-16 13:54:19 | 只看该作者
没有人遇到这个问题吗
回复 支持 反对

使用道具 举报

3

主题

852

帖子

3538

积分

创龙

Rank: 8Rank: 8

积分
3538
板凳
发表于 2017-4-16 18:19:44 | 只看该作者
可以参考一下TL_IPC双核通信例程。
. z  v0 i9 w2 Y% \5 R, ]TL_IPC是广州创龙独立开发的一种双核通讯协议。ARM核上运行Linux程序,DSP核上运行裸机或SYS/BIOS程序。基于TL_IPC的开发是指在两个处理间采用以直接触发中断进行异步事件通知,以直接读写共享内存进行数据交换,并结合创龙提供的c674x_irq_events内核模块(用于ARM端程序捕获由DSP触发的中断)实现双核通信的一种双核开发方式。
回复 支持 反对

使用道具 举报

5

主题

24

帖子

95

积分

注册会员

Rank: 2

积分
95
地板
 楼主| 发表于 2017-4-16 21:23:53 | 只看该作者
human 发表于 2017-4-16 18:19( r5 F) y) F9 l. Q: b$ w
可以参考一下TL_IPC双核通信例程。  k0 O7 C; W9 Y
TL_IPC是广州创龙独立开发的一种双核通讯协议。ARM核上运行Linux程序,D ...

  s( Q1 m$ r- z9 _3 Z; D% |@human 您好,请问有c674x_irq_events模块的源码吗,光盘没有附带,只提供模块,这个模块还不能满足我的需求,但是我想参考他的中断实现。谢谢
回复 支持 反对

使用道具 举报

5

主题

24

帖子

95

积分

注册会员

Rank: 2

积分
95
5#
 楼主| 发表于 2017-4-17 10:12:54 | 只看该作者
human 发表于 2017-4-16 18:19
% [/ Y" ^( y& N  |$ k2 y可以参考一下TL_IPC双核通信例程。
2 |4 ?$ |3 ^: g  d* z$ o' C; uTL_IPC是广州创龙独立开发的一种双核通讯协议。ARM核上运行Linux程序,D ...

  A! C3 b; [# c请问有c674x_irq_events模块的源码吗
回复 支持 反对

使用道具 举报

5

主题

24

帖子

95

积分

注册会员

Rank: 2

积分
95
6#
 楼主| 发表于 2017-4-17 12:08:24 | 只看该作者
问题已解决,驱动没有任何问题,而是DSP端调用了DelayTimerSetup()这个函数导致定时器的状态被改变,从而导致arm端的定时器驱动无法正常工作,而依赖此定时器的其他驱动也就无法正常工作了,这也是双核的弊端吧,两个核共用一些资源,如果一个核在没有告知其他核的情况下改变了一些资源的寄存器就会导致出问题。
回复 支持 反对

使用道具 举报

5

主题

24

帖子

95

积分

注册会员

Rank: 2

积分
95
7#
 楼主| 发表于 2017-4-17 13:07:27 | 只看该作者
至于DSP触发ARM中断两次的问题,这是由于linux的中断机制导致的,可以参考https://e2e.ti.com/support/embedded/linux/f/354/t/234510
3 ~/ o# |' F  H7 k3 M% `解决方法:在dsp端触发后立即将clr标志位置1清除中断线,即可解决触发两次的问题
回复 支持 反对

使用道具 举报

3

主题

852

帖子

3538

积分

创龙

Rank: 8Rank: 8

积分
3538
8#
发表于 2017-4-17 15:41:59 | 只看该作者
加陈工的QQ2942385389获取资料
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|嵌入式开发者社区 ( 粤ICP备15055271号

GMT+8, 2025-8-3 03:23 , Processed in 0.126574 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2015 Comsenz Inc.

快速回复 返回顶部 返回列表