ひでみのアイデア帳

くだらないことなんだけど、忘れないために・・・

本棚を作ってみた

来年の新開発環境を整備するためにまずは漫画を整理し始めた。

と、いうか、こういう本棚が欲しかったんだけど、なかなかちょうどいいサイズが見つからなかったので作った。

3年ぐらいは探してかな?

ディノスやベルメゾンに良さげなのがあるんだけど、俺、コミック専用棚でいいんだよなぁ。

今回は4つの棚を作って、3つはコミック(B6版サイズ)専用で1つはA4サイズの本専用でデスクの下に入るようにした。

本棚

木材はホームセンターで切ってもらって、あとは家でドリルでネジ締めだけ。

皿ネジ止めようの穴を開けてからネジ止めだけど・・・

本棚の下にはキャスターが付いているので引き出せるようになっている。

ちょぉ〜、満足♪

ダンボールで屋根裏に眠っている新旧の漫画を入れ替えたりして、本棚のラインナップを整理。

デスクの上が騒然となっているので来週はデスクの後ろに50mm程度の配線をまとめる棚を作成する予定。

今日のUltra96

昨日のUltra96のPowerDownはUIOで制御にしたら落とせるよってのナシね。

2018年11月11日 22時12分19秒 - Permament Link

Ultra96の電源制御

LTC2954のエラー内容は下記のとおりです。

root@ultra96:~# dmesg | grep -i ltc
[    1.393172] ltc2952-poweroff ltc2954: pm_power_off already registered
[    1.393186] ltc2952-poweroff: probe of ltc2954 failed with error -16

単純に言えば、すでに登録されてしまっているんだなってことだよね。

ということは誰に負けたのかを見つければいいだけで・・・

Devicetreeから逆に追いかけるとltc2954-poweroff.cにたどり着く。

ソースコードをみるとprobeの最初でエラーしていることがわかる。

static int ltc2952_poweroff_probe(struct platform_device *pdev)
{
    int ret;
    struct ltc2952_poweroff *data;

    if (pm_power_off) {
        dev_err(&pdev->dev, "pm_power_off already registered");
        return -EBUSY;
    }

ということはpm_power_offを先にセットした奴を見つければよいのだ。

これは単なる犯人探しゲームのようなものだな。

さて、ざっくりとソースコードからpm_power_off変数にセットする奴を探してみましょう。

grep -R -i pm_power_off|grep pm_power_off
platform/x86/pmc_atom.c:    if (acpi_base_addr != 0 && pm_power_off == NULL)
platform/x86/pmc_atom.c:        pm_power_off = pmc_power_off;
parisc/power.c:         if (pm_power_off)
parisc/power.c:             pm_power_off();
char/ipmi/ipmi_poweroff.c:  old_poweroff_func = pm_power_off;
char/ipmi/ipmi_poweroff.c:  pm_power_off = ipmi_poweroff_function;
char/ipmi/ipmi_poweroff.c:  pm_power_off = old_poweroff_func;
char/ipmi/ipmi_poweroff.c:      pm_power_off = old_poweroff_func;
mfd/tps80031.c: if (pdata->use_power_off && !pm_power_off) {
mfd/tps80031.c:     pm_power_off = tps80031_power_off;
mfd/tps80031.c:     pm_power_off = NULL;
mfd/rn5t618.c:static struct rn5t618 *rn5t618_pm_power_off;
mfd/rn5t618.c:  regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_REPCNT,
mfd/rn5t618.c:  regmap_update_bits(rn5t618_pm_power_off->regmap, RN5T618_SLPCNT,
mfd/rn5t618.c:  rn5t618_pm_power_off = priv;
mfd/rn5t618.c:      if (!pm_power_off)
mfd/rn5t618.c:          pm_power_off = rn5t618_power_off;
mfd/rn5t618.c:  if (priv == rn5t618_pm_power_off) {
mfd/rn5t618.c:      rn5t618_pm_power_off = NULL;
mfd/rn5t618.c:      pm_power_off = NULL;
mfd/tps65910.c: if (pmic_plat_data->pm_off && !pm_power_off) {
mfd/tps65910.c:     pm_power_off = tps65910_power_off;
mfd/max8907.c:  if (pm_off && !pm_power_off) {
mfd/max8907.c:      pm_power_off = max8907_power_off;
mfd/palmas.c:       } else if (pdata->pm_off && !pm_power_off) {
mfd/palmas.c:           pm_power_off = palmas_power_off;
mfd/palmas.c:       pm_power_off = NULL;
mfd/retu-mfd.c:static struct retu_dev *retu_pm_power_off;
mfd/retu-mfd.c: struct retu_dev *rdev = retu_pm_power_off;
mfd/retu-mfd.c: mutex_lock(&retu_pm_power_off->mutex);
mfd/retu-mfd.c: mutex_unlock(&retu_pm_power_off->mutex);
mfd/retu-mfd.c: if (i2c->addr == 1 && !pm_power_off) {
mfd/retu-mfd.c:     retu_pm_power_off = rdev;
mfd/retu-mfd.c:     pm_power_off      = retu_power_off;
mfd/retu-mfd.c: if (retu_pm_power_off == rdev) {
mfd/retu-mfd.c:     pm_power_off      = NULL;
mfd/retu-mfd.c:     retu_pm_power_off = NULL;
mfd/tps6586x.c: if (pdata->pm_off && !pm_power_off) {
mfd/tps6586x.c:     pm_power_off = tps6586x_power_off;
mfd/rk808.c:    if (pm_off && !pm_power_off) {
mfd/rk808.c:        pm_power_off = pm_pwroff_fn;
mfd/rk808.c:    pm_power_off = NULL;
mfd/axp20x.c:static struct axp20x_dev *axp20x_pm_power_off;
mfd/axp20x.c:   if (axp20x_pm_power_off->variant == AXP288_ID)
mfd/axp20x.c:   regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
mfd/axp20x.c:   if (!pm_power_off) {
mfd/axp20x.c:       axp20x_pm_power_off = axp20x;
mfd/axp20x.c:       pm_power_off = axp20x_power_off;
mfd/axp20x.c:   if (axp20x == axp20x_pm_power_off) {
mfd/axp20x.c:       axp20x_pm_power_off = NULL;
mfd/axp20x.c:       pm_power_off = NULL;
mfd/dm355evm_msp.c: pm_power_off = NULL;
mfd/dm355evm_msp.c: pm_power_off = dm355evm_power_off;
mfd/ab8500-sysctrl.c:   if (!pm_power_off)
mfd/ab8500-sysctrl.c:       pm_power_off = ab8500_power_off;
mfd/ab8500-sysctrl.c:   if (pm_power_off == ab8500_power_off)
mfd/ab8500-sysctrl.c:       pm_power_off = NULL;
mfd/twl4030-power.c:    if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) {
mfd/twl4030-power.c:        pm_power_off = twl4030_power_off;
rtc/rtc-jz4740.c:       if (!pm_power_off) {
rtc/rtc-jz4740.c:           pm_power_off = jz4740_rtc_power_off;
rtc/rtc-omap.c:     if (!pm_power_off) {
rtc/rtc-omap.c:         pm_power_off = omap_rtc_power_off;
rtc/rtc-omap.c: if (pm_power_off == omap_rtc_power_off &&
rtc/rtc-omap.c:     pm_power_off = NULL;
pinctrl/qcom/pinctrl-msm.c:         pm_power_off = msm_ps_hold_poweroff;
memory/emif.c:      if (pm_power_off) {
memory/emif.c:          WARN(1, "FIXME: NO pm_power_off!!! trying restart\n");
staging/nvec/nvec.c:    pm_power_off = nvec_power_off;
staging/nvec/nvec.c:    pm_power_off = NULL;
power/reset/vexpress-poweroff.c:        pm_power_off = vexpress_power_off;
power/reset/restart-poweroff.c: /* If a pm_power_off function has already been added, leave it alone */
power/reset/restart-poweroff.c: if (pm_power_off != NULL) {
power/reset/restart-poweroff.c:         "pm_power_off function already registered");
power/reset/restart-poweroff.c: pm_power_off = &restart_poweroff_do_poweroff;
power/reset/restart-poweroff.c: if (pm_power_off == &restart_poweroff_do_poweroff)
power/reset/restart-poweroff.c:     pm_power_off = NULL;
power/reset/at91-poweroff.c:    pm_power_off = at91_poweroff;
power/reset/at91-poweroff.c:        pm_power_off = at91_lpddr_poweroff;
power/reset/at91-poweroff.c:    if (pm_power_off == at91_poweroff ||
power/reset/at91-poweroff.c:        pm_power_off == at91_lpddr_poweroff)
power/reset/at91-poweroff.c:        pm_power_off = NULL;
power/reset/Kconfig:      say N here or disable in dts to make sure pm_power_off never be
power/reset/qnap-poweroff.c:    if (pm_power_off) {
power/reset/qnap-poweroff.c:        lookup_symbol_name((ulong)pm_power_off, symname);
power/reset/qnap-poweroff.c:            "pm_power_off already claimed %p %s",
power/reset/qnap-poweroff.c:            pm_power_off, symname);
power/reset/qnap-poweroff.c:    pm_power_off = qnap_power_off;
power/reset/qnap-poweroff.c:    pm_power_off = NULL;
power/reset/gpio-poweroff.c: * since pm_power_off itself is global.
power/reset/gpio-poweroff.c:    /* If a pm_power_off function has already been added, leave it alone */
power/reset/gpio-poweroff.c:    if (pm_power_off != NULL) {
power/reset/gpio-poweroff.c:            "%s: pm_power_off function already registered",
power/reset/gpio-poweroff.c:    pm_power_off = &gpio_poweroff_do_poweroff;
power/reset/gpio-poweroff.c:    if (pm_power_off == &gpio_poweroff_do_poweroff)
power/reset/gpio-poweroff.c:        pm_power_off = NULL;
power/reset/gemini-poweroff.c:  pm_power_off = gemini_poweroff;
power/reset/syscon-poweroff.c:  if (pm_power_off) {
power/reset/syscon-poweroff.c:      lookup_symbol_name((ulong)pm_power_off, symname);
power/reset/syscon-poweroff.c:      "pm_power_off already claimed %p %s",
power/reset/syscon-poweroff.c:      pm_power_off, symname);
power/reset/syscon-poweroff.c:  pm_power_off = syscon_poweroff;
power/reset/syscon-poweroff.c:  if (pm_power_off == syscon_poweroff)
power/reset/syscon-poweroff.c:      pm_power_off = NULL;
power/reset/imx-snvs-poweroff.c:    pm_power_off = do_imx_poweroff;
power/reset/piix4-poweroff.c:   pm_power_off = piix4_poweroff;
power/reset/piix4-poweroff.c:   if (pm_power_off == piix4_poweroff)
power/reset/piix4-poweroff.c:       pm_power_off = NULL;
power/reset/at91-sama5d2_shdwc.c: * since pm_power_off itself is global.
power/reset/at91-sama5d2_shdwc.c:   pm_power_off = at91_poweroff;
power/reset/at91-sama5d2_shdwc.c:       pm_power_off = at91_lpddr_poweroff;
power/reset/at91-sama5d2_shdwc.c:   if (pm_power_off == at91_poweroff ||
power/reset/at91-sama5d2_shdwc.c:       pm_power_off == at91_lpddr_poweroff)
power/reset/at91-sama5d2_shdwc.c:       pm_power_off = NULL;
power/reset/ltc2952-poweroff.c: * This global variable is only needed for pm_power_off. We should
power/reset/ltc2952-poweroff.c: if (pm_power_off) {
power/reset/ltc2952-poweroff.c:     dev_err(&pdev->dev, "pm_power_off already registered");
power/reset/ltc2952-poweroff.c: pm_power_off = ltc2952_poweroff_kill;
power/reset/ltc2952-poweroff.c: pm_power_off = NULL;
power/reset/msm-poweroff.c: pm_power_off = do_msm_poweroff;
power/reset/as3722-poweroff.c:static void as3722_pm_power_off(void)
power/reset/as3722-poweroff.c:  if (!pm_power_off)
power/reset/as3722-poweroff.c:      pm_power_off = as3722_pm_power_off;
power/reset/as3722-poweroff.c:  if (pm_power_off == as3722_pm_power_off)
power/reset/as3722-poweroff.c:      pm_power_off = NULL;
acpi/sleep.c:       pm_power_off_prepare = acpi_power_off_prepare;
acpi/sleep.c:       pm_power_off = acpi_power_off;
regulator/act8865-regulator.c:      if (!pm_power_off && (off_reg > 0)) {
regulator/act8865-regulator.c:          pm_power_off = act8865_power_off;
firmware/psci.c:    pm_power_off = psci_sys_poweroff;
firmware/efi/reboot.c:static void (*orig_pm_power_off)(void);
firmware/efi/reboot.c:  if (orig_pm_power_off)
firmware/efi/reboot.c:      orig_pm_power_off();
firmware/efi/reboot.c:      orig_pm_power_off = pm_power_off;
firmware/efi/reboot.c:      pm_power_off = efi_power_off;
watchdog/bcm2835_wdt.c: if (pm_power_off == NULL)
watchdog/bcm2835_wdt.c:     pm_power_off = bcm2835_power_off;
watchdog/bcm2835_wdt.c: if (pm_power_off == bcm2835_power_off)
watchdog/bcm2835_wdt.c:     pm_power_off = NULL;

これでおおよそ、"pm_power_off = "で、もちろんスペース込みで検索すればさらに犯人を絞れます。

$ grep -R -i pm_power_off|grep "pm_power_off = "
platform/x86/pmc_atom.c:        pm_power_off = pmc_power_off;
char/ipmi/ipmi_poweroff.c:  pm_power_off = ipmi_poweroff_function;
char/ipmi/ipmi_poweroff.c:  pm_power_off = old_poweroff_func;
char/ipmi/ipmi_poweroff.c:      pm_power_off = old_poweroff_func;
mfd/tps80031.c:     pm_power_off = tps80031_power_off;
mfd/tps80031.c:     pm_power_off = NULL;
mfd/rn5t618.c:  rn5t618_pm_power_off = priv;
mfd/rn5t618.c:          pm_power_off = rn5t618_power_off;
mfd/rn5t618.c:      rn5t618_pm_power_off = NULL;
mfd/rn5t618.c:      pm_power_off = NULL;
mfd/tps65910.c:     pm_power_off = tps65910_power_off;
mfd/max8907.c:      pm_power_off = max8907_power_off;
mfd/palmas.c:           pm_power_off = palmas_power_off;
mfd/palmas.c:       pm_power_off = NULL;
mfd/retu-mfd.c:     retu_pm_power_off = rdev;
mfd/retu-mfd.c:     retu_pm_power_off = NULL;
mfd/tps6586x.c:     pm_power_off = tps6586x_power_off;
mfd/rk808.c:        pm_power_off = pm_pwroff_fn;
mfd/rk808.c:    pm_power_off = NULL;
mfd/axp20x.c:       axp20x_pm_power_off = axp20x;
mfd/axp20x.c:       pm_power_off = axp20x_power_off;
mfd/axp20x.c:       axp20x_pm_power_off = NULL;
mfd/axp20x.c:       pm_power_off = NULL;
mfd/dm355evm_msp.c: pm_power_off = NULL;
mfd/dm355evm_msp.c: pm_power_off = dm355evm_power_off;
mfd/ab8500-sysctrl.c:       pm_power_off = ab8500_power_off;
mfd/ab8500-sysctrl.c:       pm_power_off = NULL;
mfd/twl4030-power.c:        pm_power_off = twl4030_power_off;
rtc/rtc-jz4740.c:           pm_power_off = jz4740_rtc_power_off;
rtc/rtc-omap.c:         pm_power_off = omap_rtc_power_off;
rtc/rtc-omap.c:     pm_power_off = NULL;
pinctrl/qcom/pinctrl-msm.c:         pm_power_off = msm_ps_hold_poweroff;
staging/nvec/nvec.c:    pm_power_off = nvec_power_off;
staging/nvec/nvec.c:    pm_power_off = NULL;
power/reset/vexpress-poweroff.c:        pm_power_off = vexpress_power_off;
power/reset/restart-poweroff.c: pm_power_off = &restart_poweroff_do_poweroff;
power/reset/restart-poweroff.c:     pm_power_off = NULL;
power/reset/at91-poweroff.c:    pm_power_off = at91_poweroff;
power/reset/at91-poweroff.c:        pm_power_off = at91_lpddr_poweroff;
power/reset/at91-poweroff.c:        pm_power_off = NULL;
power/reset/qnap-poweroff.c:    pm_power_off = qnap_power_off;
power/reset/qnap-poweroff.c:    pm_power_off = NULL;
power/reset/gpio-poweroff.c:    pm_power_off = &gpio_poweroff_do_poweroff;
power/reset/gpio-poweroff.c:        pm_power_off = NULL;
power/reset/gemini-poweroff.c:  pm_power_off = gemini_poweroff;
power/reset/syscon-poweroff.c:  pm_power_off = syscon_poweroff;
power/reset/syscon-poweroff.c:      pm_power_off = NULL;
power/reset/imx-snvs-poweroff.c:    pm_power_off = do_imx_poweroff;
power/reset/piix4-poweroff.c:   pm_power_off = piix4_poweroff;
power/reset/piix4-poweroff.c:       pm_power_off = NULL;
power/reset/at91-sama5d2_shdwc.c:   pm_power_off = at91_poweroff;
power/reset/at91-sama5d2_shdwc.c:       pm_power_off = at91_lpddr_poweroff;
power/reset/at91-sama5d2_shdwc.c:       pm_power_off = NULL;
power/reset/ltc2952-poweroff.c: pm_power_off = ltc2952_poweroff_kill;
power/reset/ltc2952-poweroff.c: pm_power_off = NULL;
power/reset/msm-poweroff.c: pm_power_off = do_msm_poweroff;
power/reset/as3722-poweroff.c:      pm_power_off = as3722_pm_power_off;
power/reset/as3722-poweroff.c:      pm_power_off = NULL;
acpi/sleep.c:       pm_power_off = acpi_power_off;
regulator/act8865-regulator.c:          pm_power_off = act8865_power_off;
firmware/psci.c:    pm_power_off = psci_sys_poweroff;
firmware/efi/reboot.c:      orig_pm_power_off = pm_power_off;
firmware/efi/reboot.c:      pm_power_off = efi_power_off;
watchdog/bcm2835_wdt.c:     pm_power_off = bcm2835_power_off;
watchdog/bcm2835_wdt.c:     pm_power_off = NULL;

オブジェクトが作成されているか確認する

相当な数を絞って、最後にこの中からオブジェクトになっているソースコードのみに絞ります。

そしたら、下記のように3だけがpm_power_offを書き込むのね。

$ grep -R -i pm_power_off|grep "pm_power_off = "
power/reset/ltc2952-poweroff.c: pm_power_off = ltc2952_poweroff_kill;
firmware/psci.c:    pm_power_off = psci_sys_poweroff;
firmware/efi/reboot.c:      pm_power_off = efi_power_off;

printkを入れて犯人探し

3つぐらいの関数ならprintkを入れて実行した一発で答え出ますよ。

root@ultra96:~# dmesg|grep KNL
[    0.000000] [KNL] psci_0_2_set_functions: ffffff800875d4f8
[    1.395875] [KNL] ltc2952_poweroff_probe: ffffff800875d4f8

ほらね。

犯人はfirmware/psci.cでした。

ここからどうするかです

じゃぁ、firmware/psci.cをロードさせているトリガーは何か探す必要が有ります。

このドライバがDeviceTreeでロードされているのか、それとも固定的に組み込まれているドライバなのか判断する必要が有ります。

もし、固定的なドライバならコンフィグで外せるか、もしくは、固定的に組み込まれて勝てないので諦めるかしなければいけません。

これがもし、DeviceTreeでロードされているなら設定の方法によって対照することができる可能性が残っています。

と、compatibleを見てみると・・・

static const struct of_device_id psci_of_match[] __initconst = {
    { .compatible = "arm,psci", .data = psci_0_1_init},
    { .compatible = "arm,psci-0.2", .data = psci_0_2_init},
    { .compatible = "arm,psci-1.0", .data = psci_0_2_init},
    {},
};

DeviceTreeでロードしてるので確認すると・・・

        idle-states {
            entry-method = "arm,psci";

            CPU_SLEEP_0: cpu-sleep-0 {
                compatible = "arm,idle-state";
                arm,psci-suspend-param = <0x40000000>;
                local-timer-stop;
                entry-latency-us = <300>;
                exit-latency-us = <600>;
                min-residency-us = <10000>;
            };
        };
    psci {
        compatible = "arm,psci-0.2";
        method = "smc";
    };

Ultra96のsysfdを確認するとどうも後者側の方で呼び出されているようです。

そこでDeviceTreeからpsciを無効にしました。

そうすると次のようにLTC2954のドライバが読み込まれました。

[    1.462987] ltc2952-poweroff ltc2954: unable to claim gpio "watchdog"
[    4.328691] ltc2952-poweroff ltc2954: probe successful

ここまでできたのですが、poweroffとかshutdownで電源が落ちません。

しかも、シリアルポートが見えないのでどこまで進んだかわからずじまい・・・

まぁ、落ちなくてもいいかぁ・・・

2018年11月10日 20時52分53秒 - Permament Link

Ultra96のBlutetooth

Ulrtra96のBluetoothが動かない問題について結論が出た。

Ultra96を触り始めた、薄い本を書いたときは動いてたのになぁ〜と、Ultra96勉強会でやってみたら全然動かなかった。

薄い本を書いてた当時からはLinux KernelもBlutetoothのFirmwareも入れ替えたりしてたけど、動くものだとほったらかしにしていた。

って、Ulyra96でBluetooth使う人いる?

まずはエラー内容

ほとんどの人がハマっているエラー内容はこれだと思う。

dmesgで確認すると次のように出ると思う。

root@ultra96:~# dmesg|grep -i bluetooth
[    1.307976] Bluetooth: Core ver 2.22
[    1.308013] Bluetooth: HCI device and connection manager initialized
[    1.308026] Bluetooth: HCI socket layer initialized
[    1.308037] Bluetooth: L2CAP socket layer initialized
[    1.308059] Bluetooth: SCO socket layer initialized
[    1.395439] Bluetooth: HCI UART driver ver 2.3
[    1.395450] Bluetooth: HCI UART protocol H4 registered
[    1.395458] Bluetooth: HCI UART protocol BCSP registered
[    1.395492] Bluetooth: HCI UART protocol LL registered
[    1.395501] Bluetooth: HCI UART protocol ATH3K registered
[    1.395509] Bluetooth: HCI UART protocol Three-wire (H5) registered
[    1.395551] Bluetooth: HCI UART protocol Intel registered
[    1.395559] Bluetooth: HCI UART protocol QCA registered
[    1.395720] Bluetooth: Generic Bluetooth SDIO driver ver 0.1
[    1.403387] Bluetooth: RFCOMM TTY layer initialized
[    1.403399] Bluetooth: RFCOMM socket layer initialized
[    1.403417] Bluetooth: RFCOMM ver 1.11
[    1.403428] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    1.403435] Bluetooth: BNEP filters: protocol multicast
[    1.403446] Bluetooth: BNEP socket layer initialized
[    1.403454] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[    1.403464] Bluetooth: HIDP socket layer initialized
[    5.338648] Bluetooth: hci0: change remote baud rate command in firmware ← ここで終わり

Firmwareの問題か?

BluetoothのFirmwareは公式っぽいのがいくつかあって、バージョンが違うようなのです。

TIの公式WebサイトからダウンーどしたものからgithubなどのFirwmwareを試してみたけど、結果は変わらず。

データシートを確認

Bluetoothのログの最後が"change remote baud rate command in firmware"だったのでボーレートかな?と思って、データシートを確認するとBluetoothで使用するUARTのところの最大ボーレートが3Mbpsであった。

そういえば、Zynq MPSoCのUARTってもっと出せるんじゃなかったっけ?

そもそも、最大ボーレートを設定する必要があるのでは?

と、Linux KernelのBluetoothを調べてみるとmax-speedなる宣言があるではないですか?

こんなのどこのドキュメントにも書いてませんよ。

最大スピードなんて設定してなかったのでこれかなぁと思いつつ・・・

ログを眺めていたら

いくつかのバージョンのFirmwareのログを眺めていたら・・・

root@ultra96:~# dmesg|grep -i bluetooth
[    1.307762] Bluetooth: Core ver 2.22
[    1.307796] Bluetooth: HCI device and connection manager initialized
[    1.307809] Bluetooth: HCI socket layer initialized
[    1.307820] Bluetooth: L2CAP socket layer initialized
[    1.307847] Bluetooth: SCO socket layer initialized
[    1.395891] Bluetooth: HCI UART driver ver 2.3
[    1.395902] Bluetooth: HCI UART protocol H4 registered
[    1.395910] Bluetooth: HCI UART protocol BCSP registered
[    1.395939] Bluetooth: HCI UART protocol LL registered
[    1.395947] Bluetooth: HCI UART protocol ATH3K registered
[    1.395955] Bluetooth: HCI UART protocol Three-wire (H5) registered
[    1.395995] Bluetooth: HCI UART protocol Intel registered
[    1.396004] Bluetooth: HCI UART protocol QCA registered
[    1.396168] Bluetooth: Generic Bluetooth SDIO driver ver 0.1
[    1.403734] Bluetooth: RFCOMM TTY layer initialized
[    1.403747] Bluetooth: RFCOMM socket layer initialized
[    1.403764] Bluetooth: RFCOMM ver 1.11
[    1.403780] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    1.403788] Bluetooth: BNEP filters: protocol multicast
[    1.403799] Bluetooth: BNEP socket layer initialized
[    1.403808] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[    1.403818] Bluetooth: HIDP socket layer initialized
[    5.246430] Bluetooth: hci0: change remote baud rate command in firmware ← ここ
[    7.203761] Bluetooth: hci0: sleep command in scr
[    7.706191] Bluetooth: hci0: sleep command in scr
[   14.948453] Bluetooth: hci0 command 0xfe38 tx timeout
[   23.012466] Bluetooth: hci0: send command failed
[   23.017094] Bluetooth: hci0: download firmware failed, retrying...
[   23.560142] Bluetooth: hci0: change remote baud rate command in firmware ← ここ
[   25.412331] Bluetooth: hci0: sleep command in scr
[   25.914661] Bluetooth: hci0: sleep command in scr

あれ?

"change remote baud rate command in firmware"が2回表示されている。

もしかして、Firmwareはちゃんと書き込まれてる?

と、思って、もしかして原因は別のところにある?

もしかして、単にEnableになってないだけ・・・?

HCIを見てみよう

hciconfigなるコマンドがあるらしいので実行してみると・・・

あぁ、やっぱりDOWNやん。

root@ultra96:~# hciconfig hci0 
hci0:   Type: Primary  Bus: UART
    BD Address: 10:CE:A9:E2:B5:AA  ACL MTU: 1021:6  SCO MTU: 180:4
    DOWN 
    RX bytes:4598 acl:0 sco:0 events:597 errors:0
    TX bytes:117960 acl:0 sco:0 commands:598 errors:0

それだったら、upすりゃいいんでしょ。

root@ultra96:~# hciconfig hci0 up
Can't init device hci0: Operation not possible due to RF-kill (132)

ダメやん。

でも、このメッセージが出るってことは・・・

RFを疑ってみた

試しにrfkillしてみる。

root@ultra96:~# rfkill list
0: hci0: bluetooth
    Soft blocked: yes ← ここ
    Hard blocked: no
1: phy0: wlan
    Soft blocked: no
    Hard blocked: no

これやん(苦笑)

結論

rfkillでunblockしたらokなのさ。

root@ultra96:~# rfkill unblock bluetooth
root@ultra96:~# hciconfig hci0 up
root@ultra96:~# hciconfig 
hci0:   Type: Primary  Bus: UART
    BD Address: 10:CE:A9:E2:B5:AA  ACL MTU: 1021:6  SCO MTU: 180:4
    UP RUNNING PSCAN 
    RX bytes:5261 acl:0 sco:0 events:634 errors:0
    TX bytes:118707 acl:0 sco:0 commands:635 errors:0

動作したところでキーボード繋げてみた。

次のようにキーボードも接続できて完了!

root@ultra96:~# bluetoothctl 
[NEW] Controller XX:XX:XX:XX:XX:XX BlueZ 5.48 [default]
[NEW] Device XX:XX:XX:XX:XX:XX SP Abs Fit 2 0149999
[NEW] Device XX:XX:XX:XX:XX:XX KJ-43W870C
[NEW] Device XX:XX:XX:XX:XX:XX SP Body Fit 2 0077772
[NEW] Device XX:XX:XX:XX:XX:XX BSKBB06
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller XX:XX:XX:XX:XX:XX Discovering: yes
[CHG] Device XX:XX:XX:XX:XX:XX RSSI: -73
[CHG] Device XX:XX:XX:XX:XX:XX TxPower: 10
[NEW] Device XX:XX:XX:XX:XX:XX SKB-BT23BK ← これがキーボード
[bluetooth]# pair XX:XX:XX:XX:XX:XX ← キーボードのMACアドレスを入力する
Attempting to pair with XX:XX:XX:XX:XX:XX
[CHG] Device XX:XX:XX:XX:XX:XX Connected: yes
[agent] PIN code: 775270 ← キーボードからこの数字を入力する
[CHG] Device XX:XX:XX:XX:XX:XX ServicesResolved: yes
[CHG] Device XX:XX:XX:XX:XX:XX Paired: yes
Pairing successful
[CHG] Device XX:XX:XX:XX:XX:XX ServicesResolved: no
[CHG] Device XX:XX:XX:XX:XX:XX Connected: no
[bluetooth]# trust XX:XX:XX:XX:XX:XX ← キーボードのMACアドレスを入力して信頼させる
[CHG] Device XX:XX:XX:XX:XX:XX Trusted: yes
Changing XX:XX:XX:XX:XX:XX trust succeeded
[bluetooth]# connect XX:XX:XX:XX:XX:XX ← 最後にキーボードのMACアドレスを入力してコネクションする
Attempting to connect to XX:XX:XX:XX:XX:XX
[CHG] Device XX:XX:XX:XX:XX:XX Connected: yes
Connection successful ← ほら、繋がった

単にLinuxでRFをOffにしていたということだったらしい。

結局、FirmwareはTI公式の最新版で問題なかった。

2018年11月09日 20時07分38秒 - Permament Link

あらあら、もう、11月ですね。

もう、11月ですね。

10月はブログを書かずじまいで過ぎ去ってしまった。

C95(冬コミ)

C95(冬コミ)は当選しました!

ネタは今考えているところです。

今回も薄い本を作ることは間違いなしです。

今のところの候補は次の2つですね。

  • DisplayPortの動作をより詳細に?
  • SDSoCでパーシャルリコンフィグのフレームワークを確立するか?
  • Ultra96でRaspberryPiをg_etherでUSB経由のEthernet接続でgstreamerキャプチャーとか?

とりあえず、締め切りがあと1ヶ月ってことだけが決まっている。

Ultra96勉強会

11月3日(土)はアヴネットで開催されたUltra96勉強会に参加してきました。

SDSoCを追いかけようと思ったのですが、Ultra96のWiFi接続を午後まで引っ張ったせいで何かする時間が確保できなくなってしまい・・・

Bluetoothの接続を確認しようとしたのですが1度だけ、成功しそうな気配があったのですがそれ以外は初期化エラーで動作しなかった。

あとはDisplayPort周辺を確認していたような感じです。

なんか、いいアウトプットが出せず・・・

最後になって気がついたのですがPSからの画像出力とPLからの画像入力の同期がとれてなかったところですがDisplayPortをリセット中に設定して、リセット解除前にPLからSyncを入れてあげなきゃいけないのではないかと思いついたけど時間切れ・・・

Ultra96のDisplayPort

そうそう、Ultra96のDisplayPortなんだけど、PS-GTRを2つ使ってるのね。

LANE0/1を使ってるんだけど、コネクタへの接続を見てみたら、LANE0/1ってひっくり返ってるんだわ。

DisplayPortのGTR用RefClockはPS_MGTRREFCLK1_P/Nの27MHzを使うんだけど、これをGTR_0/1の両方に分配しなきゃいけないよね。

この辺がベアメタルでDisplayPortするために設定が必要なのでは?と、現状の推測です。

GTRの部分はレジスタ値が公開されておらず、ウィザードの設定を突っ込むことになっているので追いかけるのも捗らず・・

まぁ、私の場合はLinuxを動かさないというソリューションが少ないので諦めても良い部分なのですが・・・

時間ができたらGTRの設定値を抜き出して再挑戦かな?

2018年11月05日 23時43分54秒 - Permament Link

Ultra96でUbuntuのXウィンドウ表示に挑戦してみた

FPGAの部屋@marsee101さんがUltra96でDebianとWLANが動かせたということでほったらかしにしていたUbuntuでのWLANを確認したら動作した。

何に引っかかってたか?

よくわからな良いけどwpa_supplicantの設定をミスってたようで・・・

ただ、それだけでした。

Xorgを立ち上げてみるか・・・

WLAN繋がればaptできるので、インストールできる手間が一気に解消される。

そこで、XorgをインスコしてGUIを表示できないか挑戦してみた。

Ultra96のUbuntu環境は16.04.5LTSをベースファイルから構築している。

Xorgインスコしたけどarmsocドライバが無い

インスコしているUbuntuはarm64版でXorgはインスコできるんだけど、armsocドライバがない。

armsocドライバは探してみるとarmhf版しかない。

???

64bit版でドライバが変わったのかな?

apt sourceでソースコードをダウンロードしてビルドしようとしても64bitではサポートしていないというエラーが発生。

どうしたものかな・・・

Xilinxのデモイメージ

ソースコード解析職人の@VengineerからXilinxの「OpenGLWESのデモ」でX-Windowのデモがあると教えてもらったのでUltra96で試してみたら・・・

  • Ubuntu 15.04
  • とにかく、GUIの操作が重い!
  • xorg.confの設定はarmsocドライバを使用

深くは追いかけなかったがUbuntuでarmsocドライバできるのは現時点でarmhfしか選択肢がない。

じゃぁ、YoctoでX-Windowビルドしたら?

Yoctoもcore-image-satoでX-Windowを構築できるので試してみると、Xorgのドライバはarmsocだった。

ただし、Yoctoはフルビルド環境なのでarmsocドライバもビルドしていたので特に問題ない。

まとめ

Ubuntu 64bit環境にはXorgのarmsocドライバが無いので64bit環境でX-Windowを立ち上げるのはほぼ不可能なのかな?

XilinxのようにOpenGLESを使用するためだけdのGUI表示だけであれば、32bit環境でも良いのだけど、ウィンドウ操作が重いのを見るだけで、無理に32bit環境使う必要もないんじゃない?

と、諦めた。

2018年09月24日 10時00分58秒 - Permament Link