源码说明
源代码位于 bsp/artinchip/
:
bsp/artinchip/drv/tsen/drv_tsen.c,TSenor Driver 层实现
bsp/artinchip/hal/tsen/hal_tsen.c,TSenor HAL 层实现
bsp/artinchip/include/hal/hal_tsen.h,TSenor HAL 层接口头文件
模块架构
TSensor 驱动 Driver 层采用 RT-Thread 的Sensor设备驱动框架,如果只使用HAL层也可以支持 Baremetal 方式的应用场景。
关键流程设计
初始化流程
TSensor 驱动的初始化接口通过 INIT_DEVICE_EXPORT(drv_tsen_init)
完成,会通过调用 Sensor子系统的接口 rt_hw_sensor_register() 注册一个 Sensor设备。
TSensor 控制器的初始化过程,主要步骤有:
初始化模块的clk
注册中断
初始化默认参数
向设备框架中注册Sensor设备
中断处理流程
TSensor 支持使用中断方式来读取数据,这样避免应用层的忙等待。
对于非周期模式:当用户层触发 ops->fetch_data() 接口,就会启动一次硬件去读数据
当硬件准备好数据,会产生一个中断
在中断处理函数中,用INT Flag来区分是哪个通道有数据,逐个通道扫描将数据读出,会缓存到一个全局变量中
对于周期模式: TSensor 控制器会自动按给定周期产生一次数据中断
数据结构设计
struct aic_tsen_dev
属于 Driver 层内部使用的数据结构,管理TSensor控制器的设备资源:
struct aic_tsen_dev {
struct rt_sensor_device dev;
u32 pclk_rate;
struct aic_tsen_ch *ch;
};
2
3
4
5
struct aic_tsen_ch
属于 HAL 层接口,管理一个 TSensor 通道的配置信息:
struct aic_tsen_ch {
int id;
bool available;
char name[16];
enum aic_tsen_mode mode;
enum aic_tsen_soft_mode soft_mode;
bool diff_mode;
bool inverted;
u16 latest_data; // 10 * actual temperature value
u16 smp_period; // in seconds
bool hta_enable; // high temperature alarm
u16 hta_thd; // 10 * temperature value
u16 hta_rm_thd; // 10 * temperature value
bool lta_enable; // low temperature alarm
u16 lta_thd; // 10 * temperature value
u16 lta_rm_thd; // 10 * temperature value
bool otp_enable; // over temperature protection
u16 otp_thd; // 10 * temperature value
int slope; // 10000 * actual slope
int offset; // 10000 * actual offset
aicos_sem_t complete;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Driver 层接口设计
以下接口是 TSensor 设备驱动框架的标准接口。
struct rt_sensor_ops
{
rt_size_t (*fetch_data)(struct rt_sensor_device *sensor, void *buf, rt_size_t len);
rt_err_t (*control)(struct rt_sensor_device *sensor, int cmd, void *arg);
};
2
3
4
5
aic_tsen_fetch
函数原型 | rt_size_t aic_tsen_fetch(struct rt_sensor_device* sensor, void* buf, rt_size_t len) |
---|---|
功能说明 | 读取TSensor温度数据 |
参数定义 | sensor - 指向sensor设备的指针 buf - 用来保存读取到的温度, 是struct rt_sensor_data类型的数据结构 len - buf的长度 |
返回值 | 1, 成功; <0, 失败 |
注意事项 | 目前仅支持读取CPU位置处的TSensor |
aic_tsen_control
函数原型 | rt_err_t aic_tsen_control(struct rt_sensor_device* sensor, int cmd, void* args) |
---|---|
功能说明 | TSensor驱动的ioctl接口 |
参数定义 | sensor - 指向sensor设备的指针 cmd - ioctl命令码 args - ioctl命令相应的参数 |
返回值 | -1, 失败 |
注意事项 | 目前暂未实现此接口中的ioctl命令, 所以统一返回-1。不影响正常读数据功能 |
HAL 层接口设计
HAL 层的函数接口声明存放在 hal_tsen.h 中,主要接口有:
void hal_tsen_enable(int enable);
void hal_tsen_ch_enable(u32 ch, int enable);
int hal_tsen_ch_init(struct aic_tsen_ch *chan, u32 pclk);
int hal_tsen_get_temp(struct aic_tsen_ch *chan, s32 *val);
s32 hal_tsen_data2temp(struct aic_tsen_ch *chan);
u16 hal_tsen_temp2data(struct aic_tsen_ch *chan, s32 temp);
void hal_tsen_status_show(struct aic_tsen_ch *chan);
irqreturn_t hal_tsen_irq_handle(int irq, void *arg);
2
3
4
5
6
7
8
9
10
Demo
此Demo是 sensor_polling
命令的部分代码(详见kernel/rt-thread/components/drivers/sensors/sensor_cmd.c),可以作为 TSensor设备的使用参考:
static void sensor_polling(int argc, char **argv)
{
rt_uint16_t num = 10;
rt_device_t dev = RT_NULL;
rt_sensor_t sensor;
struct rt_sensor_data data;
rt_size_t res, i;
rt_int32_t delay;
rt_err_t result;
dev = rt_device_find(argv[1]);
if (dev == RT_NULL)
{
LOG_E("Can't find device:%s", argv[1]);
return;
}
if (argc > 2)
num = atoi(argv[2]);
sensor = (rt_sensor_t)dev;
delay = sensor->info.period_min > 100 ? sensor->info.period_min : 100;
for (i = 0; i < num; i++)
{
res = rt_device_read(dev, 0, &data, 1);
if (res != 1)
{
LOG_E("read data failed!size is %d", res);
}
else
{
sensor_show_data(i, sensor, &data);
}
rt_thread_mdelay(delay);
}
rt_device_close(dev);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37