欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:MTK

柚子快報激活碼778899分享:MTK

http://yzkb.51969.com/

目錄

一、簡介

二、架構(gòu)介紹

三、sensor driver

一、重要結(jié)構(gòu)體

二、宏定義介紹

三、i2c操作函數(shù)

四、重要組成部分

一、傳感器初始化

二、注冊廣播消息

三、注冊傳感器設(shè)備

四、注冊服務(wù)器

五、數(shù)據(jù)處理

四、sensor manger

一、重要結(jié)構(gòu)體

二、調(diào)用流程

一、RTOS發(fā)送數(shù)據(jù)

二、RTOS接收數(shù)據(jù)

五、kernel

一、簡介

????????MTK Sensor Hub 框架是一個專門用于管理和處理智能手機中各類傳感器數(shù)據(jù)的協(xié)處理器系統(tǒng),旨在提高傳感器數(shù)據(jù)處理效率和降低功耗。

????????在現(xiàn)代智能手機中,傳感器起著至關(guān)重要的作用,它們能夠提供諸如加速度、陀螺儀、磁力、氣壓、濕度、壓力、光照、近程和心率等多種物理數(shù)據(jù)的測量。然而,隨著傳感器數(shù)量和使用頻率的增加,其對電能的消耗也相應(yīng)增加。為了優(yōu)化手機的電源使用效率,谷歌和聯(lián)發(fā)科(MediaTek Inc., MTK)分別開發(fā)了CHRE(Context Hub Runtime Environment)和SCP(Sensor Control Processor),以實現(xiàn)更高效的傳感器控制。

????????MTK Sensor Hub框架的核心是SCP和CHRE。SCP是一種協(xié)處理器,專門用于處理與音頻和傳感器相關(guān)的功能以及其他客制化需求,它采用freeRTOS作為操作系統(tǒng)。而CHRE則是一種事件驅(qū)動的體系結(jié)構(gòu),可以視為一個輕量級、實時性的操作系統(tǒng),其主要職能是處理傳感器相關(guān)的操作。在這種架構(gòu)下,CHRE的應(yīng)用負(fù)責(zé)實現(xiàn)具體的傳感器驅(qū)動程序,包括sensorInfo、sensorOps以及處理event的handler模塊。

????????那么freeRTOS系統(tǒng)怎么與Android系統(tǒng)進(jìn)行通訊呢?首先,我們需要了解SCP和CHRE之間的關(guān)系。CHRE是一個中間件,負(fù)責(zé)管理SCP上的各種服務(wù),包括傳感器、音頻等。CHRE通過IPC(進(jìn)程間通信)與安卓系統(tǒng)進(jìn)行通信。具體來說,CHRE提供了一組API,供安卓系統(tǒng)調(diào)用,以獲取SCP上的服務(wù)。這些API包括打開/關(guān)閉服務(wù)、設(shè)置/獲取服務(wù)參數(shù)等功能。接下來,我們來看freeRTOS如何與安卓系統(tǒng)通信。在SCP上運行的freeRTOS系統(tǒng)中,有一個名為“sensor hub driver”的驅(qū)動程序。這個驅(qū)動程序負(fù)責(zé)將SCP上的傳感器數(shù)據(jù)傳輸?shù)紺HRE。當(dāng)SCP上的傳感器產(chǎn)生數(shù)據(jù)時,sensor hub driver會將這些數(shù)據(jù)封裝成特定的格式,并通過SPI(串行外設(shè)接口)或I2C(兩線式串行總線)等通信協(xié)議發(fā)送給CHRE。CHRE收到這些數(shù)據(jù)后,會對其進(jìn)行解析和處理,然后將處理后的數(shù)據(jù)通過IPC發(fā)送給安卓系統(tǒng)。安卓系統(tǒng)收到這些數(shù)據(jù)后,會根據(jù)需要進(jìn)行進(jìn)一步的處理,例如更新UI界面、觸發(fā)其他應(yīng)用程序等。

二、架構(gòu)介紹

應(yīng)用層:開發(fā)者通過獲取SensorManager服務(wù)并注冊監(jiān)聽器來簡單地調(diào)用傳感器,此后傳感器信息便會通過回調(diào)接口上報。Framework層:該層為開發(fā)者提供了與傳感器交互的抽象接口,實際工作中會獲取SystemSensorManager服務(wù),這是專門為上層注冊接口的類。JNI層:這一層提供了從Java到native代碼的轉(zhuǎn)換,使得java框架能與下層的HAL進(jìn)行交互。HAL層:MTK的HAL層實現(xiàn)了對多個sensor的控制處理,其中HfManager扮演了重要角色,負(fù)責(zé)管理不同sensor的控制流程。內(nèi)核層:此層提供了sensor數(shù)據(jù)流的通道,并與硬件相關(guān)的驅(qū)動緊密相連。SCP/CHRE層:在這一層,所有的sensor driver實現(xiàn)都必須遵循CHRE app的設(shè)計框架,確保統(tǒng)一處理control和data flow

模塊名稱 功能 代碼路徑 hal層列表 hal層申明添加 vendor\mediatek\proprietary\hardware\sensor\2.0\hal\SensorListV2.cpp sensor型號 對應(yīng)sensor下選擇sensor IC型號 vendor\mediatek\proprietary\tinysys\scp\project\RV55_A\chip>\項目>\inc\overlay_sensor.h 算法庫 有些sensor標(biāo)定需要算法支持如地磁 放置路徑:vendor/mediatek/proprietary/tinysys/scp/middleware/sensorhub/algos/RV55_A/calibration 配置編譯范圍 配置編譯范圍 配置路徑:vendor\mediatek\proprietary\tinysys\scp\project\RV55_A\chip>\platform\features\sensorhub.mk(chre.mk) config配置 配置項目是否支持 編譯配置:vendor\mediatek\proprietary\tinysys\scp\project\RV55_A\chip>\項目>\project.mk sensor dts配置 配置sensor總線名稱及地址信息 配置路徑:vendor/mediatek/proprietary/tinysys/scp/project/RV55_A/chip>/項目>/sensordts.c sensor driver sensor 的驅(qū)動代碼,被 sensor hub manage 調(diào)用。 sensorhub3.0架構(gòu):vendor/mediatek/proprietary/tinysys/scp/middleware/sensorhub/drivers/physical sensorhub2.0架構(gòu): vendor/mediatek/proprietary/tinysys/scp/middleware/contexthub/MEMS_Driver

注:使用算法庫時,需要將算法庫路徑添加至sensorhub.mk文件中的LIBFLAGS項。

三、sensor driver

一、重要結(jié)構(gòu)體

struct i2c_regmap {

uint8_t bus_id;

uint8_t addr;

uint8_t *tx_buf;

uint8_t *rx_buf;

size_t len;

uint32_t speed_hz;

};

struct broadcast_receiver {

struct broadcast_handle handle; //操作句柄

void (*receive)(void *, uint8_t, const void *); //回調(diào)函數(shù)用于處理接收的廣播內(nèi)容

void *private_data;

};

//確認(rèn)傳感器的ID

enum OVERLAY_WS {

OVERLAY_WORK_00 = 0,

OVERLAY_WORK_01,

OVERLAY_WORK_02,

OVERLAY_WORK_03,

OVERLAY_WORK_04,

OVERLAY_WORK_05,

OVERLAY_WORK_06,

OVERLAY_WORK_07,

OVERLAY_WORK_08,

OVERLAY_WORK_09,

NUM_OVERLAY_WORK,

/*for sensor start */

/*acceleremter and gyroscope sensor */

OVERLAY_ID_ACCGYRO = OVERLAY_WORK_00,

/*magnetometer sensor */

OVERLAY_ID_MAG = OVERLAY_WORK_01,

/*light and proximity sensor */

OVERLAY_ID_ALSPS = OVERLAY_WORK_02,

/*barometer sensor */

OVERLAY_ID_BARO = OVERLAY_WORK_03,

/*light and proximity sensor secondary */

OVERLAY_ID_ALSPS_SECONDARY = OVERLAY_WORK_04,

/*sar sensor */

OVERLAY_ID_SAR = OVERLAY_WORK_05,

/*cali fusion lib*/

OVERLAY_ID_CALIFUSION = OVERLAY_WORK_06,

/*for sensor end */

};

//確認(rèn)任務(wù)等級

enum broadcast_tasks {

principal,

deputy,

vice,

MAX_BROADCAST_TASK,

};

struct sensor_device {

struct list_t list; //記錄傳感器的信息vendor,喚醒模式,傳感器類型,數(shù)據(jù)上報模式,等

const struct broadcast_receiver *receiver;

const struct sensor_info *support_list;

unsigned int support_size;

struct sensor_manager *manager;

void *private_data;

char *name;

};

//光距感eg:

static const struct sensor_info stk3acx_list[] =

{

{

.sensor_type = SENSOR_TYPE_LIGHT,

.wakeup_mode = NON_WAKEUP_MODE,

.report_mode = ONCHANGE_REPORT_MODE,

.down_sample = NON_DOWN_SAMPLE_MODE,

.name = ALS_NAME,

.vendor = VENDOR_NAME,

},

{

.sensor_type = SENSOR_TYPE_PROXIMITY,

.wakeup_mode = WAKEUP_MODE,

.report_mode = ONCHANGE_REPORT_MODE,

.down_sample = NON_DOWN_SAMPLE_MODE,

.name = PS_NAME,

.vendor = VENDOR_NAME,

},

};

二、宏定義介紹

//根據(jù)傳感器中OVERLAY_DECLARE傳入的參數(shù)分配一段內(nèi)存,

#define OVERLAY_DECLARE_V2(ovl_name, ovl_section, ovl_data, ovl_func) \

void overlay_construct_##ovl_name(void) __attribute__((section(".overlay_construct"))); \

struct overlay_init_s overlay_init_##ovl_name __attribute__((section(".overlay_init"))) = { \

.overlay_section = ovl_section, \

.construct = overlay_construct_##ovl_name, \

.data = (void *)ovl_data, \

.func = (void *)ovl_func, \

}; \

void overlay_construct_##ovl_name(void) { \

extern char __load_start_##ovl_name; \

extern char __load_stop_##ovl_name; \

extern struct overlay_init_s overlay_init_##ovl_name; \

overlay_init_##ovl_name.name = #ovl_name; \

overlay_init_##ovl_name.overlay_load_start = &__load_start_##ovl_name; \

overlay_init_##ovl_name.overlay_load_end = &__load_stop_##ovl_name; \

}

#define GET_OVERLAY_DECLARE_MACRO(_1, _2, _3, _4, NAME, ...) NAME

#define OVERLAY_DECLARE(...) GET_OVERLAY_DECLARE_MACRO(__VA_ARGS__, OVERLAY_DECLARE_V2, OVERLAY_DECLARE_V1)(__VA_ARGS__)

//eg:

OVERLAY_DECLARE(mmc5603, OVERLAY_ID_MAG, deputy, init_mmc5603);

三、i2c操作函數(shù)

使用regmap機制來管理I2C\SPI,將I2C, SPI驅(qū)動做了一次重構(gòu),把I/O讀寫的重復(fù)邏輯在regmap中實現(xiàn)。

//根據(jù)設(shè)備樹信息獲取i2c設(shè)備地址,總線編號,傳輸速度等注冊regmap

int i2c_regmap_request(struct i2c_regmap *regmap);

//regmap寫操作

int i2c_regmap_write(struct i2c_regmap *regmap, uint8_t reg, uint8_t data);

//regmap讀操作

int i2c_regmap_read(struct i2c_regmap *regmap, uint8_t reg, size_t len, uint8_t **buf);

四、重要組成部分

一、傳感器初始化

OVERLAY_DECLARE(****, OVERLAY_ID_MAG, deputy, init_****); //注冊傳感器,參數(shù):傳感器名稱,傳感器類型,task等級,回調(diào)函數(shù)

int init_****(uint8_t task, uint8_t id); //會穿task句柄,ID用于注冊廣播接收

二、注冊廣播消息

//注冊廣播接收,broadcast_receiver結(jié)構(gòu)體中包含回調(diào)函數(shù)(用于處理sensor manger發(fā)送的消息),傳感器初始化傳入的task,ID,私有數(shù)據(jù)

int broadcast_receiver_register(const struct broadcast_receiver *br) //注冊廣播接收

{

broadcast_set_handle(&br->handle);

return 0;

}

三、注冊傳感器設(shè)備

//注冊傳感器設(shè)備,sensor_device中包含設(shè)備信息,如:傳感器類型,數(shù)據(jù)上傳方式,是否喚醒cpu等,詳見sensor_device->sensor_info數(shù)組

//并將傳入broadcast_receiver放置sensor_device結(jié)構(gòu)體中,關(guān)聯(lián)在一起

int sensor_device_register(struct sensor_device *dev, const struct broadcast_receiver *receiver);

四、注冊服務(wù)器

int sensor_client_register(struct sensor_client *client, const struct broadcast_receiver *receiver)

五、數(shù)據(jù)處理

在注冊廣播消息時,注冊了回調(diào)函數(shù),將接收到符合傳感器類型的消息時,將會調(diào)用。根據(jù)不同的事件類型調(diào)用不同的函數(shù),示例如下

tatic void mxc4005_receive(void *private_data, uint8_t event_type, const void *event_data)

{

const struct sensor_control *control = event_data;

const struct sensor_bytestream *bstr = event_data;

struct mxc4005_device *dev = private_data;

switch (event_type) {

case EVENT_SAMPLE://193

mxc4005_sample(dev);

break;

case EVENT_ENABLE://9

mxc4005_enable(dev, control);

break;

case EVENT_DISABLE://8

mxc4005_disable(dev);

break;

case EVENT_FLUSH://10

mxc4005_flush(dev);

break;

case EVENT_ENABLE_RAW://15

mxc4005_raw(dev, true);

break;

case EVENT_DISABLE_RAW://16

mxc4005_raw(dev, false);

break;

case EVENT_CONFIG://12

mxc4005_config(dev, bstr);

break;

case EVENT_CALI://11

mxc4005_cali(dev);

break;

case EVENT_DEBUG:

logi("debug\n");

break;

case EVENT_READY:

logi("ready\n");

break;

}

}

在通過regmap讀取到傳感器詳細(xì)信息后調(diào)用sensor_single_data_alloc申請地址,在將數(shù)據(jù)拷貝到這個地址中,最后調(diào)用sensor_broadcast函數(shù)。

struct sensor_single_data * sensor_single_data_alloc(uint8_t sensor_type);

//eg: dbuf = sensor_single_data_alloc(SENSOR_TYPE_ACCELEROMETER);

//數(shù)據(jù)拷貝 memcpy(dbuf->data[0].ivalue, ivalue, len);

int sensor_broadcast(uint8_t event_type, void *event_data, void (*free_func)(uint8_t, void *));

//eg: sensor_broadcast(EVENT_CALI_DATA, dbuf, sensor_single_data_free);

四、sensor manger

一、重要結(jié)構(gòu)體

struct sensor_core {

spinlock_t client_lock;

struct list_t client_list[MAX_BROADCAST_TASK];

spinlock_t state_lock;

struct sensor_state state[MAX_SENSOR_TYPE];

spinlock_t manager_lock; // lock for another task find manager

struct sensor_manager *manager_list[MAX_SENSOR_TYPE];

struct list_t device_list; //存放注冊的設(shè)備信息

};

struct sensor_manager {

const struct sensor_device *dev;

struct sensor_core *core;

};

struct sensor_device {

struct list_t list;

const struct broadcast_receiver *receiver; //調(diào)用sensor_device_register是放置receiver,存放操作句柄ID等

const struct sensor_info *support_list;

unsigned int support_size;

struct sensor_manager *manager; //調(diào)用sensor_device_register時,申請空間,manager->dev,指向sensor_device

void *private_data;

char *name;

};

struct sensor_client {

struct list_t list;

const struct broadcast_receiver *receiver;

spinlock_t request_lock;

struct sensor_state request[MAX_SENSOR_TYPE];

struct sensor_core *core;

char *name;

};

二、調(diào)用流程

mtk對sensor數(shù)據(jù)的采集采用freeRTOS作為操作系統(tǒng)。

文件路徑:vendor\mediatek\proprietary\tinysys\scp\project\RV55_A\mt6789\platform\src\main.c

int main(void)

{

........

#ifdef CFG_SENSORHUB_SUPPORT

sensorhub_init();

#endif

........

}

文件路徑:vendor\mediatek\proprietary\tinysys\scp\middleware\sensorhub\core\init.c

void sensorhub_init(void)

{

sensorhub_percluster_init(); //注冊IPC接口用于freeRTOS與AP通信

sensorhub_main_init(); //注冊sensorhub相關(guān)

sensorhub_secondary_init(); //

}

static void sensorhub_main_init(void)

{

if (LOCAL_CLUSTER_ID() == 0) {

if (LOCAL_CPU_ID() == 0) {

sensor_comm_init(); //創(chuàng)建鏈表,創(chuàng)建任務(wù),初始化鎖,注冊一些通知鏈

scp_ready_init(); //創(chuàng)建通知鏈?zhǔn)褂迷硬僮鱽硗ㄖ芾?/p>

sensor_list_init(); //注冊一些鏈表的通知函數(shù)

broadcast_init(); //注冊廣播

sensor_manager_init(); //重點函數(shù)

rpc_init();

dts_init();

ipc_external_init();

module_core_init();

timesync_init();

host_suspend_init();

custom_cmd_init();

power_manager_init();

}

}

}

文件路徑:vendor\mediatek\proprietary\tinysys\scp\middleware\sensorhub\core\sensor_manager.c

void sensor_manager_init(void)

{

fatal(MAX_SENSOR_EVENT <= EVENT_SENSOR_END);

init_sensor_core(&sens_core); //初始化隊列,此隊列用于傳感器加載注冊

broadcast_dispatch_register(SENSOR_HANDLER, sensor_dispatch, NULL); //注冊發(fā)送廣播回調(diào)函數(shù)

broadcast_rescue_register(SENSOR_HANDLER, sensor_rescue, NULL); //注冊接收廣播函數(shù)

broadcast_notifier_register(&sensor_notifier); //注冊廣播通知鏈

sens_mgr_pool = MEM_POOL_INIT(sens_mgr_mem, struct sensor_manager, MAX_SENSOR_MANAGER_NUM);

sens_ctrl_pool = MEM_POOL_INIT(sens_ctrl_mem, struct sensor_control, MAX_SENSOR_CONTROL_NUM);

sens_single_pool = MEM_POOL_INIT(sens_single_mem, struct sensor_single_data, MAX_SENSOR_SINGLE_DATA_NUM);

sens_multi_pool = MEM_POOL_INIT(sens_multi_mem, struct sensor_multi_data, MAX_SENSOR_MULTI_DATA_NUM);

sens_super_single_pool = MEM_POOL_INIT(sens_super_single_mem, struct sensor_super_single_data,

MAX_SENSOR_SUPER_DATA_NUM);

down_sample_init();

debug_file_init();

}

傳感器注冊廣播接收

int broadcast_receiver_register(const struct broadcast_receiver *br) //注冊廣播接收

{

broadcast_set_handle(&br->handle);

return 0;

}

void broadcast_set_handle(const struct broadcast_handle *handle)

{

uint8_t task, id;

fatal(handle); //一個斷言語句,用于檢查變量,如果不成立,程序?qū)伋鲆粋€異常或終止執(zhí)行。這通常用于調(diào)試和驗證代碼的正確性。

task = handle->task;

id = handle->id;

if (task < MAX_BROADCAST_TASK && id < MAX_BROADCAST_HANDLE_NUM) {

if (!bc_handle[task][id])

bc_handle[task][id] = handle;

fatal(bc_handle[task][id] == handle)

}

}

//注冊后會放置這個二維數(shù)組中bc_handle,用于存儲指向broadcast_handle結(jié)構(gòu)體的指針

static const struct broadcast_handle *bc_handle[MAX_BROADCAST_TASK][MAX_BROADCAST_HANDLE_NUM];

注冊device

int sensor_device_register(struct sensor_device *dev, const struct broadcast_receiver *receiver)

{

unsigned int i = 0;

unsigned long flags = 0;

const struct sensor_info *info = NULL;

struct sensor_manager *manager = NULL;

if (!atomic_read(&sens_register_permit) ||

!dev || !receiver || !dev->name ||

!dev->support_list || !dev->support_size)

return -EINVAL;

manager = mem_pool_alloc(sens_mgr_pool);

fatal(manager);

manager->dev = dev; //此處關(guān)聯(lián)了,client,manager,core結(jié)構(gòu)體

manager->core = &sens_core; //static struct sensor_core sens_core;

dev->receiver = receiver;

dev->manager = manager;

list_init(&dev->list);

/* hold manager_lock for another task find manager */

flags = spinlock_lock_irqsave(&manager->core->manager_lock);

for (i = 0; i < dev->support_size; ++i) {

info = &dev->support_list[i];

fatal(info->sensor_type < MAX_SENSOR_TYPE);

fatal(info->name);

fatal(info->vendor);

manager->core->manager_list[info->sensor_type] = manager;

}

list_add_tail(&manager->core->device_list, &dev->list);

spinlock_unlock_irqrestore(&manager->core->manager_lock, flags);

return 0;

}

注冊服務(wù)器

int sensor_client_register(struct sensor_client *client, const struct broadcast_receiver *receiver)

{

uint8_t task = 0;

unsigned long flags = 0;

if (!atomic_read(&sens_register_permit) ||

!client || !receiver || !client->name)

return -EINVAL;

list_init(&client->list);

client->receiver = receiver;

spinlock_init(&client->request_lock);

client->core = &sens_core;

task = receiver->handle.task;

fatal(task < ARRAY_SIZE(client->core->client_list));

flags = spinlock_lock_irqsave(&client->core->client_lock);

list_add_tail(&client->core->client_list[task], &client->list); //講服務(wù)添加至static struct sensor_core sens_core

spinlock_unlock_irqrestore(&client->core->client_lock, flags);

return 0;

}

傳感器會調(diào)用此函數(shù)傳遞數(shù)據(jù)處理。

int sensor_broadcast(uint8_t event_type, void *event_data, void (*free_func)(uint8_t, void *))

{

int ret = 0;

unsigned int i = 0;

unsigned long flags = 0;

bool broadcast = false, has_request = false;

struct sensor_header *header = (struct sensor_header *)event_data;

uint8_t sensor_type = header->sensor_type;

struct sensor_core *core = &sens_core;

struct list_t *curr = NULL, *tmp = NULL;

struct sensor_client *client = NULL;

flags = spinlock_lock_irqsave(&core->client_lock);

for (i = 0; i < ARRAY_SIZE(core->client_list); ++i) {

list_for_each_entry_safe(&core->client_list[i], curr, tmp) {

/*

* NOTE: each loop must reset has_request to false

* if don't reset swtich default branch will send invalid event

*/

has_request = false;

client = list_entry(curr, struct sensor_client, list);

switch (event_type) {

case EVENT_DATA:

has_request = client->request[sensor_type].enable;

break;

case EVENT_FLUSH_DATA:

has_request = client->request[sensor_type].flush > 0;

break;

case EVENT_CALI_DATA:

has_request = client->request[sensor_type].cali;

break;

case EVENT_BIAS_DATA:

has_request = client->request[sensor_type].bias;

break;

case EVENT_TEMP_CALI_DATA:

has_request = client->request[sensor_type].temp;

break;

case EVENT_SELF_TEST_DATA:

has_request = client->request[sensor_type].test;

break;

case EVENT_RAW_DATA:

has_request = client->request[sensor_type].raw;

break;

default:

fatal(NULL);

break;

}

if (has_request) {

/*

* NOTE: must first set and after broadcast_event failed clear.

* if not, event_data will be used after free and system crash.

* task0: task1: task2:

* broadcast_event

* bit_clear_return(free)

*

* bit_set(task1, task2)

* bit_clear_return(crash)

*/

bit_set(&header->task_map, client->receiver->handle.task);

ret = broadcast_event(&client->receiver->handle,

SENSOR_HANDLER, event_type, event_data, free_func, false); //傳遞數(shù)據(jù)

/*

* NOTE: broadcast_event not use failed_auto_free,

* when broadcast_event failed return, we should clear task_map.

*/

if (ret < 0)

bit_clear(&header->task_map, client->receiver->handle.task);

/*

* NOTE: when has_request of client is true in one task,

* we must break list_for_each_entry_safe for others clients in this task,

* if not, event_data will be used after free and system crash.

*/

break;

}

}

}

/* check bit to detect free or not in spinlock */

broadcast = !!bit_read(&header->task_map);

spinlock_unlock_irqrestore(&core->client_lock, flags);

/* no task require data must free event data */

if (!broadcast && free_func && event_data)

free_func(FORCE_FREE, event_data);

/* must return 0 due to multi dispatcher */

return 0;

}

一、RTOS發(fā)送數(shù)據(jù)

sensor根據(jù)接收到書指令發(fā)送AP所需的數(shù)據(jù),會調(diào)用以下函數(shù)

文件路徑:vendor\mediatek\proprietary\tinysys\scp\middleware\sensorhub\core\broadcast.c

int broadcast_event(const struct broadcast_handle *handle,

uint8_t user_type, uint8_t event_type, void *event_data,

void (*free_func)(uint8_t, void *), bool failed_auto_free)

{

unsigned long flags = 0;

struct broadcast_message *bm = NULL;

struct broadcast_task *bt = NULL;

bool need_wakeup = false;

fatal(handle->task < MAX_BROADCAST_TASK &&

handle->id < MAX_BROADCAST_HANDLE_NUM);

if (!atomic_read(&task_ready[handle->task])) {

/* task not ready should free event data */

if (user_type != DEFER_HANDLER &&

failed_auto_free && free_func && event_data)

free_func(handle->task, event_data);

loge("%u %u to %u fail %d\n", user_type, event_type, handle->task, -ENODEV);

return -ENODEV;

}

bm = mem_pool_alloc(msg_pool);

if (!bm) {

/* can't alloc should free event data */

if (user_type != DEFER_HANDLER &&

failed_auto_free && free_func && event_data)

free_func(handle->task, event_data);

loge("%u %u to %u fail %d\n", user_type, event_type, handle->task, -ENOMEM);

return -ENOMEM;

}

list_init(&bm->list);

bm->user_type = user_type;

bm->event_type = event_type;

bm->task = handle->task;

bm->id = handle->id;

bm->event_data = event_data;

bm->free_func = free_func;

if (is_in_isr())

bm->task_wakeup = xTaskGetTickCountFromISR();

else

bm->task_wakeup = xTaskGetTickCount();

bt = &bc_task[handle->task];

flags = spinlock_lock_irqsave(&bt->lock);

need_wakeup = !bt->event_running;

list_add_tail(&bt->bm_head, &bm->list); //它將事件信息封裝成消息并將其添加到相應(yīng)任務(wù)的消息隊列中。

spinlock_unlock_irqrestore(&bt->lock, flags);

if (need_wakeup) //如果任務(wù)當(dāng)前沒有運行事件,函數(shù)會喚醒任務(wù)以處理新的消息。

broadcast_wakeup(handle->task); //果需要喚醒任務(wù),則調(diào)用 broadcast_wakeup

return 0;

}

static inline void broadcast_wakeup(uint8_t task)

{

BaseType_t xTaskWoken = pdFALSE;

if (is_in_isr()) { //檢查當(dāng)前是否處于中斷服務(wù)程序(ISR)中。

xTaskWoken = pdFALSE;

vTaskNotifyGiveFromISR(bc_task_handle[task], &xTaskWoken); //指定的任務(wù)發(fā)送通知

portYIELD_FROM_ISR(xTaskWoken); //讓出CPU控制權(quán),以便其他任務(wù)有機會運行。

} else {

if (xTaskNotifyGive(bc_task_handle[task]) == pdFAIL)

loge("wakeup %u %s fail\n", task, pcTaskGetName(bc_task_handle[task]));

}

}

文件路徑:vendor/mediatek/proprietary/tinysys/freertos/source/kernel/FreeRTOS/Source/tasks.c

void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )

二、RTOS接收數(shù)據(jù)

以下函數(shù)用于接受IPC發(fā)送的數(shù)據(jù)

//broadcast_init初始化時會調(diào)用此函數(shù),創(chuàng)建任務(wù)

static void deputy_init(void)

{

fatal(xTaskCreate(deputy_task, "DEPUTY", 1024, NULL, DEPUTY_PRI, NULL));

}

static void deputy_task(void *pvParameters)

{

task_run(deputy, deputy_task_run);

}

static void task_run(uint8_t task, void (*second_run)(uint8_t))

{

fatal(task < MAX_BROADCAST_TASK);

wait_host_ready(task);

list_init(&bc_task[task].bm_head);

list_init(&bc_task[task].br_head);

spinlock_init(&bc_task[task].lock);

bc_task_handle[task] = xTaskGetCurrentTaskHandle();

module_level_init(task);

second_run(task);

}

static void deputy_task_run(uint8_t local)

{

set_task_ready(local);

/* there overlay init and register to deputy_driver list */

while (1) {

receive_event(local);

if (!ulTaskNotifyTake(pdTRUE, portMAX_DELAY))

loge("task %u wait fail\n", local);

}

}

static int receive_event(uint8_t task)

{

unsigned long flags = 0;

struct broadcast_task *bt = NULL;

struct broadcast_message *bm = NULL;

uint32_t event_exe = 0;

fatal(task < MAX_BROADCAST_TASK);

task_running[task] = xTaskGetTickCount();

bt = &bc_task[task];

flags = spinlock_lock_irqsave(&bt->lock);

bt->event_running = true;

while (!list_empty(&bt->bm_head)) {

bm = list_first_entry(&bt->bm_head, struct broadcast_message, list);

list_delete(&bm->list);

spinlock_unlock_irqrestore(&bt->lock, flags);

event_start[task] = xTaskGetTickCount();

dispatch_to(task, bm); //重點函數(shù)

event_end[task] = xTaskGetTickCount();

event_exe = event_end[task] - event_start[task];

if (event_exe > 10 / portTICK_RATE_MS /* ms */) {

logi("id %u user_type %u event_type %u execute %ums\n",

bm->id, bm->user_type, bm->event_type, event_exe);

//if (bm->event_type != EVENT_SELF_TEST)

//fatal(event_exe < 200 / portTICK_RATE_MS /* ms */);

}

/* must first free event_data */

if (bm->user_type != DEFER_HANDLER && bm->free_func && bm->event_data)

bm->free_func(task, bm->event_data);

/* free broadcast message */

mem_pool_free(msg_pool, bm);

flags = spinlock_lock_irqsave(&bt->lock);

}

bt->event_running = false;

spinlock_unlock_irqrestore(&bt->lock, flags);

task_idle[task] = xTaskGetTickCount();

return 0;

}

static void dispatch_to(uint8_t task, struct broadcast_message *bm)

{

uint8_t user_type = bm->user_type;

struct broadcast_dispatch *bcd = NULL;

fatal(task < MAX_BROADCAST_TASK);

fatal(user_type < MAX_BROADCAST_USER);

fatal(bm->task == task);

fatal(bm->id < MAX_BROADCAST_HANDLE_NUM);

bcd = &bc_dispatch[user_type];

if (bcd->dispatch)

bcd->dispatch(task, bm, bcd->private_data); //調(diào)用這個函數(shù)指針

}

int broadcast_dispatch_register(uint8_t index,

int (*f)(uint8_t, const struct broadcast_message *, void *), void *private_data)

{

if (index >= MAX_BROADCAST_USER)

return -EINVAL;

bc_dispatch[index].private_data = private_data;

bc_dispatch[index].dispatch = f; //調(diào)用此函數(shù)對函數(shù)指針賦值

return 0;

}

//在broadcast_init時調(diào)用broadcast_dispatch_register注冊廣播

void broadcast_init(void)

{

.........

broadcast_dispatch_register(PUBLIC_HANDLER, public_dispatch, NULL);

broadcast_dispatch_register(PRIVATE_HANDLER, private_dispatch, NULL);

broadcast_dispatch_register(DEFER_HANDLER, defer_dispatch, NULL);

broadcast_rescue_register(PUBLIC_HANDLER, public_rescue, NULL);

broadcast_rescue_register(PRIVATE_HANDLER, private_rescue, NULL);

broadcast_rescue_register(DEFER_HANDLER, defer_rescue, NULL);

...........

}

static int public_dispatch(uint8_t task, const struct broadcast_message *bm, void *private_data)

{

uint8_t id = 0, i = 0;

const struct broadcast_handle *handle = NULL;

const struct broadcast_receiver *br = NULL;

uint32_t modules = 0;

fatal(bm->user_type == PUBLIC_HANDLER);

fatal(bm->event_type > EVENT_PUBLIC && bm->event_type < EVENT_PRIVATE);

modules = module_get_modules(task);

for (id = 0, i = 0; id < MAX_BROADCAST_HANDLE_NUM && i < modules; ++id, ++i) {

handle = bc_handle[task][id]; //bc_handle是broadcast_receiver_register函數(shù)注冊用于存放的數(shù)組,根據(jù)task ID信息獲得句柄

if (!handle)

continue;

br = list_entry(handle, struct broadcast_receiver, handle); //用于遍歷鏈表并獲取指向特定元素的指針

br->receive(br->private_data, bm->event_type, bm->event_data); //根據(jù)句柄信息找到broadcast_receiver_register注冊時的回調(diào)函數(shù)。

}

return 0;

}

五、kernel

文件路徑:alps\kernel-5.10\drivers\misc\mediatek\sensor\2.0\sensorhub\transceiver.c

注:當(dāng)配置CONFIG_MTK_SENSOR_ARCHITECTURE=2.0時,mt8797 才能支持SCP側(cè)的sensorhub

//入口函數(shù)

module_init(transceiver_init);

static int __init transceiver_init(void)

{

int ret = 0;

struct transceiver_device *dev = &transceiver_dev;

...................

memset(&dev->hf_dev, 0, sizeof(dev->hf_dev));

dev->hf_dev.dev_name = "transceiver";

dev->hf_dev.device_poll = HF_DEVICE_IO_INTERRUPT;

dev->hf_dev.device_bus = HF_DEVICE_IO_ASYNC;

dev->hf_dev.support_list = dev->support_list;

dev->hf_dev.support_size = dev->support_size;

dev->hf_dev.enable = transceiver_enable;

dev->hf_dev.batch = transceiver_batch;

dev->hf_dev.flush = transceiver_flush;

dev->hf_dev.calibration = transceiver_calibration;

dev->hf_dev.config_cali = transceiver_config;

dev->hf_dev.selftest = transceiver_selftest;

dev->hf_dev.rawdata = transceiver_rawdata;

dev->hf_dev.debug = transceiver_debug;

dev->hf_dev.custom_cmd = transceiver_custom_cmd;

dev->hf_dev.private_data = dev;

ret = hf_device_register(&dev->hf_dev); //重點函數(shù),注冊一個用于發(fā)送的數(shù)據(jù)的設(shè)備

..........

}

//傳輸原始數(shù)據(jù)

static int transceiver_rawdata(struct hf_device *hf_dev,

int sensor_type, int en)

{

int ret = 0;

if (en)

ret = transceiver_comm_with(sensor_type,

SENS_COMM_CTRL_ENABLE_RAW_CMD, NULL, 0);

else

ret = transceiver_comm_with(sensor_type,

SENS_COMM_CTRL_DISABLE_RAW_CMD, NULL, 0);

return ret;

}

static int transceiver_comm_with(int sensor_type, int cmd,

void *data, uint8_t length)

{

int ret = 0;

struct sensor_comm_ctrl *ctrl = NULL;

uint32_t ctrl_size = 0;

ctrl_size = ipi_comm_size(sizeof(*ctrl) + length);

ctrl = kzalloc(ctrl_size, GFP_KERNEL); //申請指定的空間用

ctrl->sensor_type = sensor_type;

ctrl->command = cmd;

ctrl->length = length;

if (length)

memcpy(ctrl->data, data, length);

ret = sensor_comm_ctrl_send(ctrl, ctrl_size);

kfree(ctrl);

return ret;

}

int sensor_comm_ctrl_send(struct sensor_comm_ctrl *ctrl, unsigned int size)

{

int retry = 0, ret = 0;

const int max_retry = 10;

const int64_t timeout = 10000000000LL;

int64_t start_time = 0, duration = 0;

start_time = ktime_get_boottime_ns();

if (!READ_ONCE(scp_status)) {

pr_err_ratelimited("dropped comm %u %u\n",

ctrl->sensor_type, ctrl->command);

return 0;

}

do {

ret = sensor_comm_ctrl_seq_send(ctrl, size); //發(fā)送命令需要

} while (retry++ < max_retry && ret < 0);

duration = ktime_get_boottime_ns() - start_time;

if (duration > timeout)

pr_notice("running time %lld, type %u, cmd %u, retries %d\n",

duration, ctrl->sensor_type, ctrl->command, retry);

return ret;

}

柚子快報激活碼778899分享:MTK

http://yzkb.51969.com/

好文閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19533627.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄