OTP学习

//TODO高通部分的介绍参考网上某篇模块,找到后会在这里加上引用

1、名词解释

1.1 OTP

Camera Module一般会采取两种方式来记录该Sensor的一些信息

1、OTP:One Time Programmable。

在嵌入式系统中,所有代码和系统数据都被存储在FLASH芯片内部。FLASH芯片可多次擦写,且掉电数据不丢失。为了保护FLASH中的数据,厂商提供OTP寄存器,OTP这个寄存器只可以编写一次,之后不能修改。

2、EEPROM:全称“电可擦除可编程只读存储器”( Electrically Erasable Programmable Read - Only Memory),手机中camera模块的EEPROM主要用来存储OTP数据,用来进行校准,来保持模组一致性。

1.2 OTP数据包括

Module Info:物料ID、日期、镜头、VCM等基本信息

 LSC:lens shading calibration data

 AWB:R、Gr、Gb、B的通道值或比值

 AF:远、近焦的position对应DAC值

PDAF:SPC和DCC的data

1.3 Platform OTP

    Sensor没有OTP自校准功能,需要我们BB端进行校正。从存储空间(外挂eeprom或者sensor内部存储空间)中读出数据,然后将数据送到BB端进行校正

1.4 Sensor OTP

    Sensor有OTP自校准功能, 从存储空间(外挂eeprom或者sensor内部存储空间)中读出数据,然后写回sensor寄存器,送到BB端的Raw Data是已经校准过的数据

2、OTP存储方式

Sensor:在sensor芯片中ROM,和sensor公用I2C bus和read/write id

OTP数据烧录在sensor的寄存器中。 这种方案省钱,不需要额外的存储器件,但是存储空间小,如果需要烧录的数据量过大,就不适用。

Sensor:sensor外挂的EEPROM,和sensor公用I2C bus,但具有不同的read/write id

该方案优势是存储空间大,如果数据量过多,就需要这种方案,缺点是多一个独立的EEPROM存储器件。

3、OTP作用

       OTP是用来给camera sensor做calibration(校准)用的。 因为模组生产出来会有很大的差异性,为了保证效果一致性, 模组厂会挑选一部分模组作为golden,然后将其他模组的相应参数校准到和这些golden一样, (golden不是最好的模组,也不是最差的模组,而是各方面最平均的模组)

4、代码实现

    4.1 MTK代码

     4.1.1 Platform OTP

 如果是MTK平台,首先需要读文档:MT6779_OTP_Porting_Guide.pdf

Using eeprom_drive.c, cam_cal_list.c as OTP adapter

Kernel modification

/Kernel-4.9/arch/arm64/boot/dts/mediatek/cust_tb8768_camera.dtsi

/kernel-4.9/drivers/misc/mediate/dws/mediatek/mt6765/tp8768tp1_64_bsp.dws

/Kernel-4.9/arch/arm64/configs/achilles6_prc_wifi_defconfig

/Kernel-4.9/arch/arm64/configs/ achilles6_prc_wifi_debug_defconfig

/kernel-4.9/drivers/misc/mediatek/cam_cal/src/common/v1/eeprom_drive.c

/kernel-4.9/drivers/misc/mediatek/cam_cal/src/mk6765/cam_cal_list.c

 

Hal modification

/vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/camera_calibration_cam_cal.cpp

Platform OTP 框架

Step1check dtsi and defconfig

/kernel-4.9/drivers/misc/mediate/dws/mediatek/mt6765/tp8768tp1_64_bsp.dws

配置main/sub eeprom地址,不能配置一样就行避免冲突(但实际上这块配置在不同CHANNEL,不会有冲突)。这块有工具配置(dws 工具路径:

./vendor/mediatek/proprietary/scripts/dct/DrvGen.exe

        

  

通过上述截图可以发现,CAMERA_MAIN_EEPROM、CAMERA_SUB_EEPROM的通讯地址分别是0x50、0x52。对应生成cust.dtsi文件

cust.dtsi在对camera的配置

文件路径:

/out/target/product/tb8768tp1_64_bsp/obj/KERNEL_OBJ/arch/arm/boot/dts/ tb8768tp1_64_bsp /cust.dtsi

代码中想要成功调用到对应的 eeprom_hw_i2c_probe() 和eeprom_hw_i2c_probe2() 函数需要分别匹配上 cust.dtsi 文件中的 compatible 节点 “mediatek,camera_main_eeprom” 和 "mediatek,camera_sub_ eeprom "

 

配置defconfig 文件

/Kernel-4.9/arch/arm64/configs/achilles6_prc_wifi_defconfig

/Kernel-4.9/arch/arm64/configs/ achilles6_prc_wifi_debug_defconfig

 

Step2OTP Adapter

/kernel-4.9/drivers/misc/mediatek/cam_cal/src/mk6765/cam_cal_list.c

 

Step3:OTP Hal

NULL表示不支持OTP,否则表示支持

/vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/sensor_list.cpp

 

/vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/camera_calibration_cam_cal.cpp   默认sensor流程

/vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/camera_calibration_cam_cal_ov13b10.cpp       特定sensor

 

 

DoCamCal2Again()其他的函数和DoCamCalSingleLsc()实现很相似

 

配置像素ID:如果要进行Isc校准,需要在camera_isp_isc_xxxmipirow .h中配置像素id与模块厂商确定烧成OTP的第一个像素,然后修改vendor/mediatek/proprietary /custom / mt6765/hal/ imgsensor / xxx_mipi_raw/ camera_isp_Isc_xxxmipiraw.h

SensorGoldenCalTable{ //SensorGoldenCalTable

pixId: 3, //0,1,2,3: B, Gb, Gr,R

SlimLscType: 0

 Width:0

}

 

OTP Read Flow

     4.1.2 Sensor OTP

       Sensor OTP代码和Platform OTP代码类似,在custom_camera_msdk.cpp中GetCameraCalData()函数来区分走默认函数CAM_CALGetCalData(),就是sensor OTP。Sensor

1、这块可以修改rg bg的值,刷版本看预览是否偏色,来看OTP是否正常(偏色)应用

2、这一抓kernel log来看OTP数据,是否正常。这块可以联系模组厂fae看OTP数据是否正常。

  adb reboot

  adb root

  adb shell dmesg > D:\log\kernel.txt

sensor OTP的函数 》sensor型号_read_data_kernel《,获取有差异,但是大同小异。这里讲一个不一样的,万一找不到,从datasheet中找出OTP的寄存器,然后在驱动代码中搜寄存器就找到了;platform OTP可以根据camera_custom_msdk.cpp中GetCameraCalData()函数来看走那个函数来分析。

    4.2.高通代码

4.2.1.kernel层

(1)eeprom初始化

./kernel/msm-4.14/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c

 

函数主要是实现了两个功能:

  • 通过platform_driver_register函数注册平台驱动(有match device和driver的动作)(msm_eeprom_platform_driver)
  • 将msm_eeprom_i2c_driver挂载i2c总线上

(2)match驱动和设备
这之后,就会根据名称匹配驱动driver和设备device

./kernel/msm-4.14/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c

 

./kernel/msm-4.14/arch/arm/boot/dts/qcom/sm8150-camera-sensor-qrd.dtsi(//举个例子)

 

在dtsi中是设备的定义

平台 + 驱动 + 设备

 

**compatible = “qcom,eeprom”**和 .driver = {.name = “qcom,eeprom”,匹配上了,
系统就去调用probe函数probe = msm_eeprom_i2c_probe

 

 

(3)match成功,调用probe

./kernel/msm-4.14/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c

     

 

这个函数主要工作:

  • msm_eeprom_get_dt_data(e_ctrl);读取dtsi配置的上电时序配置/
  • msm_eeprom_parse_memory_map用于解析以下节点

  • msm_camera_power_up上电
  • read_eeprom_memory读取OTP数据
  • msm_camera_power_down下电

说白了,前面无非就是去读取dtsi的配置,进行上电,然后读取OTP数据下电
这就是整个probe函数的流程!

 

 

(4)读取OTP数据:read_eeprom_memory

 
qcom,page0 =
= <
有效值 地址 地址类型 数据 数据类型 延迟>

qcom,page7 = <1 0x3d81 2 0x01 1 10>;/*往0x3d81写入0x01:把OTP数据加载到buffer中 */

        qcom,pageen7 = <0 0x0 0 0x0 0 0>;

        qcom,poll7 = <0 0x0 0 0x0 0 0>;

        qcom,mem7 = <256 0x7010 2 0 1 1>;/*从0x7010开始读取256个数据*/

 

4.2.2.User层

在kernel层,数据最后被保存到memptr指向的地址里

vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/eeprom/eeprom.c

用户态通过ioctl下到内核,我们看下内核的接受者函数

./kernel/msm-4.14/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c

Copy_to_user中将cal_data.mapdata的num_bytes个数据放到cfg.read_data.dbuffer

 

 

  • 22
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Secure OTP(One-Time Password)是一种用于身份验证的安全机制。它基于密码学算法生成一次性密码,用于在用户登录或进行敏感操作时进行验证。Secure OTP可以提供更高的安全性,因为每个密码只能使用一次,有效期很短,并且密码是动态生成的,不容易被猜测或重复使用。 以下是一个使用HMAC-SHA算法生成Secure OTP的Python示例代码[^1]: ```python import hmac import hashlib import time def generate_otp(secret_key): counter = int(time.time() / 30) # 每30秒生成一个新的密码 counter_bytes = counter.to_bytes(8, byteorder='big') # 将计数器转换为字节数组 hmac_digest = hmac.new(secret_key, counter_bytes, hashlib.sha1).digest() # 使用HMAC-SHA1算法生成摘要 offset = hmac_digest[-1] & 0x0F # 获取摘要的最后一个字节的低4位作为偏移量 otp = (hmac_digest[offset] & 0x7F) << 24 | (hmac_digest[offset + 1] & 0xFF) << 16 | \ (hmac_digest[offset + 2] & 0xFF) << 8 | (hmac_digest[offset + 3] & 0xFF) # 将4个字节的值转换为整数 otp = otp % 10 ** 6 # 将整数限制在6位数范围内 return str(otp).zfill(6) # 将密码补齐为6位数 # 使用示例 secret_key = b'secret_key' # 密钥,可以是任意字节串 otp = generate_otp(secret_key) print("Secure OTP:", otp) ``` 这段代码使用了HMAC-SHA1算法生成摘要,并从摘要中提取了一个6位数的密码。每30秒生成一个新的密码,以确保安全性。你可以根据需要调整计数器的时间间隔和密码的位数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值