问题描述:
休眠时模块接收短信,连接USB组合的AT串口,不能显示短信信息。
【测试步骤】
1、短信接收方式设置为存储而不显示(AT+CNMI=2,1,0,0,0);
2、执行AT命令,使能低功耗;
3、长按DTR按键进入低功耗;
4、间隔30s以上测试一次来短信,共测试接收短信3次;
5、释放DTR按键;
6、读取接收短信内容;
7、执行AT命令,恢复默认设置。
【预期结果】
1、短信接收方式设置成功;
2、使能低功耗成功,返回OK;
3、成功进入低功耗,设备管理器USB口掉口;
4、低功耗模式下来短信,能唤醒模块,唤醒成功率为100%;
5、模块成功退出低功耗;
6、模块接收到的短信与辅测终端发送的短信一致;
7、恢复默认设置成功。
【实测结果】
6、模块退出低功耗后,不上报来短信提示,发送一条AT指令后才上报来短信。
分析:
应用的同事反馈UartWrite -> xxx_handler_write --> write这里返回值w_cnt是正数,表示写正常,但是休眠后最终没有在串口AT上打印出来,怀疑是底层驱动的问题。
思路:看一下 w_cnt = write(m_pc_write_fd, buf, len)调用的流程,是不是只写到缓存里去了。
流程:
应用的write调用
–> tty_write(tty_io.c)
–> do_tty_write
–> n_tty_write
–> gs_write (u_serial.c)
–> gs_start_tx
gs_start_tx这个函数实现usb底层对数据的封装,传送到usb的端点。
通过添加打印,发现休眠时gs_write这个函数里port->port_usb为空,只是把数据存到了buf,并没有调用gs_start_tx(port)。意味着USB端口还没有正常配置完成,并没有写成功。所以需要修改了这里的代码逻辑:如果没有写成功,给上层报一个负值,表示写出错,由上层保证写正确。
static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
struct gs_port *port = tty->driver_data;
unsigned long flags;
pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
port->port_num, tty, count);
spin_lock_irqsave(&port->port_lock, flags);
if (count)
count = gs_buf_put(&port->port_write_buf, buf, count);
/* treat count == 0 as flush_chars() */
if (port->port_usb)
gs_start_tx(port);
spin_unlock_irqrestore(&port->port_lock, flags);
return count;
}
这里无论是否发送成功,都会返回count。
修改如下:
#define USB_DISCONNECT_ERR -11
static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
struct gs_port *port = tty->driver_data;
unsigned long flags;
pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
port->port_num, tty, count);
spin_lock_irqsave(&port->port_lock, flags);
//begin:stone modify for tty disconnect
if (port->port_usb)
{
if (count)
count = gs_buf_put(&port->port_write_buf, buf, count);
}
else
count = USB_DISCONNECT_ERR;
//end:stone modify for tty disconnect
/* treat count == 0 as flush_chars() */
if (port->port_usb)
gs_start_tx(port);
spin_unlock_irqrestore(&port->port_lock, flags);
return count;
}