08 otp
作者:马亚丹 | 最后修改:2026-04-13
一、什么是 otp
otp 核心库是合宙 LuatOS 系统中用于操作" 一次性可编程存储(One-Time Programmable Memory)"的模块,主要作用是:
- 读取芯片内置 otp 区域的数据(如设备唯一 ID、加密密钥、生产信息等);
- 向 otp 区域写入数据
关键注意事项
- otp 的 “一次性” 特性:
- 关于擦除重写。目前只有 Air780Exx 系列/Air8000x 系列支持 otp 写入后擦除重写,Air8101 系列不支持写入后再擦除重写。
- 关于加锁。合宙所有模组 otp 加锁都是不可逆的,otp 存储区域写入后如果加锁就不可再擦除重写,会变成永久只读,因此加锁前必须确认数据正确。
例如:otp.lock(1)锁定 Air780EHV 的 otp 区域 1,返回 true 加锁成功之后,无法再进行 otp 区域 1 的擦除写入。
- 地址与长度限制: 写入 / 读取的长度需与 otp 块大小对齐,按 4 字节对齐。
典型应用场景
- 设备身份标识:读取 otp 中内置的唯一 ID,如 IMEI、序列号,作为设备 “身份证”;
- 加密密钥存储:将 AES/RSA 密钥写入 otp,防止被逆向窃取;
- 生产信息固化:工厂量产时写入固件版本、生产日期等信息,永久保存。
二、功能演示概述
本文演示合宙 4G 模组使用 LuatOS 开发时, otp 的应用功能.
使用 Air780EHV 核心板下载 Air780EHV 的 LuatOS 示例代码中 otp 的例程进行验证,例程中实现的功能核心业务逻辑为:
1.读取指定 otp 区域的数据
2.进入飞行模式,擦除指定的 otp 区域的数据
3.擦除完成后向该区域写入数据
4.谨慎操作区域加锁 (区域加锁后会永久变成只读无法写入)
5.退出飞行模式
三、准备硬件环境
3.1 参考:硬件环境清单第二章节内容,准备以及组装好硬件环境。
3.2 Air780EHV 核心板一块
3.3 TYPE-C USB 数据线一根 ,Air780EHV 核心板和数据线的硬件接线方式为:
- Air780EHV 核心板通过 TYPE-C USB 口供电;(USB 的拨码开关 off/on,拨到 on)
- TYPE-C USB 数据线直接插到核心板的 TYPE-C USB 座子,另外一端连接电脑 USB 口
四、准备软件环境
在开始实践本示例之前,先准备一下软件环境:
4.1、Luatools 工具,如果是第一次使用 Luatools 工具,请仔细阅读此链接教程。
4.2、内核固件文件(底层 core 固件文件):
本demo开发测试时使用的固件为LuatOS-SoC_V2018_Air780EHV_1.soc,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;
4.3、luatos 需要的脚本和资源文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHV/demo/otp
-
main.lua:主程序入口;
-
otp_test.lua: 功能演示核心脚本,读取 otp 区域数据、进入飞行擦除区域写入数据等,在 main.lua 中加载运行。
4.4、lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
准备好软件环境之后,接下来查看如何烧录项目文件到 Air780EHV 核心板,将本篇文章中演示使用的项目文件烧录到 Air780EHV 核心板中。
五、API 接口说明
六、示例代码和功能展示
6.1 流程介绍
1、搭建好硬件环境
2、Luatools 烧录内核固件和 demo 脚本代码
3、烧录成功后,代码会自动运行,查看打印日志,如果正常运行,会打印读取 otp 区域数据、进入飞行擦除区域写入数据等信息,如下 log 显示:
6.2 代码和 log
- 代码示例(点击查看 otp 的完整 demo)
PROJECT = "otp_demo"
VERSION = "001.000.000"
-- 在日志中打印项目名和项目版本号
log.info("main", PROJECT, VERSION)
-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
if wdt then
--配置喂狗超时时间为9秒钟
wdt.init(9000)
--启动一个循环定时器,每隔3秒钟喂一次狗
sys.timerLoopStart(wdt.feed, 3000)
end
-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
-- 启动errDump日志存储并且上传功能,600秒上传一次
-- if errDump then
-- errDump.config(true, 600)
-- end
-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
-- 可以使用合宙的iot.openluat.com平台进行远程升级
-- 也可以使用客户自己搭建的平台进行远程升级
-- 远程升级的详细用法,可以参考fota的demo进行使用
-- 启动一个循环定时器
-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
-- 方便分析内存使用是否有异常
-- sys.timerLoopStart(function()
-- log.info("mem.lua", rtos.meminfo())
-- log.info("mem.sys", rtos.meminfo("sys"))
-- end, 3000)
-- 加载otp_test功能模块
require "otp_test"
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后不要加任何语句!!!!!因为添加的任何语句都不会被执行
- 核心代码部分(点击查看 otp 的完整 demo)
local function otp_test()
log.info("========otp read start=========")
local otpdata = otp.read(1, 0, 64)
if otpdata then
log.info("otp 读取结果", otpdata, type(otpdata))
else
log.info("otp 读取失败")
end
log.info("写数据前先进入飞行模式")
local result = mobile.flymode(0, true)
if result then
log.info("现在是飞行模式",result)
log.info("========otp erase start=========")
local erase_ok = otp.erase(1)
if erase_ok then
log.info("OTP 擦除成功")
else
log.info("OTP 擦除失败")
end
local write_data = "1234"
log.info("=========向otp区域1写入数据==========")
local write_ok = otp.write(1, write_data, 0)
if write_ok then
log.info("OTP 写入成功", write_data)
else
log.info("OTP 写入失败")
end
end
log.info("=========读取otp区域1数据==========")
local otpdata_1 = otp.read(1, 0, 4)
local otpdata_2 = otp.read(1, 0, 8)
if otpdata_1 then
log.info("读取4字节数据", otpdata_1, type(otpdata_1))
else
log.info("===========otp区域1读取失败=========")
end
if otpdata_2 then
log.info("读取8字节数据", otpdata_2, type(otpdata_2))
else
log.info("===========otp区域1读取失败=========")
end
--=====锁定 OTP 区域,特别注意!!! 一定要在飞行模式下操作锁定!!!=============
--=====OTP一旦加锁即无法解锁,OTP 会变成只读!!!
-- local lock_ok = otp.lock(1)
-- if lock_ok then
-- log.info("OTP 锁定成功")
-- end
--===========================================================================
--退出飞行模式
local result2 = mobile.flymode(0, false)
if not result2 then
log.info("退出飞行模式", result2)
end
end
sys.taskInit(otp_test)
- 例程 log 打印如下:
[2025-11-24 17:08:21.592][000000000.370] I/user.main otp_demo 001.000.000
[2025-11-24 17:08:21.602][000000000.377] I/user.========otp read start=========
[2025-11-24 17:08:21.609][000000000.378] I/user.otp 读取结果 string
[2025-11-24 17:08:21.619][000000000.378] I/user.写数据前先进入飞行模式
[2025-11-24 17:08:21.731][000000000.951] I/user.现在是飞行模式 true
[2025-11-24 17:08:21.738][000000000.951] I/user.========otp erase start=========
[2025-11-24 17:08:21.744][000000000.952] I/otp otp erase zone 1 00001000
[2025-11-24 17:08:21.749][000000000.953] I/user.OTP 擦除成功
[2025-11-24 17:08:21.755][000000000.953] I/user.=========向otp区域1写入数据==========
[2025-11-24 17:08:21.760][000000000.953] I/user.OTP 写入成功 1234
[2025-11-24 17:08:21.765][000000000.953] I/user.=========读取otp区域1数据==========
[2025-11-24 17:08:21.772][000000000.954] I/user.读取4字节数据 1234 string
[2025-11-24 17:08:21.777][000000000.954] I/user.读取8字节数据 1234 string
[2025-11-24 17:08:21.861][000000001.119] I/user.退出飞行模式 false
[2025-11-24 17:08:26.285][000000005.485] D/mobile cid1, state0
[2025-11-24 17:08:26.289][000000005.486] D/mobile bearer act 0, result 0
[2025-11-24 17:08:26.293][000000005.487] D/mobile NETIF_LINK_ON -> IP_READY
[2025-11-24 17:08:26.296][000000005.515] D/mobile TIME_SYNC 0
- luatools 页面显示如下:

七、总结
本文档主要介绍 4G 通信中 otp 的应用。
结合 demo 例程讲解了 otp 基本原理,介绍了 otp 主要 API,旨在最简单的快速上手 Air780EHV 的 LuatOS 的 otp 开发.