主架构 run()详解

运行机制

​ 该架构是用消息机制实现的,运行框架基于消息处理机制,消息根据来源分为两种:内部消息和外部消息。 内部消息:lua 脚本调用本文件 dispatch 接口产生的消息,消息存储在 qmsg 表中。 外部消息:底层 core 软件产生的消息,lua 脚本通过 rtos.receive 接口读取这些外部消息。 ​ 消息根据类型,也有两种:table 型和 Number 型。Number 型使用比较频繁。 Number 类型的消息目前分为:

  • 定时器 timeout 消息(msg.id=rtos.MSG_TIMER=1)
  • 串口消息(msg.id = rtos.MSG_UART_RXDATA=2)又分为虚拟 AT 口(msg.uart_id = uart.ATC)和串口(msg.uart_id = 串口号)
  • 键盘消息(msg.id=rtos.MSG_KEYPAD=3)
  • 中断消息(msg.id=rtos.MSG_INT=4)
  • 电源管理消息(msg.id=rtos.MSG_PMD=5)。

​ 当电池在位状态、电池电压百分比、电池电压、充电器在位状态、充电状态任何一个发生-- 变化,就会上报该消息。

  • msg.present (电池在位状态,boolean 型,true 或 false)
  • msg.level (百分比 0-100,number 型)
  • msg.voltage (电池电压,number 型)
  • msg.charger (充电器在位状态,boolean 型,true 或 false)
  • msg.state (充电状态,number 型,0-不在充电 1-充电中 2-充电停止)

消息注册

​ 各个消息处理程序使用前需要用 regmsg 程序注册到 handlers 表中(除了定时器 timeout 消息和 物理串口消息以外)。这样代码改动影响面小,当业务流程有修改的时候,只需要修改具体的消息处 理程序的内容即可。

​ 消息注册函数讲解参阅消息注册

run() 流程详细介绍

function run()
    local msg,msgpara
    while true do
        --处理内部消息
        runqmsg()
        --阻塞读取外部消息
        msg,msgpara = rtos.receive(rtos.INF_TIMEOUT)

        --电池电量为0%,用户应用脚本中没有定义“低电关机处理程序”,并且没有启动自动关机定时器       
        if --[[not lprfun and ]]not lpring and type(msg) == "table" and msg.id == rtos.MSG_PMD and msg.level == 0 then
            --启动自动关机定时器,60秒后关机
            lpring = true
            timer_start(rtos.poweroff,60000,"r1")
        end

        --外部消息为table类型
        if type(msg) == "table" then
            --定时器类型消息
            if msg.id == rtos.MSG_TIMER then
                timerfnc(msg.timer_id)
            --AT命令的虚拟串口数据接收消息
            elseif msg.id == rtos.MSG_UART_RXDATA and msg.uart_id == uart.ATC then
                handlers.atc()
            else
                --物理串口数据接收消息
                if msg.id == rtos.MSG_UART_RXDATA then
                    if uartprocs[msg.uart_id] ~= nil then
                        uartprocs[msg.uart_id]()
                    else
                        handlers[msg.id](msg)
                    end
                --串口发送数据完成消息
                elseif msg.id == rtos.MSG_UART_TX_DONE then
                    if uartxprocs[msgpara] then
                        uartxprocs[msgpara]()               
                    end
                --其他消息(音频消息、充电管理消息、按键消息等)
                else
                    handlers[msg.id](msg)
                end
            end
        --外部消息非table类型
        else
            --定时器类型消息
            if msg == rtos.MSG_TIMER then
                timerfnc(msgpara)
            --串口数据接收消息
            elseif msg == rtos.MSG_UART_RXDATA then
                --AT命令的虚拟串口
                if msgpara == uart.ATC then
                    handlers.atc()
                --物理串口
                else
                    if uartprocs[msgpara] ~= nil then
                        uartprocs[msgpara]()
                    else
                        handlers[msg](msg,msgpara)
                    end
                end
            --串口发送数据完成消息
            elseif msg == rtos.MSG_UART_TX_DONE then
                if uartxprocs[msgpara] then
                    uartxprocs[msgpara]()               
                end
            end
        end
        --打印lua脚本程序占用的内存,单位是K字节
        --print("mem:",base.collectgarbage("count"))
    end
end

​ 在 ril.lua 中我们已经用 sys.regmsg("atc",atcreader)把 ATC 口的处理程序注册好了。

​ 如果需要电源管理,可以单独写个应用模块,比如取名为 power.lua,并在里面注册 rtos.MSG_PMD 消息处理程序,并定义相应的处理程序。

​ 如果需要 GPIO 中断,也可以单独写个应用模块,并在里面注册 rtos.MSG_INT 消息的处理程序, 并定义相应的处理程序。

​ 如果想单独运行一个函数,可以将通过定时器调用函数。具体例子可参阅定时器