sensor 上电过程

2023年08月14日17:17:44 更新
以 i2c 举例

void xxx_start_hw_detect_sequence(sns_sensor *const this)
{
    /**-----------------Register and Open COM Port-------------------------*/
    if (NULL == state->common.com_port_info.port_handle)
    {
        rv = state->scp_service->api->sns_scp_register_com_port(
                 &state->common.com_port_info.com_config,
                 &state->common.com_port_info.port_handle);

        if (rv == SNS_RC_SUCCESS)
        {
            rv = state->scp_service->api->sns_scp_open(state->common.com_port_info.port_handle);
        }
    }

    /**---------------------Register Power Rails --------------------------*/
    if (sns_suid_lookup_get(&state->common.suid_lookup_data, "timer", NULL)
        && NULL == state->pwr_rail_service
        && rv == SNS_RC_SUCCESS)
    {
        rv = stk3a6x_register_power_rail(this);
        /**---------------------Turn Power Rails ON----------------------------*/
        state->common.rail_config.rail_vote = state->common.registry_rail_on_state;

        if (rv == SNS_RC_SUCCESS)
        {
            rv = state->pwr_rail_service->api->sns_vote_power_rail_update(state->pwr_rail_service,
                    this,
                    &state->common.rail_config,
                    NULL);
        }

        /**-------------Create a Timer stream for Power Rail ON timeout.---------*/
        if (rv == SNS_RC_SUCCESS)
        {
            stk3a6x_start_power_rail_timer(this,
                                           sns_convert_ns_to_ticks(STK3A6X_OFF_TO_IDLE_MS * 1000 * 1000),
                                           STK3A6X_POWER_RAIL_PENDING_INIT);
        }
    }
}

1:注册 COM Port
sns_scp_register_com_port
函数路径:
sns_sync_com_port_service.c

SNS_SECTION(".text.sns") sns_rc sns_scp_register_com_port(sns_com_port_config const *com_config,
                                 sns_sync_com_port_handle **port_handle)
{
 //  已经打开过了,就不在重复打开 
  if(NULL != *port_handle)
  {
    sns_scp_deregister_com_port(port_handle);
  }
 // 分配空间。 
 port_priv_handle = sns_malloc(SNS_HEAP_ISLAND, sizeof(sns_com_port_priv_handle));
//  sensor 驱动传过去的 一些参数.主要是从 registery 读取出来的数据。
  sns_memscpy(&port_priv_handle->com_config,
               sizeof(sns_com_port_config),
               com_config,
               sizeof(sns_com_port_config));
//  只是赋值了 bus_info .其他的后续再来看下 
  port_priv_handle->bus_info.bus_type = com_config->bus_type;
  port_priv_handle->bus_info.power_on = false;
  port_priv_handle->bus_info.opened   = false;
  /** bus_info::bus_config shall be allocated by bus specific
   *  implementation.
   */

  *port_handle = (sns_sync_com_port_handle *)port_priv_handle;

  return SNS_RC_SUCCESS;
}

2: sns_scp_open
port_handle 是第一步分配的内存,并对 bus_type 进行了些赋值

SNS_SECTION(".text.sns") sns_rc sns_scp_open(sns_sync_com_port_handle *port_handle)

{

  sns_com_port_priv_handle *priv_handle = (sns_com_port_priv_handle *)port_handle;
  sns_bus_info *bus_info = &priv_handle->bus_info;
  sns_rc return_code = SNS_RC_SUCCESS;
// 打开过,就不要在打开了
  if(bus_info->opened == true)
  {
    return SNS_RC_SUCCESS;
  }
// 
  return_code = scp_port_apis[bus_info->bus_type]->sns_scp_open(port_handle);
  else
  {
    bus_info->opened   = true;
    bus_info->power_on = true;
  }

  return return_code;
}

看下这个 scp_port_apis[bus_info->bus_type]->sns_scp_open(port_handle);
跑到 sns_com_port_i2c.c
sns_open_i2c 函数中,最后还是通过这个函数
sns_open_i2c_internal来实现的 .

static sns_rc sns_open_i2c_internal(sns_sync_com_port_handle *port_handle)
{
  sns_com_port_priv_handle *priv_handle = (sns_com_port_priv_handle *)port_handle;
  sns_bus_info             *bus_info = &priv_handle->bus_info;
  sns_com_port_config      *com_config = &priv_handle->com_config;
 // malloc 空间
  bus_info->bus_config = sns_malloc( SNS_HEAP_ISLAND, sizeof(sns_i2c_info) );

  i2c_info = (sns_i2c_info *)bus_info->bus_config;
//以请求的 i2c 速度打开 clk 资源.
  sns_result =
    sns_i2c_setup_clk_resources(com_config->bus_type,
                                (i2c_instance)(com_config->bus_instance),
                                com_config->max_bus_speed_KHz,
                                NULL);
// clk 设置完成,接下来 open i2c.
  result = i2c_open( (i2c_instance)(com_config->bus_instance),
                     &i2c_info->i2c_handle);

//  i2c 上电 
  result = i2c_power_on( i2c_info->i2c_handle );

//  log . 可以查看 哪个 sensor 上电成功.
  SNS_PRINTF( LOW, sns_fw_printf, "i2c_open success. hndl:%p instance:%u type:%u addr:0x%x",
              i2c_info->i2c_handle, com_config->bus_instance, 
              com_config->bus_type, com_config->slave_control );

  return SNS_RC_SUCCESS;
}

i2c 协议的一些上电大概就是这个流程, 其他协议应该也差不多.
普通的 gpio 口怎么上电呢? 比如 有些 sensor vdd 时序是有上电时序要求的.

再来继续看 Register Power Rails
应该是 注册 vdd/vddio
把这段代码 贴过来,看下

//  注册了个 定时器
 if (sns_suid_lookup_get(&state->common.suid_lookup_data, "timer", NULL)
        && NULL == state->pwr_rail_service
        && rv == SNS_RC_SUCCESS)
    {
        rv = stk3a6x_register_power_rail(this);
        /**---------------------Turn Power Rails ON----------------------------*/
        state->common.rail_config.rail_vote = state->common.registry_rail_on_state;

        if (rv == SNS_RC_SUCCESS)
        {
            rv = state->pwr_rail_service->api->sns_vote_power_rail_update(state->pwr_rail_service,
                    this,
                    &state->common.rail_config,
                    NULL);
        }

        /**-------------Create a Timer stream for Power Rail ON timeout.---------*/
        if (rv == SNS_RC_SUCCESS)
        {
            stk3a6x_start_power_rail_timer(this,
                                           sns_convert_ns_to_ticks(STK3A6X_OFF_TO_IDLE_MS * 1000 * 1000),
                                           STK3A6X_POWER_RAIL_PENDING_INIT);
        }
    }

看下 stk3a6x_register_power_rail

static sns_rc stk3a6x_register_power_rail(sns_sensor *const this)
{
  /** OFF state.
   *  Must be used when there are no active Sensors Instances.
   */
    state->common.rail_config.rail_vote = SNS_RAIL_OFF;

    if (NULL == state->pwr_rail_service)
    {
        state->pwr_rail_service =
            (sns_pwr_rail_service*)smgr->get_service(smgr, SNS_POWER_RAIL_SERVICE);
        state->pwr_rail_service->api->sns_register_power_rails(state->pwr_rail_service,
                &state->common.rail_config);
    }

    if (NULL == state->pwr_rail_service)
    {
        rv = SNS_RC_FAILED;
    }

    return rv;
}

rail_config 这些之类的 就是 json 设置的 这些
"num_rail":{ "type": "int", "ver": "0",
        "data": "  "  
      },
      "rail_on_state":{ "type": "int", "ver": "0",
        "data": "2"
      },
      "vddio_rail":{ "type": "str", "ver": "0",
        "data": "/pmic/client/sensor_vddio" 
      },

ok ,我们看下这个注册函数.有解释的.
大概理解下:
为物理的 sensor 供电的. 一般有一个或者多个. 从这可以看出,这不就是 vdd/vddio 这一类的东西嘛
这些东西应该定义在 non-volatile registry 。 是的,我们设置了 json文件,最后解析在 persist 分区中。最后从 registry 取出我们设置的数据. 当然这个只能初始化一次,上电过程不可能多次上电.

 /**
  *  Register power rails for a physical sensor.
  *
  *  All physical sensors typically have one or more power rails
  *  that supply power to the sensor hardware. Power rail
  *  configuration for all sensors shall be defined in the
  *  non-volatile registry. After the sensor driver fetches rail
  *  information from the registry, it shall register all rails
  *  using this API. Rail registration must happen only once for
  *  any rail.
  *  
  *  @param[i] this                  Power rail service reference.
  *  @param[i] rail_config           Rail config being registered.
  *
  *  @return
  *  SNS_RC_INVALID_VALUE - input rail config is invalid
  *  SNS_RC_SUCCESS - rail registration successful
  */
  sns_rc (*sns_register_power_rails)(sns_pwr_rail_service* this,
                                     sns_rail_config const* rail_config);

我们大致看下 这个函数的实现

SNS_SECTION(".text.sns") sns_rc sns_register_power_rails(sns_pwr_rail_service *this,
                                sns_rail_config const* rail_config)
{
   SNS_ISLAND_EXIT();
   return sns_register_power_rails_internal(this,rail_config);
}
// 
static sns_rc __attribute__ ((noinline))
sns_register_power_rails_internal(sns_pwr_rail_service *this,
                                sns_rail_config const* rail_config)
{
 // 获取 锁 
  sns_osa_lock_acquire(pwr_rail_service.rail_mgr_lock);
  else
  {
  // 有几路 供电.
    for(i = 0; i< rail_config->num_of_rails; i++)
    {
      rc = sns_pwr_rail_init(&rail_config->rails[i]);
      // if even a single rail init fails then return immediately.
      if(rc != SNS_RC_SUCCESS)
      {
        break;
      }
    }
  }
  // 释放 锁
  sns_osa_lock_release(pwr_rail_service.rail_mgr_lock);
  return rc;
}

//  假设  只有 vdd 供电,简单点
//  现在 看下 sns_pwr_rail_init
static sns_rc __attribute__ ((noinline))
sns_pwr_rail_init(sns_rail_name const* rail)
{
//  这名字也不是随便取的,可以参照下这个函数
  if(!sns_rail_name_is_valid(rail))
  {
    return SNS_RC_INVALID_VALUE;
  }

  // Init default state for rail.
  pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].state = SNS_RAIL_OFF;

  // Copy Rail name.
  sns_strlcpy(pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].name.name,
         rail->name,
         RAIL_NAME_STRING_SIZE_MAX);

  // Init client list for rail.
  sns_isafe_list_init(&pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].client_item_list);

  // Get NPA handle for rail. Not to be done for dummy rail
  if((0 != strncmp(DUMMY_SENSOR_VDD, pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].name.name,
                    sizeof(DUMMY_SENSOR_VDD))) &&
     (0 != strncmp(SNS_PWR_RAIL_VDD, pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].name.name,
                    sizeof(SNS_PWR_RAIL_VDD))))
  {
    pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].rail_npa_handle =
        npa_create_sync_client(pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].name.name,
                               "Sensors",
                               NPA_CLIENT_REQUIRED);
    if (NULL == pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].rail_npa_handle)
    {
      SNS_SPRINTF(ERROR, sns_fw_printf, "Could not initialize power rail: %s",
               pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].name.name);
    }

  }
  else
  {
    pwr_rail_service.rails[pwr_rail_service.num_rails_initialized].rail_npa_handle = NULL;
  }

  // Increment number of initialized rails.
  pwr_rail_service.num_rails_initialized++;

  return SNS_RC_SUCCESS;
}



下班时间到了,只能到后续有时间在写了…
继续 2023年08月15日10:04:14 更新

/**

  • Define a dummy rail for OEMs that use external rails for their sensors.
  • Dummy rail config is required so island mode block/unblock logic still
  • works for those OEMs.
    */
    #define DUMMY_SENSOR_VDD “/pmic/client/dummy_vdd”
    #define SNS_PWR_RAIL_VDD “/see/rail/eLDO”
    不太清楚这两个有啥区别??

可以使用外部供电. 比如下面这样.
在这里插入图片描述
没有使用 dsp 的pmic ,用了AP 那边的 pmic, 在 linux kernel 对这个口进行输出高电平,这个 sensor 就能进行供电了。

OK ,注册完成。接下来应该就是上电。
继续回到 xxx_start_hw_detect_sequence

 /**---------------------Turn Power Rails ON----------------------------*/
 // json 中设置 的 rail_on_state 。 就是启动转态 LPM/NPM 这种
        state->common.rail_config.rail_vote = state->common.registry_rail_on_state;
//  
        if (rv == SNS_RC_SUCCESS)
        {
            rv = state->pwr_rail_service->api->sns_vote_power_rail_update(state->pwr_rail_service,
                    this,
                    &state->common.rail_config,
                    NULL);
        }

看下是 怎么 power on 的
重点是这个函数 sns_vote_power_rail_update

sns_pwr_rail_service.c

  /**
  *  Vote for a power rail status change.
  *
  *  Each physical sensor driver uses this API to turn it's
  *  sensors power rails ON when there is an active client
  *  request. It is also the driver's responsibility to vote for
  *  power rails OFF when all clients requests are disabled (i.e.
  *  there are no Sensors Instances present)
  */
/*
 看注释的话: 
 1: 客户端上电请求
 2: 下电请求,会有多个下电请求,用 投票方法决定哪个下电。 不知道上电需不需要?? 没太看懂 
 3: sensor instance 不会有这个动作发生。 
*/
// 实际实现在这里. 
static sns_rc __attribute__ ((noinline))
sns_vote_power_rail_update_internal(sns_pwr_rail_service *this,
                                  struct sns_sensor const* sensor,
                                  sns_rail_config const* rails_config,
                                  sns_time* rail_on_timestamp)
{
  for(i = 0; i < rails_config->num_of_rails; i++)
  {
  // 判断是否注册了。 
     rail_is_registered = sns_rail_is_registered(&rails_config->rails[i], &rail_index);
 // 我们设置的状态是 SNS_RAIL_OFF . 这个是移除 pwr_rail_client 
     if(rails_config->rail_vote == SNS_RAIL_OFF)
     {
       sns_remove_pwr_rail_client(sensor, rail_index);
     }
     else
     {
       sns_add_pwr_rail_client(sensor, rails_config->rail_vote, rail_index);
     }

     // Update the power rail state. Not required for dummy rail
     if(0 != strncmp(DUMMY_SENSOR_VDD, pwr_rail_service.rails[rail_index].name.name, sizeof(DUMMY_SENSOR_VDD)))
     {
       sns_update_power_rail_state(rail_index);
     }

//  主要是为了获取硬件初始化的多长时间.
     /** There can be more than one rail that a client wants to
      *  turn ON. Using max operation to get timestamp of rail that
      *  was turned ON most recently so that the client can know
      *  exactly how long it needs until HW is available. */
     on_timestamp = SNS_MAX(on_timestamp, sns_get_rail_on_timestamp(rail_index));
  }
  return rc;
}

接下来最重要的就是: sns_update_power_rail_state
Parses client info for the rail and chooses best state.

static void __attribute__ ((noinline))
sns_update_power_rail_state(uint8_t rail_index)
{
  for(;
      NULL != sns_isafe_list_iter_curr(&iter);
      sns_isafe_list_iter_advance(&iter))
  {
    item = (sns_client_item*)sns_isafe_list_iter_get_curr_data(&iter);

    // Search for the highest vote in rail's client list.
    new_state = SNS_MAX(new_state, item->vote);

    if (SNS_RAIL_ON_LPM == item->vote)
    {
      lpm_client_count++;
    }
  }
//  LPM > 1. 新的状态进行赋值 SNS_RAIL_ON_NPM . 
  if (MAX_LPM_CLIENTS_PER_RAIL < lpm_client_count)
  {
    new_state = SNS_RAIL_ON_NPM;
  }

 //  进去
  if(new_state != pwr_rail_service.rails[rail_index].state)
  {
    /* state        new_state                     action
     *  ----------------------------------------------------------------------
     *  OFF          LPM/NPM     change right away. Update on_timestamp.
     *  LPM          NPM         change right away. Update on_timestamp.
     *  NPM/LPM      OFF         change right away. Clear on_timestamp.
     *  NPM          LPM         change right away. No change to on_timestamp.
     */
// 没有跑进去,不管
    if (SNS_VDDIO_PWR_RAIL_ALWAYS_ON == 0x1)
    {
    	if ((new_state == SNS_RAIL_OFF)
        	&& (0 == strncmp(PMIC_NPA_GROUP_ID_SENSOR_VDDIO, pwr_rail_service.rails[rail_index].name.name, sizeof(PMIC_NPA_GROUP_ID_SENSOR_VDDIO))))
        {
           if (0== sns_isafe_list_iter_len(&iter)) 
           {
              new_state = SNS_RAIL_ON_LPM;
           }
           else 
              return;
        }
    }
    if(0 == strncmp(SNS_PWR_RAIL_VDD, pwr_rail_service.rails[rail_index].name.name, sizeof(SNS_PWR_RAIL_VDD)))
    {
#ifdef SNS_GPIO_FOR_EXTERNAL_LDO
      sns_write_gpio(SNS_GPIO_FOR_EXTERNAL_LDO, 1, SNS_GPIO_DRIVE_STRENGTH_2_MILLI_AMP, 
			SNS_GPIO_PULL_TYPE_PULL_UP,(SNS_RAIL_OFF != new_state)?SNS_GPIO_STATE_HIGH:SNS_GPIO_STATE_LOW);
#endif
    }
    else
    {
    //  向  NPA 发送 power_on 请求.
      pmic_rail_state = (new_state == SNS_RAIL_OFF) ?
                        PMIC_NPA_MODE_ID_SENSOR_POWER_OFF :
                        ((new_state == SNS_RAIL_ON_LPM) ?
                        PMIC_NPA_MODE_ID_SENSOR_LPM :
                        PMIC_NPA_MODE_ID_SENSOR_POWER_ON);

      if (NULL != pwr_rail_service.rails[rail_index].rail_npa_handle)
      {
      npa_issue_required_request(pwr_rail_service.rails[rail_index].rail_npa_handle,
                                 pmic_rail_state);

      SNS_SPRINTF(HIGH, sns_fw_printf, "sensor power rail: %s, state: %d",
          (char*)pwr_rail_service.rails[rail_index].name.name,
          pmic_rail_state);
      }
    }
    pwr_rail_service.rails[rail_index].state = new_state;   // 更新状态
  }
}

new_state:是我们sensor 那边 传进去的状态
pwr_rail_service.rails[rail_index].state : 这个初始值 不太确定是多少,从哪里传过来的. 后面在去看下
这个不是很确定
转态发送了改变, 才会进行相应的动作.
从 log 中可以看到打印:

sensor power rail: /pmic/client/sensor_vdd, state: 2
sensor power rail: /pmic/client/sensor_vddio, state: 2
sensor power rail: /pmic/client/sensor_vdd_2, state: 2
sensor power rail: /pmic/client/sensor_vddio_2, state: 2
我们设置的 rail_on_state 是2, 没毛病。 这样就 power on 了.

这个是等待的时间。
个人认为是 等待 dsp 那边稳定后,再来读取 sensor id 。

/**-------------Create a Timer stream for Power Rail ON timeout.---------*/
    if (rv == SNS_RC_SUCCESS)
    {
        stk3a6x_start_power_rail_timer(this,
                                       sns_convert_ns_to_ticks(STK3A6X_OFF_TO_IDLE_MS * 1000 * 1000),
                                       STK3A6X_POWER_RAIL_PENDING_INIT);
    }

我们看下这个写法:

void stk3a6x_start_power_rail_timer(sns_sensor *const this,
                                    sns_time timeout_ticks,
                                    stk3a6x_power_rail_pending_state pwr_rail_pend_state)
{
    req_payload.timeout_period = timeout_ticks;
    if (NULL == state->timer_stream)
    {
        sns_service_manager *smgr = this->cb->get_service_manager(this);
        sns_stream_service *stream_svc = (sns_stream_service*)smgr->get_service(smgr, SNS_STREAM_SERVICE);
        sns_sensor_uid suid;
        sns_suid_lookup_get(&state->common.suid_lookup_data, "timer", &suid);
        stream_svc->api->create_sensor_stream(stream_svc, this, suid,
                                              &state->timer_stream);
    }

    req_len = pb_encode_request(buffer, sizeof(buffer), &req_payload,
                                sns_timer_sensor_config_fields, NULL);

    if (req_len > 0 && NULL != state->timer_stream)
    {
        sns_request timer_req =
        {
            .message_id = SNS_TIMER_MSGID_SNS_TIMER_SENSOR_CONFIG,
            .request = buffer, .request_len = req_len
        };
        state->timer_stream->api->send_request(state->timer_stream, &timer_req);
        state->power_rail_pend_state = pwr_rail_pend_state;
    }
}

看到只是发了个 消息: SNS_TIMER_MSGID_SNS_TIMER_SENSOR_CONFIG
state->power_rail_pend_state = pwr_rail_pend_state; 这句是在发送之后进行赋值的,并没有发送出去.

进入 sns_timer_sensor.c

SNS_SECTION(".text.sns")
static sns_sensor_instance*
sns_timer_set_client_request(sns_sensor *const this,
                             sns_request const *curr_req,
                             sns_request const *new_req,
                             bool remove) {
  else if( SNS_TIMER_MSGID_SNS_TIMER_SENSOR_CONFIG == new_req->message_id &&
           sns_timer_get_decoded_req(new_req, &decoded_request, &decoded_payload) )
    {
        // 加入到 timer 链表当中去.
 		 this->instance_api->set_client_config(timer_inst, &inst_req);
        sns_isafe_list_item_init(&new_inst_state->periodic_entry, timer_inst);
        rc = sns_timer_sensor_record_entry(state, timer_inst, true);
        
         // Generate timer registration event
        if(!pb_send_event(timer_inst, sns_timer_sensor_reg_event_fields,
                          &(new_inst_state->client_config), sns_get_system_time(),
                          SNS_TIMER_MSGID_SNS_TIMER_SENSOR_REG_EVENT, NULL))
        {
          SNS_PRINTF(ERROR, sns_fw_printf, "Timer registration event failure");
        }
    }

}

可以看到 最后发送 SNS_TIMER_MSGID_SNS_TIMER_SENSOR_REG_EVENT
这个可以看到, 没有什么用. sensor 当中没有对这个做处理
我们看下 timer 时间到了 怎么处理的

SNS_SECTION(".text.sns")
static sns_rc
sns_timer_inst_generate_event(sns_sensor_instance *const timer_inst,
                              sns_sensor *const timer_sensor,
                              sns_time system_time)
{
  timer_event.timeout_time = sensor_state->ro_buffer.timeout_event.timestamp;
  timer_event.requested_timeout_time = state->trigger_time;
   //  发送  SNS_TIMER_MSGID_SNS_TIMER_SENSOR_EVENT  message 的消息
  if(!pb_send_event(timer_inst, sns_timer_sensor_event_fields, &timer_event,
                    system_time, SNS_TIMER_MSGID_SNS_TIMER_SENSOR_EVENT,
                    NULL))
  {
  }
#ifdef SNS_TIMER_ENABLE_DEBUG
  SNS_PRINTF(LOW, sns_fw_printf, "Timer sent event for %x, tout %x, now %x",
             (uint32_t)timer_inst, (uint32_t)state->trigger_time,
             (uint32_t)system_time );
#endif
  return SNS_RC_SUCCESS;
}

可以看到,时间到了,会发送 SNS_TIMER_MSGID_SNS_TIMER_SENSOR_EVENT 的消息。
接下来,我们在回到 sensor 的驱动中
sns_stk3a6x_sensor_island.c

sns_rc stk3a6x_sensor_notify_event(sns_sensor *const this)
{
// 处理  timer event 
   /**----------------------Handle a Timer Sensor event.-------------------*/
       if (NULL != state->timer_stream)
   {
        event = state->timer_stream->api->peek_input(state->timer_stream);
        while (NULL != event)
        {
          pb_istream_t stream = pb_istream_from_buffer((pb_byte_t*)event->event,event->event_len);
          // timer 定时器,时间到了,发来的消息 SNS_TIMER_MSGID_SNS_TIMER_SENSOR_EVENT
            if (SNS_TIMER_MSGID_SNS_TIMER_SENSOR_EVENT == event->message_id)
            {
                if (pb_decode(&stream, sns_timer_sensor_event_fields, &timer_event))
                { 
                   // 注册的时候设置的 STK3A6X_POWER_RAIL_PENDING_INIT 
                    if (state->power_rail_pend_state == STK3A6X_POWER_RAIL_PENDING_INIT)
                    {
                        /**-------------------Read and Confirm WHO-AM-I------------------------*/
                        state->island_service->api->sensor_island_exit(state->island_service, this);
                        state->common.hw_is_present = stk3a6x_discover_hw(this);
                        if (state->common.hw_is_present)
                        {
                            stk3a6x_publish_available(this);
                            stk3a6x_update_sibling_sensors(this);
                        }             
                        state->power_rail_pend_state = STK3A6X_POWER_RAIL_PENDING_NONE;
                    }
                         }

            event = state->timer_stream->api->get_next_input(state->timer_stream);
        }

        /** Free up timer stream if not needed anymore */
        if (state->power_rail_pend_state == STK3A6X_POWER_RAIL_PENDING_NONE)
        {
            sns_sensor_util_remove_sensor_stream(this, &state->timer_stream);
        }
    }

}

总结下这个函数:
stk3a6x_start_power_rail_timer(this,
sns_convert_ns_to_ticks(STK3A6X_OFF_TO_IDLE_MS * 1000 * 1000),
STK3A6X_POWER_RAIL_PENDING_INIT);

power rail 等 STK3A6X_OFF_TO_IDLE_MS 的时间 ,在来继续处理
init 完成后,接下来就是读取 id

bool stk3a6x_discover_hw(sns_sensor *const this)
{
    /**-------------------Read and Confirm WHO-AM-I------------------------*/
    rv = stk3a6x_get_who_am_i(state->scp_service, state->common.com_port_info.port_handle,
                              &buffer[0]);
    STK3A6X_PRINTF(ERROR, this, "STK3A6X rv:%d,buffer[0]:0x%X",rv, buffer[0]);
    if ((rv == SNS_RC_SUCCESS) && (stk3a6x_check_pid(buffer[0]) == true))
    {
        // Reset Sensor only if an inatance is not alreadly running
        //  像是有什么故障,所以要 reset sensor 
        if (NULL == sns_sensor_util_get_shared_instance(this))
        {
            rv = stk3a6x_reset_device(state->scp_service, state->common.com_port_info.port_handle,
                                      (STK3A6X_ALS_OC | STK3A6X_ALS_STRM | STK3A6X_PS_OC | STK3A6X_PS_STRM));
        }
        if (rv == SNS_RC_SUCCESS)
        {
            hw_is_present = true;
        }
    }

    state->common.who_am_i = buffer[0];
    /**------------------Power Down and Close COM Port--------------------*/
    state->scp_service->api->sns_scp_update_bus_power(
        state->common.com_port_info.port_handle,
        false);
    state->scp_service->api->sns_scp_close(state->common.com_port_info.port_handle);
    state->scp_service->api->sns_scp_deregister_com_port(&state->common.com_port_info.port_handle);
    /**----------------------Turn Power Rail OFF--------------------------*/
    state->common.rail_config.rail_vote = SNS_RAIL_OFF;
    state->pwr_rail_service->api->sns_vote_power_rail_update(state->pwr_rail_service,
            this,
            &state->common.rail_config,
            NULL);
    return hw_is_present;
}

关闭了 com port / power done . 不知道 等传输数据的时候,还要打开这些吗??

读取到了id ,找到了硬件,publish 属性上去…
if (state->common.hw_is_present)
{
stk3a6x_publish_available(this);
stk3a6x_update_sibling_sensors(this);
}

现在 有个 sensor vdd 上电时序有要求,改哪里呢?
在这里插入图片描述

蓝色是 vdd , 如果要增加蓝色 vdd 的低电平的时间,要怎么改??
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Image Sensor是摄像机用来成像的感光元件,它将光图像转换成图像电信号。目前广泛使用的Image Sensor有两种,分别是CCD Sensor和CMOS Sensor。CCD Sensor和CMOS Sensor在1960年代开发,并被广泛应用在数码相机和其他电子光学设备中。CCD传感器在过去40年一直主导市场,但随着CMOS传感器设计的改进,CMOS传感器的市场份额不断增长,并在许多图像传感器应用中取代了CCD。相比于CCD,CMOS传感器功耗更低、处理图像的速度更快,制造成本更低。目前CMOS传感器已经被广泛应用于手机和其他移动产品中。\[1\] Image Sensor的曝光设置是图像处理过程中的一个重要参数,不同的Image Sensor厂商会有不同的曝光设置。常用的Image Sensor厂商OV和Sony会根据不同的曝光方式进行寄存器的配置。\[2\] 理想的CMOS Sensor具有线性响应特性,可以根据输入信号的大小调节增益系数。然而,实际的Sensor只能在一定的范围内保持线性响应,对于过小或过大的输入信号可能无法准确表示。\[3\] #### 引用[.reference_title] - *1* *3* [Image Sensor原理和常用术语简单介绍](https://blog.csdn.net/baidu_38797690/article/details/125146801)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Image Sensor的曝光和增益设置](https://blog.csdn.net/propor/article/details/128914659)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值