您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>電子元器件>傳感器>

淺析MTK hall霍爾傳感器之原理

2018年10月07日 15:50 作者:工程師譚軍 用戶評(píng)論(0
  霍爾傳感器
?
  霍爾傳感器是根據(jù)霍爾效應(yīng)制作的一種磁場傳感器?;魻栃?yīng)是磁電效應(yīng)的一種,這一現(xiàn)象是霍爾(A.H.Hall,1855—1938)于1879年在研究金屬的導(dǎo)電機(jī)構(gòu)時(shí)發(fā)現(xiàn)的。后來發(fā)現(xiàn)半導(dǎo)體、導(dǎo)電流體等也有這種效應(yīng),而半導(dǎo)體的霍爾效應(yīng)比金屬強(qiáng)得多,利用這現(xiàn)象制成的各種霍爾元件,廣泛地應(yīng)用于工業(yè)自動(dòng)化技術(shù)、檢測技術(shù)及信息處理等方面。霍爾效應(yīng)是研究半導(dǎo)體材料性能的基本方法。通過霍爾效應(yīng)實(shí)驗(yàn)測定的霍爾系數(shù),能夠判斷半導(dǎo)體材料的導(dǎo)電類型、載流子濃度及載流子遷移率等重要參數(shù)。
?
?
  磁場中有一個(gè)霍爾半導(dǎo)體片,恒定電流I從A到B通過該片。在洛侖茲力的作用下,I的電子流在通過霍爾半導(dǎo)體時(shí)向一側(cè)偏移,使該片在CD方向上產(chǎn)生電位差,這就是所謂的霍爾電壓。
?
  霍爾電壓隨磁場強(qiáng)度的變化而變化,磁場越強(qiáng),電壓越高,磁場越弱,電壓越低,霍爾電壓值很小,通常只有幾個(gè)毫伏,但經(jīng)集成電路中的放大器放大,就能使該電壓放大到足以輸出較強(qiáng)的信號(hào)。若使霍爾集成電路起傳感作用,需要用機(jī)械的方法來改變磁感應(yīng)強(qiáng)度。下圖所示的方法是用一個(gè)轉(zhuǎn)動(dòng)的葉輪作為控制磁通量的開關(guān),當(dāng)葉輪葉片處于磁鐵和霍爾集成電路之間的氣隙中時(shí),磁場偏離集成片,霍爾電壓消失。這樣,霍爾集成電路的輸出電壓的變化,就能表示出葉輪驅(qū)動(dòng)軸的某一位置,利用這一工作原理,可將霍爾集成電路片用作用點(diǎn)火正時(shí)傳感器。霍爾效應(yīng)傳感器屬于被動(dòng)型傳感器,它要有外加電源才能工作,這一特點(diǎn)使它能檢測轉(zhuǎn)速低的運(yùn)轉(zhuǎn)情況。
?
  霍爾效應(yīng)
?
  霍爾效應(yīng)從本質(zhì)上講是運(yùn)動(dòng)的帶電粒子在磁場中受洛侖茲力作用引起的偏轉(zhuǎn)。當(dāng)帶電粒子(電子或空穴)被約束在固體材料中,這種偏轉(zhuǎn)就導(dǎo)致在垂直電流和磁場的方向上產(chǎn)生正負(fù)電荷的聚積,從而形成附加的橫向電場。對(duì)于圖一所示的半導(dǎo)體試樣,若在X方向通以電流Is,在Z方向加磁場B,則在Y方向即試樣A,A′電極兩側(cè)就開始聚積異號(hào)電荷而產(chǎn)生相應(yīng)的附加電場。電場的指向取決定于測試樣品的電類型。顯然,該電場是阻止載流子繼續(xù)向側(cè)面偏移,
?
  當(dāng)載流子所受的橫向電場力eEH與洛侖茲力相等時(shí),樣品兩側(cè)電荷的積累就達(dá)到平衡,故有
?
 ?、?/div>
?
  其中EH為霍爾電場,V是載流子在電流方向上的平均漂移速度。設(shè)試樣的寬為b,厚度為d,載流子濃度為n,則
?
 ?、?/div>
?
  由⑴、⑵兩式可得
?
  ⑶
?
  即霍爾電壓VH(A、A′電極之間的電壓)與ISB乘積正比與試樣厚度d成反比。比例系數(shù) 稱為霍爾系數(shù),它是反映材料霍爾效應(yīng)強(qiáng)弱的重要參數(shù),只要測出 VH(伏)以及知道IIs(安)、B(高斯)和d(厘 米)可按下式計(jì)算RH(厘米3/庫侖)
?
  分類
?
  霍爾傳感器分為線型霍爾傳感器和開關(guān)型霍爾傳感器兩種。
?
  (一)開關(guān)型霍爾傳感器由穩(wěn)壓器、霍爾元件、差分放大器,斯密特觸發(fā)器和輸出級(jí)組成,它輸出數(shù)字量。開關(guān)型霍爾傳感器還有一種特殊的形式,稱為鎖鍵型霍爾傳感器。
?
 ?。ǘ┚€性型霍爾傳感器由霍爾元件、線性放大器和射極跟隨器組成,它輸出模擬量。
?
  線性霍爾傳感器又可分為開環(huán)式和閉環(huán)式。閉環(huán)式霍爾傳感器又稱零磁通霍爾傳感器。線性霍爾傳感器主要用于交直流電流和電壓測量。。
?
  開關(guān)型
?
  如圖4所示,其中Bnp為工作點(diǎn)“開”的磁感應(yīng)強(qiáng)度,BRP為釋放點(diǎn)“關(guān)”的磁感應(yīng)強(qiáng)度。當(dāng)外加的磁感應(yīng)強(qiáng)度超過動(dòng)作點(diǎn)Bnp時(shí),傳感器輸出低電平,當(dāng)磁感應(yīng)強(qiáng)度降到動(dòng)作點(diǎn)Bnp以下時(shí),傳感器輸出電平不變,一直要降到釋放點(diǎn)BRP時(shí),傳感器才由低電平躍變?yōu)楦唠娖?。Bnp與BRP之間的滯后使開關(guān)動(dòng)作更為可靠。
?
  鎖鍵型
?
  如圖5所示,當(dāng)磁感應(yīng)強(qiáng)度超過動(dòng)作點(diǎn)Bnp時(shí),傳感器輸出由高電平躍變?yōu)榈碗娖?,而在外磁場撤消后,其輸出狀態(tài)保持不變(即鎖存狀態(tài)),必須施加反向磁感應(yīng)強(qiáng)度達(dá)到BRP時(shí),才能使電平產(chǎn)生變化。
?
  線性型
?
  輸出電壓與外加磁場強(qiáng)度呈線性關(guān)系,如圖3所示,可見,在B1~B2的磁感應(yīng)強(qiáng)度范圍內(nèi)有較好的線性度,磁感應(yīng)強(qiáng)度超出此范圍時(shí)則呈現(xiàn)飽和狀態(tài)。
?
  開環(huán)式電流傳感器
?
  由于通電螺線管內(nèi)部存在磁場,其大小與導(dǎo)線中的電流成正比,故可以利用霍爾傳感器測量出磁場,從而確定導(dǎo)線中電流的大小。利用這一原理可以設(shè)計(jì)制成霍爾電流傳感器。其優(yōu)點(diǎn)是不與被測電路發(fā)生電接觸,不影響被測電路,不消耗被測電源的功率,特別適合于大電流傳感。
?
  霍爾電流傳感器工作原理如圖6所示,標(biāo)準(zhǔn)圓環(huán)鐵芯有一個(gè)缺口,將霍爾傳感器插入缺口中,圓環(huán)上繞有線圈,當(dāng)電流通過線圈時(shí)產(chǎn)生磁場,則霍爾傳感器有信號(hào)輸出。
?
  閉環(huán)式電流傳感器
?
  磁平衡式電流傳感器也叫霍爾閉環(huán)電流傳感器,也稱補(bǔ)償式傳感器,即主回路被測電流Ip在聚磁環(huán)處所產(chǎn)生的磁場通過一個(gè)次級(jí)線圈,電流所產(chǎn)生的磁場進(jìn)行補(bǔ)償, 從而使霍爾器件處于檢測零磁通的工作狀態(tài)。
?
  磁平衡式電流傳感器的具體工作過程為:當(dāng)主回路有一電流通過時(shí),在導(dǎo)線上產(chǎn)生的磁場被聚磁環(huán)聚集并感應(yīng)到霍爾器件上, 所產(chǎn)生的信號(hào)輸出用于驅(qū)動(dòng)相應(yīng)的功率管并使其導(dǎo)通,從而獲得一個(gè)補(bǔ)償電流Is。 這一電流再通過多匝繞組產(chǎn)生磁場 ,該磁場與被測電流產(chǎn)生的磁場正好相反,因而補(bǔ)償了原來的磁場, 使霍爾器件的輸出逐漸減小。當(dāng)與Ip與匝數(shù)相乘 所產(chǎn)生的磁場相等時(shí),Is不再增加,這時(shí)的霍爾器件起指示零磁通的作用 ,此時(shí)可以通過Is來平衡。被測電流的任何變化都會(huì)破壞這一平衡。 一旦磁場失去平衡,霍爾器件就有信號(hào)輸出。經(jīng)功率放大后,立即就有相應(yīng)的電流流過次級(jí)繞組以對(duì)失衡的磁場進(jìn)行補(bǔ)償。從磁場失衡到再次平衡,所需的時(shí)間理論上不到1μs,這是一個(gè)動(dòng)態(tài)平衡的過程。
淺析MTK hall霍爾傳感器之原理

  2. dws配中斷腳和使能腳

  (根據(jù)原理圖中“09_CAMERA_SENSOR”頁中, “HALL”部分【OUT】引腳所連接 - 使能腳GPIO12)

  v666為例

  dws配置pin腳: - 由于硬件上拉-》dws也要配成上拉

  EintMode|Def.Mode M0|M1|M2|M3|M4|M5|M6|M7|InPull En|InPull SelHigh|Def.Dir|In|Out|OutHigh|VarName1

  GPIO12 1 0:GPIO12 1 1 IN GPIO_HALL_1_PIN

  dws配置EINT:

  EINTVar|Debounce Time(ms)|Polarity|Sensitive_Level|Debounce En

  EINT12 HALL_1 0 Low Level Disable

  dts:

  * HALL GPIO standardization */

  &pio {

  hall_pin_default: halldefaultcfg {

  };

  hall_pin_as_int: hallint@12 {

  pins_cmd_dat {

  pins = 《PINMUX_GPIO12__FUNC_GPIO12》;

  slew-rate = 《0》;

  bias-pull-up = 《00》;

  };

  };

  };

  &keypad {

  pinctrl-names = “default”, “hall_pin_as_int”;

  pinctrl-0 = 《&hall_pin_default》;

  pinctrl-1 = 《&hall_pin_as_int》;

  status = “okay”;

  };

  /* HALL GPIO end */

  一、 查看是否有鍵值上報(bào)

  getevent -i

  add device 8: /dev/input/event1

  bus: 0019

  vendor 2454

  product 6500

  version 0010

  name: “mtk-kpd” // 與音量加減鍵、電源鍵、hall同一個(gè)event

  location: “”

  id: “”

  version: 1.0.1

  getevent -t /dev/input/event1 // 打印出來的是16進(jìn)制

  [70.169911] 0001 0085 00000001 // 85 -》 133 遠(yuǎn)離

 ?。?0.169911] 0000 0000 00000000

 ?。?0.352126] 0001 0085 00000000

  [70.352126] 0000 0000 00000000

  二、查看代碼確定上報(bào)鍵值

  1. alps\kernel-3.18\drivers\input\keyboard\mediatek\kpd.c

  #define KEY_HALL_F3 133 //for hall eint report key far // 磁鐵遠(yuǎn)離

  #define KEY_HALL_F4 134 //for hall eint report key close // 磁鐵靠近

  2. alps/device/magcomm/magc6580_we_c_m/mtk-kpd.kl , 映射給上層

  key 114 0x72 VOLUME_DOWN // 側(cè)鍵

  key 115 0x73 VOLUME_UP

  key 116 0x74 POWER

  + key 133 F3 // 霍爾

  + key 134 F4

  注:修改此文件,可以用push的方式先試驗(yàn)

  find /system -name mtk-kpd.kl

  /system/usr/keylayout/mtk-kpd.kl

  adb push 。.. /system/usr/keylayout/

  三、添加權(quán)限

  alps/device/mediatek/common/sepolicy/basic/system_app.te

  # add permission for hall

  allow system_app sysfs_keypad_file:dir { search read write };

  allow system_app sysfs_keypad_file:file { read write getattr setattr open create };

  alps/device/mediatek/common/sepolicy/full/platform_app.te

  # add permission for hall

  allow platform_app sysfs_keypad_file:dir { search read write };

  allow platform_app sysfs_keypad_file:file { read write getattr setattr open create };

  alps/device/mediatek/common/sepolicy/full/priv_app.te

  # add permission for hall

  allow priv_app sysfs_keypad_file:dir { search read write };

  allow priv_app sysfs_keypad_file:file { read write getattr setattr open create };

  四、手寫筆插入與拔出 - 用hall來實(shí)現(xiàn),手寫筆尖有磁性(以80 5.1為例)

  1. 修改alps/device/haocheng/hct6580_weg_a_l/mtk-kpd.kl ,映射給上層

  key 133 F3

  key 134 F4

  + key 136 F6

  + key 137 F7

  2. 修改alps\kernel-3.10\drivers\misc\mediatek\keypad\kpd.c,仿造hall_1添加hall_2的代碼:

  + #ifdef GPIO_HALL_2_PIN

  #define CUSTOM_HALL_2_SUPPORT

  #define GPIO_HALL_2_EINT_PIN GPIO_HALL_2_PIN

  #define GPIO_HALL_2_EINT_PIN_M_EINT GPIO_HALL_2_PIN_M_EINT

  static unsigned int hall_2_irq;

  #define HALL_2_TAG “hall: ”

  #define HALL_2_DBG(fmt, args.。.) printk(HALL_2_TAG fmt, ##args)

  struct work_struct hall_2_eint_work;

  static int hall_2_state_flag = 0;

  static bool hall_2_state = 1; //0: close 1:far

  #define KEY_HALL_F6 136 //for hall eint report key far

  #define KEY_HALL_F7 137 //for hall eint report key close

  + #endif

  + #ifdef CUSTOM_HALL_2_SUPPORT // 提供給上層調(diào)用接口: /sys/bus/。..

  static volatile int hall_2_status = 0;

  static ssize_t store_hall_2_state(struct device_driver *ddri, const char *buf, size_t count)

  {

  if (sscanf(buf, “%u”, &hall_2_status) != 1) {

  kpd_print(“kpd call state: Invalid values\n”);

  return -EINVAL;

  }

  hall_2_state = (bool)hall_2_status;

  return count;

  }

  static ssize_t show_hall_2_state(struct device_driver *ddri, char *buf)

  {

  ssize_t res;

  res = snprintf(buf, PAGE_SIZE, “%d\n”, hall_2_state);

  return res;

  }

  static DRIVER_ATTR(hall_2_state, S_IWUSR | S_IALLUGO, show_hall_2_state, store_hall_2_state);

  + #endif

  static struct driver_attribute *kpd_attr_list[] = {

  &driver_attr_kpd_call_state,

  #ifdef CUSTOM_HALL_SUPPORT

  &driver_attr_hall_state,

  #endif

  + #ifdef CUSTOM_HALL_2_SUPPORT // 提供給上層調(diào)用接口: /sys/bus/。..

  + &driver_attr_hall_2_state,

  + #endif

  };

  + #ifdef CUSTOM_HALL_2_SUPPORT

  + void kpd_hall_2_key_handler(unsigned long pressed, u16 linux_keycode)

  {

  if(!kpd_input_dev) {

  printk(“KPD input device not ready\n”);

  return;

  }

  input_report_key(kpd_input_dev, linux_keycode, pressed);

  input_sync(kpd_input_dev);

  if (kpd_show_hw_keycode) {

  printk(KPD_SAY “(%s) KEY_HALL keycode =%d \n”, pressed ? “pressed” : “released”, linux_keycode);

  }

  }

  static void hall_2_work_func(struct work_struct *work)

  {

  if(hall_2_state == 1) {

  kpd_hall_key_handler(1, KEY_HALL_F6);

  kpd_hall_key_handler(0, KEY_HALL_F6);

  } else if(hall_2_state == 0) {

  kpd_hall_key_handler(1, KEY_HALL_F7);

  kpd_hall_key_handler(0, KEY_HALL_F7);

  }

  }

  bool get_hall_2_state()

  {

  return hall_2_state;

  }

  EXPORT_SYMBOL(get_hall_2_state);

  void hall_2_eint_func(void)

  {

  disable_irq_nosync(hall_2_irq);

  if(hall_2_state_flag)

  {

  hall_2_state_flag = 0;

  hall_2_state = 1;

  irq_set_irq_type(hall_2_irq,IRQ_TYPE_LEVEL_LOW);

  }

  else{

  hall_2_state_flag = 1;

  hall_2_state = 0;

  irq_set_irq_type(hall_2_irq,IRQ_TYPE_LEVEL_HIGH);

  }

  enable_irq(hall_2_irq);

  schedule_work(&hall_2_eint_work);

  }

  static irqreturn_t hall_2_irq_handler(int irq, void *dev_id)

  {

  hall_2_eint_func();

  return IRQ_HANDLED;

  }

  int hall_2_setup_eint(void)

  {

  struct device_node *hall_node;

  u32 ints[2] = {0, 0};

  mt_set_gpio_dir(GPIO_HALL_2_EINT_PIN, GPIO_DIR_IN);

  mt_set_gpio_mode(GPIO_HALL_2_EINT_PIN, GPIO_HALL_2_EINT_PIN_M_EINT);

  mt_set_gpio_pull_enable(GPIO_HALL_2_EINT_PIN, 0);

  hall_node = of_find_compatible_node(NULL,NULL,“mediatek, HALL_2-eint”);

  if(hall_node){

  printk(“hall_irq has find!\n”);

  of_property_read_u32_array(hall_node, “debounce”, ints, ARRAY_SIZE(ints));

  mt_gpio_set_debounce(ints[0], ints[1]);

  hall_2_irq= irq_of_parse_and_map(hall_node, 0);

  if (!hall_2_irq)

  {

  printk(“irq_of_parse_and_map hall fail??!\n”);

  return -EINVAL;

  }

  if(request_irq(hall_2_irq, hall_2_irq_handler, IRQF_TRIGGER_NONE, “HALL_2-eint”, NULL)) {

  printk(“HALL IRQ NOT AVAILABLE!!\n”);

  return -EINVAL;

  }

  }

  else{

  printk(“null hall_irq node!\n”);

  return -EINVAL;

  }

  return 0;

  }

  #endif

  static int kpd_pdrv_probe(struct platform_device *pdev)

  {

  #ifdef CUSTOM_HALL_SUPPORT

  __set_bit(KEY_HALL_F3, kpd_input_dev-》keybit);

  __set_bit(KEY_HALL_F4, kpd_input_dev-》keybit);

  #endif

  + #ifdef CUSTOM_HALL_2_SUPPORT

  + __set_bit(KEY_HALL_F6, kpd_input_dev-》keybit); // 使能input上報(bào)鍵值

  + __set_bit(KEY_HALL_F7, kpd_input_dev-》keybit);

  + #endif

  。..

  #ifdef CUSTOM_HALL_SUPPORT

  INIT_WORK(&hall_eint_work, hall_work_func);

  hall_setup_eint();

  #endif

  + #ifdef CUSTOM_HALL_2_SUPPORT

  + INIT_WORK(&hall_2_eint_work, hall_2_work_func); // 中斷中喚醒工作,工作中上報(bào)key

  + hall_2_setup_eint(); // 設(shè)置GPIO口狀態(tài),從dts獲取中斷信息,注冊(cè)中斷

  + #endif

  。..

  }

  3. 修改dws,配置GPIO口為中斷模式,配置中斷的觸發(fā)方式(電平or邊沿)

  五、39平臺(tái):

  1. device/mediateksample/k39tv1_bsp_1g/mtk-kpd.kl

  + key 133 F3

  + key 134 F4

  2. mt6739.dts

  + hall_1: hall_1 {

  + compatible = “mediatek, hall_1-eint”;

  + status = “disabled”;

  + };

  3. k39tv1_bsp_1g.dts

  + /* HALL GPIO standardization */

  + &keypad {

  pinctrl-names = “default”, “hall_pin_as_int”;

  pinctrl-0 = 《&hall_pin_default》;

  pinctrl-1 = 《&hall_pin_as_int》;

  status = “okay”;

  };

  &pio {

  hall_pin_default: halldefaultcfg {

  };

  hall_pin_as_int: hallint@14 {

  pins_cmd_dat {

  pins = 《PINMUX_GPIO14__FUNC_GPIO14》;

  slew-rate = 《0》;

  bias-pull-up = 《00》;

  };

  };

  + };

  + /* HALL GPIO end */

  4. codegen.dws

  EINT:

  ID EINTVar|Debounce Time(ms)|Polarity|Sensitive_Level|Debounce En

  EINT14 HALL_1 0 Low Level Disable

  GPIO:

  ID EintMode|Def.Mode M0|M1|M2|M3|M4|M5|M6|M7|InPull En|InPull SelHigh|Def.Dir|In|Out|OutHigh|VarName1

  GPIO14 1 0:GPIO14 1 1 1 IN 1 GPIO_HALL_1_PIN

  5. kernel-4.4/drivers/input/keyboard/mediatek/kpd.c

  + #ifdef CONFIG_KST_HALL_SUPPORT

  + #define CUSTOM_HALL_SUPPORT

  #define GPIO_HALL_EINT_PIN GPIO_HALL_1_PIN

  #define GPIO_HALL_EINT_PIN_M_EINT GPIO_HALL_1_PIN_M_EINT

  static unsigned int hall_irq;

  #define HALL_TAG “hall: ”

  #define HALL_DBG(fmt, args.。.) printk(HALL_TAG fmt, ##args)

  struct work_struct hall_eint_work;

  static int hall_state_flag = 0;

  static bool hall_state = 1; //0: close 1:far

  #define KEY_HALL_F3 133 //116 //for hall eint report key far

  #define KEY_HALL_F4 134 //62 //for hall eint report key close

  struct pinctrl *hallpinctrl;

  + struct pinctrl_state *hall_pin_as_int;

  + #endif

  + #ifdef CUSTOM_HALL_SUPPORT

  + static volatile int hall_status = 0;

  static ssize_t store_hall_state(struct device_driver *ddri, const char *buf, size_t count)

  {

  if (sscanf(buf, “%u”, &hall_status) != 1) {

  kpd_print(“kpd call state: Invalid values\n”);

  return -EINVAL;

  }

  hall_state = (bool)hall_status;

  return count;

  }

  static ssize_t show_hall_state(struct device_driver *ddri, char *buf)

  {

  ssize_t res;

  res = snprintf(buf, PAGE_SIZE, “%d\n”, hall_state);

  return res;

  }

  + static DRIVER_ATTR(hall_state, S_IWUSR | S_IRUGO, show_hall_state, store_hall_state);

  + #endif

  static struct driver_attribute *kpd_attr_list[] = {

  &driver_attr_kpd_call_state,

  + #ifdef CUSTOM_HALL_SUPPORT

  + &driver_attr_hall_state,

  + #endif

  };

  + #ifdef CUSTOM_HALL_SUPPORT

  + void kpd_hall_key_handler(unsigned long pressed, u16 linux_keycode)

  {

  if(!kpd_input_dev) {

  printk(“KPD input device not ready\n”);

  return;

  }

  input_report_key(kpd_input_dev, linux_keycode, pressed);

  input_sync(kpd_input_dev);

  if (kpd_show_hw_keycode) {

  printk(KPD_SAY “(%s) KEY_HALL keycode =%d \n”, pressed ? “pressed” : “released”, linux_keycode);

  }

  }

  static void hall_work_func(struct work_struct *work)

  {

  printk(“key hall_work_func not ready\n”); //add

  if(hall_state == 1) {

  kpd_hall_key_handler(1, KEY_HALL_F3);

  kpd_hall_key_handler(0, KEY_HALL_F3);

  }

  else if(hall_state == 0) {

  kpd_hall_key_handler(1, KEY_HALL_F4);

  kpd_hall_key_handler(0, KEY_HALL_F4);

  }

  }

  void hall_eint_func(void)

  {

  disable_irq_nosync(hall_irq);

  if(hall_state_flag)

  {

  hall_state_flag = 0;

  hall_state = 1;

  irq_set_irq_type(hall_irq,IRQ_TYPE_LEVEL_LOW);

  }

  else

  {

  hall_state_flag = 1;

  hall_state = 0;

  irq_set_irq_type(hall_irq,IRQ_TYPE_LEVEL_HIGH);

  }

  enable_irq(hall_irq);

  schedule_work(&hall_eint_work);

  }

  static irqreturn_t hall_irq_handler(int irq, void *dev_id)

  {

  hall_eint_func();

  return IRQ_HANDLED;

  }

  int hall_setup_eint(void)

  {

  struct device_node *hall_node;

  u32 ints[2] = {0, 0};

  hall_node = of_find_compatible_node(NULL,NULL,“mediatek, hall_1-eint”);

  if(hall_node){

  printk(“hall_irq has find!\n”);

  of_property_read_u32_array(hall_node, “debounce”, ints, ARRAY_SIZE(ints));

  gpio_set_debounce(ints[0], ints[1]);

  hall_irq= irq_of_parse_and_map(hall_node, 0);

  if (!hall_irq)

  {

  printk(“irq_of_parse_and_map hall fail!!\n”);

  return -EINVAL;

  }

  if(request_irq(hall_irq, hall_irq_handler, IRQF_TRIGGER_NONE, “hall_1-eint”, NULL)) {

  printk(“HALL IRQ NOT AVAILABLE!!\n”);

  return -EINVAL;

  }

  }

  else

  {

  printk(“null hall_irq node!\n”);

  return -EINVAL;

  }

  return 0;

  + }

  + #endif

  + #ifdef CUSTOM_HALL_SUPPORT

  + int hall_get_gpio_info(struct platform_device *pdev)

  {

  int ret;

  hallpinctrl = devm_pinctrl_get(&pdev-》dev);

  if (IS_ERR(hallpinctrl)) {

  ret = PTR_ERR(hallpinctrl);

  dev_err(&pdev-》dev, “hallpinctrl err!\n”);

  return ret;

  }

  hall_pin_as_int = pinctrl_lookup_state(hallpinctrl, “hall_pin_as_int”);

  if (IS_ERR(hall_pin_as_int)) {

  ret = PTR_ERR(hall_pin_as_int);

  dev_err(&pdev-》dev, “hall_pin_as_int err!\n”);

  return ret;

  }

  pinctrl_select_state(hallpinctrl, hall_pin_as_int);

  return 0;

  + }

  + #endif

  static int kpd_pdrv_probe(struct platform_device *pdev)

  {

  __set_bit(KPD_KEY_MAP, kpd_input_dev-》keybit);

  + #ifdef CUSTOM_HALL_SUPPORT

  + __set_bit(KEY_HALL_F3, kpd_input_dev-》keybit);

  + __set_bit(KEY_HALL_F4, kpd_input_dev-》keybit);

  + #endif

  。..

  hrtimer_init(&aee_timer_5s, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

  aee_timer_5s.function = aee_timer_5s_func;

  + #ifdef CUSTOM_HALL_SUPPORT

  + INIT_WORK(&hall_eint_work, hall_work_func);

  + hall_get_gpio_info(pdev);

  + hall_setup_eint();

  + #endif

  err = kpd_create_attr(&kpd_pdrv.driver);

  。..

  }

  調(diào)試案例

  案例一 : hall不通 - 電容貼錯(cuò)

  現(xiàn)象 :

  平臺(tái) : androidN,MTK6737

  排查過程: 1. 查看是否有鍵值上報(bào) - 拿磁鐵靠近

  getevent -t /dev/input/event1 - 無鍵值上報(bào)

  2. 檢查dws中的gpio口配置&中斷配置、dts中斷配置均ok(根據(jù)原理圖得知EINT12 即 GPIO12)

  3. 接示波器量中斷腳 - 磁鐵靠近時(shí) 中斷腳無高低電平變化

  4. 交給硬件同事檢查 -》 一個(gè)電容貼錯(cuò),替換后ok

  處理方案: 換料 改bom

  案例二 : hall不通 - hall芯片貼反

  現(xiàn)象 :

  平臺(tái) : androidN,MTK6737

  排查過程: 1. 查看是否有鍵值上報(bào) - 拿磁鐵靠近

  getevent -t /dev/input/event1 - 無鍵值上報(bào)

  2. 檢查dws中的gpio口配置&中斷配置、dts中斷配置均ok

  3. hall芯片貼反了 -》 改正ok

  案例三 : hall不通 - 硬件短路

  現(xiàn)象 :

  平臺(tái) : androidN,MTK6737

  排查過程: 1. 查看是否有鍵值上報(bào) - 拿磁鐵靠近

  getevent -t /dev/input/event1 - 無鍵值上報(bào)

  2. 用鑷子將hall中斷腳短地(平常上拉為高電平,低電平為中斷) - 有鍵值上報(bào)


非常好我支持^.^

(2) 100%

不好我反對(duì)

(0) 0%

( 發(fā)表人:金巧 )

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?