SylixOS中CTRL+C的大致处理流程

1.这几天在处理GPU方面的问题时碰到了在终端执行CTRL+C报错的问题,具体见Vivante GPU驱动报:SAFE mode error错误解决方法这篇帖子,这里主要记录CTRL+C的大致处理流程。

2.当键盘按下CTRL+C时,主机就向目标板发送一个控制字符,其ASSIC码为0x03,在SylixOS下常用的控制字符如下,此定义是在tyLib.c文件中

  1. /*********************************************************************************************************
  2.   全局变量(控制字 __LINUX_BACKSPACE_CHAR 直接按 backspace 处理)
  3. *********************************************************************************************************/
  4. #define __LINUX_BACKSPACE_CHAR      127                                 /*  linux 下的退格 control-?    */
  5. #define __TTY_BACKSPACE(ptyDev, ch) ((ch) == __LINUX_BACKSPACE_CHAR || (ch) == __TTY_CC(ptyDev, VERASE))
  6.  
  7. static CHAR             _G_cTyBackspaceChar  = 0x08;                    /*  默认值     control-H        */
  8. static CHAR             _G_cTyDeleteLineChar = 0x15;                    /*  默认值     control-U        */
  9. static CHAR             _G_cTyEofChar           = 0x04;                    /*  默认值     control-D        */
  10. static CHAR             _G_cTyAbortChar        = 0x03;                    /*  默认值     control-C        */
  11. static CHAR             _G_cTyMonTrapChar   = 0x18;                    /*  默认值     control-X        */

复制代码



3.开发板收到数据时,就转入uart中断处理函数中执行,中断处理函数如下

  1. /*********************************************************************************************************
  2. ** 函数名称: imx6SioIsr
  3. ** 功能描述: SIO 通道中断处理函数
  4. ** 输 入  : psiochanChan                 SIO 通道
  5. ** 输 出  : NONE
  6. ** 全局变量:
  7. ** 调用模块:
  8. *********************************************************************************************************/
  9. static irqreturn_t  imx6SioIsr (SIO_CHAN  *psiochanChan, ULONG  ulVector)
  10. {
  11.     __PSIO_CHANNEL          psiochanUart = (__PSIO_CHANNEL)psiochanChan;
  12.     CHAR                    cChar;
  13.  
  14.     if (imx6UartIsTxInt(psiochanUart->iChannelNum)) {                   /*  发送中断                    */
  15.         while (!imx6UartTxFifoFull(psiochanUart->iChannelNum)) {
  16.             if (psiochanUart->pcbGetTxChar(psiochanUart->pvGetTxArg, &cChar) != ERROR_NONE) {
  17.                 imx6UartTxIntDisable(psiochanUart->iChannelNum);        /*  关闭发送中断                */
  18.                 break;
  19.             } else {
  20.                 imx6UartTxFifoPut(psiochanUart->iChannelNum, cChar);    /*  发送数据                    */
  21.             }
  22.         }
  23.     }
  24.  
  25.     while (!imx6UartRxFifoEmpty(psiochanUart->iChannelNum)) {           /*  需要接收数据                */
  26.         if (imx6UartRxFifoGet(psiochanUart->iChannelNum, &cChar)        /*  接收数据                    */
  27.             == ERROR_NONE) {
  28.             psiochanUart->pcbPutRcvChar(psiochanUart->pvPutRcvArg, cChar);
  29.         } else {
  30.             break;
  31.         }
  32.     }
  33.  
  34.     imx6UartIntClear(psiochanUart->iChannelNum);                        /*  清除中断                    */
  35.  
  36.     return  (LW_IRQ_HANDLED);
  37. }

复制代码

由代码可知,在uart接受完数据后,执行了psiochanUart->pcbPutRcvChar(psiochanUart->pvPutRcvArg, cChar)这个函数,这个函数是注册SIO设备时所注册好的回调函数,其函数原型是_TyIRd,如下所示

  1. /*********************************************************************************************************
  2. ** 函数名称: _TyIRx
  3. ** 功能描述: 向终端的接收缓冲区中写入一个从硬件接收到的数据, FIFO
  4. ** 输 入  : 
  5. **           ptyDev,            TY 设备
  6. **           cInChar,           接收到的数据
  7. ** 输 出  : ERROR_NONE or PX_ERROR
  8. ** 全局变量: 
  9. ** 调用模块: 
  10. *********************************************************************************************************/
  11. INT  _TyIRd (TY_DEV_ID  ptyDev, CHAR   cInchar)

复制代码

这个函数的主要功能就是将uart接收到的数据上送到系统的输入缓冲区,然后进行一些处理。


4.在_TyIRd中首先就对接受到的数据是否是CTRL+C字符做了一个判断,如下

  1. if ((cInchar == __TTY_CC(ptyDev, VINTR)) && 
  2.     (iOpt & OPT_ABORT) && 
  3.     ((_G_pfuncTyAbortFunc != LW_NULL) || 
  4.     (ptyDev->TYDEV_pfuncCtrlC != LW_NULL))) {                       /*  是否需要进行 ABORT 处理     */
  5.         
  6.     LW_SPIN_UNLOCK_QUICK(&ptyDev->TYDEV_slLock, iregInterLevel);    /*  解锁 spinlock 打开中断      */
  7.         
  8.     if (ptyDev->TYDEV_pfuncCtrlC) {
  9.         ptyDev->TYDEV_pfuncCtrlC(ptyDev->TYDEV_pvArgCtrlC);
  10.     }
  11.     if (_G_pfuncTyAbortFunc) {
  12.         _G_pfuncTyAbortFunc();
  13.     }
  14.     }

复制代码

如果是CTRL+C字符就执行ptyDev->TYDEV_pfuncCtrlC(ptyDev->TYDEV_pvArgCtrlC),这个也是事先注册好的函数,其原型是__tshellRestart,如下所示

  1. /*********************************************************************************************************
  2. ** 函数名称: __tshellRestart
  3. ** 功能描述: ttiny shell 线程重启 (control-C)
  4. ** 输 入  : ulThread   线程句柄
  5. ** 输 出  : NONE
  6. ** 全局变量: 
  7. ** 调用模块: 
  8. *********************************************************************************************************/
  9. static VOID  __tshellRestart (LW_OBJECT_HANDLE  ulThread)

复制代码



5.__tshellRestart函数调用了__tshellRestartEx函数,__tshellRestartEx函数将自己交给了系统的工作队列处理线程来处理,相当于将具体的restart操作放到了中断下半部来处理,如下所示
 

  1.     if (LW_CPU_GET_CUR_NESTING()) {
  2.         return  (_excJobAdd((VOIDFUNCPTR)__tshellRestartEx, 
  3.                                      (PVOID)ulThread, (PVOID)bNeedAuthen, 0, 0, 0, 0));
  4.     }

复制代码

接着会判断本线程是否存在子线程,如果存在则杀死子线程,如果不存在,则重启当前线程,如下所示

  1.     if (ulJoin) {
  2.     #if LW_CFG_SIGNAL_EN > 0
  3.         kill(ulJoin, SIGKILL);                                          /*  杀死等待的线程/进程         */
  4.     #else
  5.         API_ThreadDelete(&ulJoin, LW_NULL);
  6.     #endif                                                                  /*  LW_CFG_SIGNAL_EN > 0        */
  7.         iMsg = API_IoTaskStdGet(ulThread, STD_OUT);
  8.         if (iMsg >= 0) {
  9.             fdprintf(iMsg, "[sh]Warning: Program is killed (SIGKILL) by shell.\n"
  10.                                 "    Restart SylixOS is recommended!\n");
  11.         }
  12.     } else {                                                            /*  重启线程                    */
  13.         API_ThreadRestart(ulThread, (PVOID)__TTINY_SHELL_GET_STDFILE(ptcbShell));
  14.     }

复制代码

API_ThreadRestart就是重启线程函数了,这里就不具体分析了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值