2012年03月29日

Jz4770 アンドロイドカーネルソース(ICS)

ICS 対応の新しい アンドロイドカーネルソース が手に入った。

例によって、linux オリジナルに対する 新規ファイル と 差分に分けて整理しておく

ほかに、Toolchain のバイナリもあるが、大きいので割愛。

ちょっと覗いてみる。

  • まずは、defconfig のチェック。

    npm701_ab_defconfig
    npm702_defconfig
    npm702_pinkflozd_defconfig

    一応 paladin 用と basic 用の両方があるようだ。あと、jz4770 のみが対応で他の jz47xx は削除されている。当然 defconfig もない。

    あぁ Jz4760/B は見捨てられたのか ... 2.x 用のソースコードはあるとは言えマージするのは相当に面倒に思える。

    あと、pinkflozd 氏は、様々なチューニングをしている。 大雑把に言うと I/O の効率化? と ライブラリ関数の差し替え が主。バグ修正のような変更はないようだ。

    このカーネルなら、確実に現行のファームウェアのカーネルと差し替えられる。

改造したいところと重なってないことを確認して、usb gadget を見てみる。


    drivers/usb/gadget/android.c:

    static struct android_usb_function *supported_functions[] = {
    &adb_function,
    &acm_function,
    &mtp_function,
    &ptp_function,
    &rndis_function,
    &mass_storage_function,
    &accessory_function,
    NULL
    };

    こんな定義がある。実際に使っていると思われる mass_storage を見ると ...

    static int mass_storage_function_init(struct android_usb_function *f,
    struct usb_composite_dev *cdev)
    {
    :
    :
    nluns = CONFIG_USB_NLUNS_NUM;

    config->fsg.nluns = nluns;
    for (i = 0; i < nluns; i++){
    config->fsg.luns[i].removable = 1;

    /*add by bcjia to use cdrom to lun2*/
    if(i == 2){
    config->fsg.luns[i].cdrom = 1;
    }
    }
    :

    なにやらまさに 2 つの removable + cdrom を作るコードがある。

    イーサネットは、こっち rndis 。

    static int rndis_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
    {
    f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
    if (!f->config)
    return -ENOMEM;
    return 0;
    }

    static int rndis_function_bind_config(struct android_usb_function *f,
    struct usb_configuration *c)
    {
    :
    if (rndis->wceis) {
    /* "Wireless" RNDIS; auto-detected by Windows */
    rndis_iad_descriptor.bFunctionClass =
    USB_CLASS_WIRELESS_CONTROLLER;
    rndis_iad_descriptor.bFunctionSubClass = 0x01;
    rndis_iad_descriptor.bFunctionProtocol = 0x03;
    rndis_control_intf.bInterfaceClass =
    USB_CLASS_WIRELESS_CONTROLLER;
    rndis_control_intf.bInterfaceSubClass = 0x01;
    rndis_control_intf.bInterfaceProtocol = 0x03;
    }
                   :

    なんだかよくわからないがコードは入っているようだ。.... 要するに board でデバイスを定義すると 構成される? それはどうやってやるのだろう?

    ... というか、これって ジェネリックなコードだろうから ググると出てきたりする?

    まぁ、これで PC と接続すると 高速に通信できそうなのは分かったので、一安心。

    その前に ... config できになる点が ...

    CONFIG_USB_MUSB_OTG=y
    CONFIG_USB_GADGET_MUSB_HDRC=y
    CONFIG_USB_MUSB_HDRC_HCD=y
    CONFIG_MUSB_PIO_ONLY=y

    CONFIG_USB_GADGET_DUALSPEED=y

    CONFIG_MUSB_PIO_ONLY .. ってことは、オーバヘッドが大きそうな ... 。ただ、ネットワークはオフロードできる要素がないから、DMA 使っても あまり差がないはず。むしろ 影響があるのは MASS STORAGE 。ファイル転送などで CPU 負荷が上がっていたのはこれのせいだったのか。

最初のビルドを試す。

    pinkflozd 氏 の git には、toolchain の Linux バイナリも含まれるようになった。これでビルドすれば同じものが出来るはず。

    まずは、gcc -v

    Target: mips-linux-gnu
    Configured with: /home/fu/dev/gcc44/gcc/configure --target=mips-linux-gnu \
    --prefix=/home/fu/dev/gcc44/build-linux/tools \
    --with-sysroot=/home/fu/dev/gcc44/build-linux/sysroot \
    --enable-__cxa_atexit --disable-libssp --disable-libgomp --disable-libmudflap \
    --enable-languages=c,c++ --with-mpfr=/home/fu/bin --with-gmp=/home/fu/bin \
    --with-llsc --disable-decimal-float --disable-fixed-point --with-mips-plt \
    --with-arch=mips32r2
    Thread model: posix
    gcc version 4.4.3 20100121 (prerelease) [gcc-4_4-branch revision 156102] (GCC)

    --with-llsc , --disable-decimal-float と --with-mips-plt は知らなかったオプション。

    ちなみに multilib は、soft-float と mips32 ( +soft-float/mips32 ) が含まれている。

    次に ベース (Ingenic-Linux 3.0.8 r1123) をビルドしてみる。

    # cp arch/mips/configs/npm702_defconfig .config
    # make

    これだけで zImage まで ビルドしてくれた。

    途中で board の選択メニューが出るのだが ...

    7. Ingenic JZ4770 NPM703 board (JZ4770_NPM703)
    :
    10. Ingenic JZ4770 AURORA board (JZ4770_AURORA)

    興味深いことに AURORA がある。AURORA が MIPS になる可能性はやはりあったようだ。NPM703 は何だろう? NPM701 が basic で NPM702 は paladin ... MIPS 版 elf ( = swordman) あたり?

    これらの選択枝は、Kconfig 上だけの話で、arch/mips/jz4770/boards には、npm702 しかない。(npm701 すら存在していない)

    あと、作られるモジュールは、
     drivers/scsi/scsi_wait_scan.ko
    のみ。

    さて、mxu_as はどこで動くのか? arch/mips/process.c が まず MXU 命令を使っているのだが、調べていくと ... mips-linux-gnu-as で MXU 命令入りのコードが通る。

    57c: 24020003 li v0,3
    580: 7002042f s32i2m xr16,v0
    584: 3c028000 lui v0,0x8000

    objdump -d でも 対応している。これは! ちゃんと対応して、もはや mxu_as は使わなくなったということか。

    次に 3.0.23 を試す。

    # cp arch/mips/configs/npm702_pinkflozd_defconfig .config
    # make

    これも無事終わる。作られるモジュールは、以下のもの。

    drivers/scsi/scsi_wait_scan.ko
    fs/btrfs/btrfs.ko
    fs/exportfs/exportfs.ko
    fs/jfs/jfs.ko
    fs/reiserfs/reiserfs.ko
    fs/xfs/xfs.ko

    CIFS は =y (モジュールではなく組み込み)

    ところで Wifi はどうしているのだろう? 公式ファームウェアでは唯一の モジュールで
     lib/wifi/modules/iw/dhd.ko
    にあるわけだが ...


    CONFIG_WIFI_BRCM=y

    config WIFI_BRCM
    bool "Broadcom"
    depends on JZSOC
    select WIRELESS_EXT
    select WEXT_PRIV
    select FW_LOADER
    help
    This option contains static memory allocation for 4319 and 4329

    BCM4319 あるいは 4329 だったっけ? それだと CONFIG_BCM4329 が別にあるのだが ... これは使えないのだろうか?

    Wireless LAN (WLAN) [Y/n/?] y
    USB ZD1201 based Wireless device support (USB_ZD1201) [N/m/y/?] n
    Enable WiFi control function abstraction (WIFI_CONTROL_FUNC) [N/y/?] n
    Broadcom 4329 wireless cards support (BCM4329) [M/n/y/?] m
    Firmware path (BCM4329_FW_PATH) [/system/etc/firmware/fw_bcm4329.bin] (NEW)
    NVRAM path (BCM4329_NVRAM_PATH) [/proc/calibration] (NEW)
    Broadcom 4329/30 wireless cards support (BCMDHD) [N/m/y/?] n
    IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP) (HOSTAP) [N/m/y/?] n
    Broadcom (WIFI_BRCM) [Y/n/?] y


    そういえば .. fw_xxx.bin は 次のものだった。
     lib/wifi/firmware/iw8101/fw_iw8101.bin

    iw8101 とは何? ここらをクリアしないと いつまでも dhd.ko に縛られることになる。

    ちなみに dhd.ko を strings で見てみると...

    license=GPL v2
    Compiled in .../work/npm702-4.0.3-1230/nda/wifi/broadcom/5.90.125.69/open-src/..

    NDA と open-src , GPL v2 という矛盾した 文字列が見える。

    あと、http://linuxwireless.org/en/users/Drivers/brcm80211 ここにあるのは何?

    brcm80211でサポートしている SDIO チップは、BCM4329/BCM4330 。BCM4329 は、Wi-Fi(a/b/g/n) とBluetooth あと FM ラジオとトランスミッタの機能がある。「Nexus One」や「iPad」も採用とのこと。

    config WIFI_BRCM が =y になっているのだから BCM4329 かそのあたりのチップのはず。いっそのこと BCM4329 そのものだと面白いのだが...

    http://forum.xda-developers.com/archive/index.php/t-906628.html

    このあたりを見ると ... やっぱり BCM4329 という気がしてくる。ちなみに DHD は Dongle Host Driver の略のようだ。

    [DHD] DHD: dongle ram size is set to 245760(orig 245760)
    [DHD] load firmware from /system/lib/wifi/firmware/iw8101/fw_iw8101.bin
    [DHD] dhdsdio_download_nvram: nvram_path=/system/lib/wifi/firmware/iw8101/nvram_iw8101.txt
    Dongle Host Driver, version 5.90.125.69

    これは、basic の dmesg なのだが、BCM4329 と ram size が違う (BCM4329 は、294912) 。

    http://nv-tegra.nvidia.com/gitweb/?p=android/platform/system/wlan/broadcom.git

    ちょっとバージョンが古いが、ここにもそれらしきドライバーがある。BCM4325 というチップにも対応しているようだ。BCM4325 は、a/b/g 対応なのが違いらしい。paladin の spec を見なおしたら a/b/g/n 対応らしい。--- ということは BCM4329 以降?

    意外にも高機能なチップを使っているようだ。その割に 調子が悪いのだが ... 。

    brcm80211 ドライバは次のところにあるという説明がある。

    git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git

    これは、https://git.kernel.org からもたどれるのだが、コードを見ると確かに BCM4329/BCM4330 にしか対応していない。そして、ramsize は、いずれも 0x48000 = 294912 。(245760 は、0x3c000)

    で、一体どんなチップなのか? 途方にくれたのだが .... すなおに iw8101 を検索したら BCM4336 とのこと。で、BCM4336 のコードは、どこにもないようだ。Dongle Host Driver の version 5.x が手に入ることがあれば、なんとかなりそうだが ... まぁ無理だろう。dhd.ko を使っていく他なさそうだ。

    追記: カーネルソースに dhd ドライバが含まれていた。下記参照。

これで何をするのか?

    とりあえず、USB でつなぎっぱなしにして、Host から ssh でログインできるものが欲しい。共有ファイルシステムは、CIFS よりは NFS が使いたい。

    swap も必須。ログインしているときは、Android 側は、swap に行って欲しい。... これを、ちゃんと実現するには、Android 側に スリープしていると錯覚させる仕組みが必要か?

    あとは、バッテリーをフル充電しない仕組みをなんとかする。充電を切ることができる インターフェイスがあれば .. ログインして使うのを前提に、普通の実行ファイルで作れそう。

    で、作っていた RHEL6 もどきの続きをするのだ。

    あとは、スターンドアローンで使うときの不具合なんかの修正。

    custom ROM 0.8 でスリープが具合悪いらしい。... というか、正規のファームウェアでも具合が悪いバージョンが 多々あるような。一旦ホーム画面にしてスリープしないとサウンドがなり続けたり。

    こういうことを考えると ... custom ROM 0.8 ベースが良いかも知れない。

    ちなみに、Windows でも USB gadget の network が、標準ドライバで使える。ルーティングも Windows 側がルータになる設定が可能らしい。Windows で ssh も問題なく使えるから Host を Linux に限定することはないかも知れない。CIFS は、ファイル置き場には使える。ワークファイルは、microSD にせざるを得ないが、2000 円ほどの microSD (たぶん SanDisk OEM) は幸いなことに小I/O が速い。

おまけ(2012/4/2)

    カーネルをビルドまでして使うなら、開発機がいつまで入手可能なのかが気になるところ。

    赤札天国では、basic (白/黒)、paladin(白)が売り切れで、paladin(黒)のみ。値段を 7980円に下げての販売で 売り切りっぽい。
    pandawill も basic (白/黒)、paladin(黒)が売り切れで、paladin(白)のみ。価格は、99.99 ドル。

    paladin が入手可能な (ほぼ)唯一の Jz4770 機で、ICS 対応の (ほぼ)唯一の MIPS 機なのだから、末永く売ってもらいたいこころなのだが....

    ちなみに、DealExtreame , focalprice でも 取り扱いはある。

    追記: ここ (UNICONE というショップ) でも取り扱っている。2012/5/21 までの取り扱いだが、送料無料で 8600円と 結構安い。過去に Ronzi A3 も取り扱っていたようだ。

github.com/naobsd/ingenic_android-3.0

    これを精査してみることに。

    基本は、最初に載せた ベース (Ingenic-Linux 3.0.8 r1123) と同じものではあるのだが... 微妙な違いがある。

    まず、最初のは 改行が CR+LF になっている点。統一されていないという点であまり良くない。

    arch/mips/configs/npm701_ab_defconfig
    arch/mips/jz4770/boards/npm701
    drivers/net/wireless/bcmdhd/dhd_cfg80211.c
    drivers/net/wireless/bcmdhd/dhd_cfg80211.h
    drivers/net/wireless/bcmdhd/wl_linux_mon.c
    include/trace/events/cpufreq_interactive.h

    次に以上のファイル(/dir) が 追加になっている。

    で、よくよく見ると drivers/net/wireless/bcmdhd が ingenic 版と AOSP では全く違う。
    ingenic 版は、古いものをベースとしているようだ。

      先に書いておくが、

      AOSP 版 Dongle Host Driver, version 5.90.195.46
      ingenic 版 Dongle Host Driver, version 5.90.125.94

      だった。上で思い悩んでいたのは何だったのだろう?

    いま一度整理してみることにした。

  • android-linux-3.0.8.tar.gz
  • android-linux-3.0.8.patch.gz
  • android-linux-3.0.8-bcmdhd.tar.gz
  • android-linux-3.0.8-bcmdhd.patch.gz

    ここまでが、AOSP (+MIPS)

  • android-linux-3.0.8-ingenic.tar.gz
  • android-linux-3.0.8-ingenic.patch.gz
  • android-linux-3.0.8-vivante.tar.gz
  • android-linux-3.0.8-vivante.patch.gz
  • android-linux-3.0.8-bcmdhd-ingenic.tar.gz
  • android-linux-3.0.8-bcmdhd-ingenic.patch.gz

    ここまでが Ingenic r1123 。android-linux-3.0.8-bcmdhd.tar.gz を 再度上書きすれば、 AOSP 版 に戻せるようにしている。

    -vivante は、GC860 ドライバ -- 規模を見るために分離してみた。(bcmdhd と vivante が AOSP / ingenic の修正それぞれの半分ぐらい占める。-- でかいから分離独立。)

    さて、興味があるのは、bcmdhd ドライバ。2 つあるわけだが、これらが実際にビルドできるのか?ちなみに、両方ともに BCM4336 をサポートしているような ...


    # CONFIG_WIFI_CONTROL_FUNC is not set
    # CONFIG_BCM4329 is not set
    CONFIG_BCMDHD=m
    CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/fw_bcmdhd.bin"
    CONFIG_BCMDHD_NVRAM_PATH="/system/etc/wifi/bcmdhd.cal"
    # CONFIG_BCMDHD_WEXT is not set
    # CONFIG_DHD_USE_STATIC_BUF is not set
    # CONFIG_HOSTAP is not set
    CONFIG_WIFI_BRCM=y

    とりあえず AOSP 版を これでやってみると ...

    ERROR: "wlcfg_drv_priv" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!
    ERROR: "wl_dbg_level" [drivers/net/wireless/bcmdhd/bcmdhd.ko] undefined!

    zImage が出来た後 module のビルドで こんなエラーが出た。まぁこの程度なら調べる気も起きる。

      Makefile を見てみたが、dhd_cfg80211.o が余計なような ...

    ingenic 版は、drivers/net/wireless/bcmdhd/bcmdhd.ko がちゃんと出来上がった。ただし、動かすためには、firmware が必要。

    /system/lib/wifi/firmware/iw8101/fw_iw8101.bin (FW)
    /system/lib/wifi/firmware/iw8101/nvram_iw8101.txt (NVRAM)

    オリジナルはここにあるわけだから、少なくとも パスを変更する必要がある。-- ただ これが bcmdhd ドライバと互換性があるのかどうかは不明。違う名前なのだから ID ぐらい違うかも知れない。

usb gadget の件

    コードを見ていたら /sys/class/android_usb/android0/ というインターフェイスになっているので、ググってみたら ...

  • Androidのadbのメモ(10) adbdの起動のトリガー

    こんな記事がみつかった。... なるほど sys.usb.config に rndis,adb とでも書けば良さそうな .... カーネルビルドの必要ないのか

      ちなみに、sys.usb.config は、initramfs の default.prop に記述されるもの


      on property:sys.usb.config=rndis
      write /sys/class/usb_composite/rndis/enable 1
      setprop sys.usb.state $sys.usb.config

      on property:sys.usb.config=rndis,adb
      write /sys/class/usb_composite/rndis/enable 1
      write /sys/class/usb_composite/adb/enable 1
      start adbd
      setprop sys.usb.state $sys.usb.config

      on property:sys.usb.config=mass_storage,rndis,adb
      write /sys/class/usb_composite/usb_mass_storage/enable 1
      write /sys/class/usb_composite/rndis/enable 1
      write /sys/class/usb_composite/adb/enable 1
      start adbd
      setprop sys.usb.state $sys.usb.config

      ググるとこんな記述が見つかるのだが、paladin の init.rc はこんな風になっていない。
      簡単に対応できるようなものではなさそう。

    CONFIG_USB_NLUNS_NUM=2

    ちなみに、CDROM を出さないようにするには、カーネルビルドが必要になる。

充電を止めるには?

    #define GPIO_CHARG_SET GPF13
    #define GPIO_CHARG_DETE GPF14

    npm701.h/npm702.h ともにこういう定義はある。だが、使っていない。

    あと、npm702-pm.c

    {32 * 5 + 13, GSS_INPUT_PULL}, /* NC */
    {32 * 5 + 14, GSS_INPUT_NOPULL}, /* CHARG_STAT_N */
    {32 * 5 + 15, GSS_INPUT_PULL}, /* NC, CHARG_CURENT_SET */

    GSS_INPUT_PULL となっているが pull-up なのか pull-down なのかは、ピンによって決まっている。確かデータシートには書いてあったはず。

      確認した。いずれも pullup で 8mA のドライブ能力。

    さて、充電用 IC が 定番の LTC4054(互換) だとすると ... STAT 端子が CHARG_STAT_N に接続されていることになる。

    あと PROG 端子と GND の間にいれる抵抗の値によって最大充電電流が決まる。FET を使って AC 電源時の充電電流を変える回路は簡単で実際に良く使われている。ソフトでも制御できるような回路になっていて GPF15 に接続されている可能性はある。

    PROG 端子を FET を使って抵抗から切り離せば、充電禁止。LTC4054 を使ってできる制御はこれぐらいなのだが ... うまく当てはまりそうな ... 。だとすると GPF13 を出力 L で 充電禁止にできるかも。 NC とも書いてあるから、出来なくともやむを得ないが ...

    ただ、sleep 時には、充電禁止が解除されるし、それが正しい制御だろう。これを踏まえて充電禁止のコードを作るのは、少々面倒かも。

basic のビルド

    basic のビルドもやってみることにした。

    実際にやってみるとコンパイルエラーになる。調べてみると AT070TN93 ドライバの不整合が原因のようだ。

  • 02_npm701-AT070TN93.patch

    とりあえずパッチを作ってみた。

  • 01_distclean-fix.patch

    ついでなのだが、このパッチは、boards の Makefile から存在しないディレクトリのものを削除するもの。こうしておかないと Make distclean とかでエラーになってしまう。

    あと config 。paladin とは、入れているドライバが随分違うようなので、趣味が大分入っているが 合わせた config を作ってみた。

  • npm701_suz_defconfig (basic)
  • npm702_suz_defconfig (paladin)

      CONFIG_VT=y
      CONFIG_CONSOLE_TRANSLATIONS=y
      CONFIG_VT_CONSOLE=y
      CONFIG_HW_CONSOLE=y

    気になるのは、これ 。basic に入っていたので、VT_CONSOLE=y としてみたが... 意味あるのかどうか。

      CONFIG_USB_ACM=m
      CONFIG_USB_SERIAL_CP210X=m
      CONFIG_USB_SERIAL_FTDI_SIO=m
      CONFIG_USB_SERIAL_PL2303=m

      CONFIG_BINFMT_MISC=m

      CONFIG_BCMDHD=m
      CONFIG_BCMDHD_FW_PATH="/system/lib/wifi/firmware/iw8101/fw_iw8101.bin"
      CONFIG_BCMDHD_NVRAM_PATH="/system/lib/wifi/firmware/iw8101/fw_iw8101.bin"

    趣味で入れたのは大体 =m (モジュール)にしている。

      # CONFIG_NTFS_FS is not set
      # CONFIG_NFS_FS is not set
      # CONFIG_NFSD is not set
      # CONFIG_CIFS is not set

    こういうのも入れておきたいが未だ。CONFIG_BT も入れたい。そういえば CONFIG_NLS_CODEPAGE もデフォルトのままだ。ちなみに CONFIG_FUSE_FS=y となっていて、NTFS は FUSE 版が入っているはず。

      CONFIG_USB_NLUNS_NUM=3

    これも 2 に変更したいが、ユーザランドとの整合性があるし未だ。

サスペンド時の リフレッシュレート 変更

    どうやって設定すべきなのか調べていないが、ToDo のひとつとしてあげておこう。

    サスペンドでは、たぶん DRAM のリフレッシュが 消費電流の支配的要因のひとつ。Jz47xx は、たしかセルフリフレッシュと メモリコントローラによるリフレッシュが選べたはず。どっちを使っているかもチェックが必要。

    たぶん保証外な リフレッシュレート にすることになると思うが、うまくいけば待機時間を 2 倍ほどに伸ばせるかも知れない。

      arch/mips/jz4770/common/pm.c: jz_pm_do_sleep()
      が sleep というか、サスペンドの処理だった。

      で、みてみると ... PLL まで止める。 DRAM は、セルフリフレッシュモードになる。クロックを供給しないから、設定できる要素はない ... はず。

      セルフリフレッシュモードでの消費電流は、ISSI の DDR2 2Gb(256MB) は、12 mA。ただし 512 MB では 2 個使うし、電源電圧は、1.8V 。スイッチングレギュレータで降圧しているので、バッテリーの電圧では、10数 mA になりそう。一方 paladin の実測値はスリープ時 12.2 mA だそうだ。

      追記: Paladin は、H5PS1G83EFR (1Gb = 128MB, DDR2-800) x4 だった。データシートは入手できていない。basic は、HY5PS1G831CFP x4 でひとつ 8mA (Max) LFP なら 5mA(Max) 。ちなみに、動作時の消費電流は 225mA(IDD4W,IDD4W) (Max) 。どうもかなりの部分が DRAM で消費されるみたいだ。

      jzsoc_do_sleep() で、on-board modules を停止させているらしいが、本当にすべてなのかどうかは不明。LCD やタッチパネル、アンプを Off しているのかどうか? 大丈夫だとは思うがチェックはしておきたい。

      ついでに idle のコードチェック

      arch/mips/kernel/cpu-probe.c: cpu_wait = JZ4770_wait_irqoff;

      r4k_wait から変更になったようだ。ただ、CPU クロックを低くしたりはしていない。そんなことは不要なのかどうか?

      あと Android のスリープ状態とは何だろう? 2 段階あるのは分かるが、浅いほうは、ただの idle ?

      ところで、 サスペンドのコードを見ていると ...

      arch/mips/jz4770/include/mach/chip-misc.h cache_prefetch(label) というのがあった。

      これは、label から 128 キャッシュライン (4KB ?) コードをキャッシュにロードするもの。
      で、jz_set_div() という関数で これを使っている。

      どうも PLL を設定しているようだ。この間メモリにはアクセスできないということ。

      もちろん DMA 等もダメだから、サスペンドからの復帰でしか使えないわけだが ... サスペンドからの復帰なら PLL を含むクロックの変更が可能ということ。1GHz から 1.2 GHz にするようなことが、このポイントなら出来るかも知れない。

    ついでなので ... jz4770 には、BDMA という インテリジェントDMA 機能がある。この機能は、Linux では DMA_ENGINE として実装するもののようだ。Programmers Manual は入手できていないが、jz4760 にも同じ機能があるので実装できる可能性がある。 ただキャッシュコヒーレンシがあるのが前提だろうから、ただ移植すれば良いものではないかも知れない。

    BDMA の定義自体は、ヘッダファイルには、きっちり入っている。ただし、BDMAC (BCH & NAND DMA Controller) という説明。BDMA は、デスクリプタも使えて、メモリコピーにも使えるのだが ...

    NAND を直接使っていないから もちろん使ってはいないのだが、勝手に使って良いものかどうか。3CH あるから、1つ2つ DMA_ENGINEに回しても 問題はなさそうだが..

    ちょっと調べたのだが、 デスクリプタの構造が定義されていないような ... jz4760_pm にはちゃんと書いてあったので簡単に説明すると 4-word または 8-word の 2 種類のデスクリプタが選べるが デスクリプタをチェーンする場合は 8-word になる。その場合 32 バイト境界でないといけない。Stride という概念があって、二次元の矩形データを他の二次元データに書き込むような目的に使える。(ただし、DMA_ENGINEはそんな機能はサポートしてないはず)

usbboot-tool

    usbboot on Ronzi A3 という記事で Linux 用 usbboot-tool のアナウンスが。Qt を使った GUI 版もあるそうだ。

    ソースコードは、ここ 。Ronzi A3 用のように書いてあるが、Ingenic のコードを移植したなら、全ての Jz47xx に対応しているはず。

    まったく関係ないのだが、USBBOOT つながりで。Allwinner A10 のブートシーケンスが ここに に書いてあった。

    どうも、sdcard slot 0 → nand flash → sdcard slot 2 の順番でスキャンするらしい。A10 には、USBBOOT のようなツールがあるのだが、nand flash が壊れてしまうと 動かないはず。sdcard にブートローダを仕込めばなんとかなりそうだが、やり方は多分知られていない。

      訂正: これだいぶ間違っていた。sdcard のブートに行く前に USB からの BOOT をするかどうかの判断が入る。要するに Jz47xx と同様 USB からブートできる。USB からのブートでは、ボタンを数回押すという変なオペレーションになっているが、これが BROM でサポートしているとは思なかったので誤解していた。

      ところで A10 の カーネルソースコードも入手してみた。A10の機種は NAND FLASH を直に接続しているようなのだが、どういう制御を しているか興味があったため。

      みてみると、mtd は使っておらず drivers/block/sun4i_nand という独自のドライバーを使っていた。WEAR_LEVELLING もサポートしているようで、SDカードを直に使うような使い勝手になっている模様。MTD+UBI よりは随分使いやすそうだ。ただ、再インストールで書き込み回数の情報はどうなってしまうのか? このあたりがきになる。いずれ調査してみよう。

      A10 用の 新しいソースコードが出ている。linux-3.0.8 になって Ingenic のカーネルとの比較がしやすくなった。見てみると 追加になったドライバーが膨大で tar+gzip で 35MB にものぼる。 そのなかで興味深いのは、drivers/block の NAND 関係、sun5i_nand/ が追加になっている。

    最近話題になっている FT701W も USBBOOT が出来るようだ。『FT701Wでomap4bootに成功!』なんて記事がある。ただこれは、どっちの方式だろう? A10方式かも。

    こういうのを見てもわかるように、USBBOOT は便利なのだ。特に カーネル開発者にとっては。さらに カーネルは、Windows ではビルドできないので Linux で USBBOOT が動くのは 嬉しかったりする。

ちょっとビルドしてみる。

    どうも jzboot , xbboot あたりの ファイルが足りない。

    しょうがないので、
  • http://projects.qi-hardware.com/index.php/p/xburst-tools/downloads/

    ここから xburst-tools_201105.tar.bz2 を取ってきて足りない ファイルを埋める。(jzboot 全部, xbboot 全部)

    基本的に

    ./autogen.sh
    ./configure --enable-firmware CROSS_COMPILE=mipsel-linux- --prefix=/usr --sysconfdir=/etc

    とするようだ。

    さて、最初に引っかかるのは、libconfuse 。confuse-2.7.tar.gz これをインストールして再挑戦。

    次に引っかかるのが、 libusb の 1.x 。これはパッケージがあったので、devel をインストール。

    バイナリの作成に カーネル作成で使った Toolchain (mips-linux-gnu- ) を使ってみたのだが ... gcc のオプションに -EL を指定しないと Bigendian になってしまうようで 具合が悪い。

    ここを直しても xburst_stage2 のビルドで nrecognized option `-call_nonpic' なんて言われてしまう。

    configure で --disable-firmware とすると xburst_stage1 , xburst_stage2 を作らないらしいので、これで ビルドしてみたら とりあえずツールだけを作成して正常終了する。

    qt 版は、usbboot の下にある QtUSBBoot , configure 未対応だから qt4 環境を用意して手動でビルド。

追記: ACT8600

    PMU (Power Managiment Unit) として ACT8600 というチップが使われているのだが、思いついて ググってみたら データシート が見つかった。

    よくよく見れば ... Advanced PMU for Ingenic JZ4760/60B/70 と書いてある。なんと専用!

    ... ほかのプロセッサ専用の チップもあるから、専用といっても 最適化したという意味でしかない。I2C で 電圧をプログラミング可能な Step-down 3ch と Step-up 1ch の DC-DC コンバーター や 数 ch の レギュレータ、 バッテリー充電の機能まである。... なるほど こいつが充電していたのか。

    さて、充電のための ピンは、

    nSTAT : 充電中 on になる Open Drain 出力 (基本LED用 , 状態はレジスタでも読める)
    ISET : GND との間に入れる抵抗値で充電電流を設定
    CHGLEV : 充電電流の制御 L: 75mA H: 450mA or 900mA (最大)

    CHGLEV が充電電流を制御できるピンなのだが、充電自体を Off にはできないようだ。たぶん L が USB 充電 + フル動作の設定で、H は、AC アダプタ または USB 充電 時の充電設定。

    その他に機能はないか 調べてみると... レジスタでいくつか設定できる項目が ...

    APCH 0xA1 bit 7 に SUSCHG という 項目がある。これは 1 で充電を サスペンドするもの。

    ついに充電停止のやりかたを見つけたようだ。

    さて、もうすこし調べてみる。充電を停止するだけでは、バッテリーを減らすことはできない。無理やり 50% などにすることが出来そうかどうか ...

    よくわからないのだが ... ONQ3(OTG 0xB0 bit5) というレジスタがある。これは、USB を 外部電源として 使うかどうかの制御のようなのだ。USB は OTG もサポートしているから、電源があっても使わない設定が 出来るに違いなく それはこれではないか と思える。

    これらのことが分かったので、USB でホストと常時接続しても バッテリーを 50% に押さえるような使い方はできそうだ。ところで、サスペンド時はどう設定できるのか? ACT8600 はたぶん生きているので、そのまま という設定は可能なような気がする。だが、外部電源があれば、サスペンドそのものをしない(スリープはする) という やりかたはできる。そうであれば、サスペンド時は、デフォルトの動作(= 充電する)ということでも良いのかも知れない。あと電源 Off 時。このときの動作の設定は無理そう。やれるのかも知れないが ... デフォルトの動作(= 充電する)で良さそう。

    以上考察してみたが ... これは Paladin と Basic のみが関係する。Philips の 機種でも 適用できそうではあるが、Ronzi A3 は 関係ない。Ronzi A3 だと ACT8600 は使っていない。

    ACT8600 関係のコードを見てみる

    drivers/power/act8600_power.c
    drivers/power/jz47xx_battery/act8600_interface.c
    include/linux/act8600_interface.h
    include/linux/act8600_power.h

    関係ありそうなのはこのあたり。act8600_interface.c が、android としてのインターフェイスを 受け持つのだろう。ちょっと見てみる。

    act8600_read_reg(ACT8600_APCH_INTR1,&intr1);
    act8600_read_reg(ACT8600_OTG_CON,&otg_con);

    こんな感じで I2C の先のレジスタを制御している。( 書き込む場合は act8600_write_reg()) 。

    config 関係は、

    CONFIG_ACTBAT_DC
    CONFIG_ACTBAT_USB
    CONFIG_ACT8600_HAS_CHARGE_LED

    ACTBAT_DC は、AC アダプタからの 充電サポート。ACTBAT_USB は、USB からの充電サポートということらしい。ACT8600_HAS_CHARGE_LED は LED のありなしで制御をちょっと変えている -- 意味がわからない。

    さて、上記の制御関係。

    case ACT8600_APCH_STAT_STATE_SUSPEND:
    :
    act8600_set_q3(1);
    :

    なんて 関係ありそうなコードが。充電のサスペンド状態を見つけると 無条件に外部電源を enable にするような雰囲気。ここは変えないと。

    次に act8600_power.c

    probe で、 act8600_set_q3(1) をやっている。それ以外には、boards/npm702/npm702-misc.c 。(0) としているところはない。

    ちなみに 充電のサスペンドは、バッテリーが抜かれたり、電源異常? でも起きる。バッテリーをわざと消費したいのでなければ、外部電源にすみやかにするわけだ。

    制御的には、バッテリーをわざと消費したい という状態を作って act8600_set_q3(0) とするとともに 充電をサスペンドすれば良さそう。 で、状態をアプリから設定できるようにする 。そのために /proc に制御用のエントリを作ったりしてインターフェイスを作る。

    こんなところか。

    ところで ... RTC が結構ずれる。10 分とか平気で。

    /*new cpu need rtc power 3.3v , use pmu default value */
    if(strcmp(jz4770_cpu_version,JZ4770_V1)) {
    /** change rtc power to 2.35V **/
    act8600_write_reg(0x91,0xd0);
    act8600_write_reg(0x90,0x17);
    act8600_write_reg(0x91,0xc0);

    こんなコードがあるのだが ... 電圧を変えたらずれも少しは変わるのかなと思ってみたり。
    試してみたいような ...
posted by すz at 18:27| Comment(9) | TrackBack(0) | Jz47xx(Linux)

2012年01月16日

Jz47xx アンドロイドカーネルソース

アンドロイド用のカーネルソースがついに手にはいった。

    http://bbs.imp3.net/thread-10520163-1-1.html 

    ものはここ。カーネルだけでなく Android のソース で 333MB 。教えてくれた fun さんに感謝。

    一見すると不完全なソースに見えるが、Ingenic は前から 標準カーネルに上書きするソースだけを提供している。これもまた、ベースとなる 2.6.32.9 に上書きすれば良いはず。

    さて、まず確認したいのは、defconfig がどうなっているか? ベースとなるものがないとビルドするのは大変なのだ。

    arch/mips/configs を見ると

    • pisces_defconfig
    • npm701_defconfig
    • npm701_ab_defconfig
    • maple_defconfig

    がある。pisces というのは、Ingenic が出している リファレンスのボード(だと思う)。npm701 は novo7 basic のこと。2 種類あるのは何だろう? maple は何?

    ともかく、basic 用はビルドできそうだ。ひとまず安心。paladin は分からないが、なんとかなりそうな気がする。(カーネルは共通という気もするが まったく未確認)

      npm701 : CONFIG_NPM701_V_1_0=y
      npm701_ab: CONFIG_NPM701_V_1_1=y

      npm701 用カーネルの ver 1.0 と ver 1.1 の違いということで、npm701_ab を使うのが正しそう。paladin で使えるものなのかどうかは、コード見ても分からないはず。bootimg の中のカーネルだけ basic 用を 入れて動けば 共通かどうかは確認できる。

      追記: V_1_0/V_1_1 の違いは、カーネルの違いではなく ボードの違いだった。V_1_0 はたぶん Basic のプロトタイプで GPIO の割り当てもだいぶ違うようだ。このノリだと GPIO の割り当てが変わってしまっていると思えるから、Paladin 用カーネルは 作るのが難しそう。

      この割当は、arch/mips/mach-jz4770/boards/npm701/npm701.h に定義されている。一例をあげると次のような割り当てがある。

        GPIO_SD2_VCC_EN_N
        GPIO_HA2605_INT
        GPIO_VOLUMEUP
        GPIO_OTG_ID_PIN
        GPIO_HDMI_INT_N

        GPIO_LCD_PWM
        GPIO_USB_DETE
        GPIO_CHARG_DETE
        GPIO_CHARG_SET
        GPIO_LCD_VCC_EN
        GPIO_TP_DRV_EN

      要するに内部デバイスの 状態とか 電源ON とか ボタンとか そういうものの GPIO 割り当て。V_1_0 と V_1_1 でも結構違うが、basic と paladin の基板はまったく違う。GPIO 割り当ても随分違うことを覚悟しないといけない。

      Linux が動いている実機があるわけで、このうちのいくつかは、割り当てを見つけ出せるだろう。最悪はそういう努力をして 見つけていけば良いのだが ... 新機種もあるし コードを貰えるように努力した方が実りが多そうだ。

      ちなみに見つけるには、いろいろヒントがある。出力ピンは 、GPIO が出力に設定されているはずだし、割り込みに使うピンは、そういう設定がされているはず。デバッグメッセージもヒントになるものがあるかも知れない。これらで条件を絞った上で、実際の動作での状態変化を見る。... といっても簡単な話ではないが。

    さて、次にチェックするのは、どんな機種用のコードがあるか?
    arch/mips/jz4770/boards には上記のものがあるが、jz4760 と jz4760b もある。

      jz4760 /jz4760b
    • z800
    • lynx
    • lepus
      (のほかにもいくつか)

    4760/4760b 共に同じ機種がある。lepus は Ingeic が出している リファレンスのボードだが、lynx (jz4760) は Ronzi A3 , lynx (jz4760b) は、ramos V65PRO のはず。

      CONFIG_JZ4760_RESET_HIBERNATE=y
      CONFIG_TOUCHSCREEN_JZ4760=y
      CONFIG_FB_JZ4760_ANDROID_IPU=y
      CONFIG_FB_JZ4760_ANDROID_LCD=y
      CONFIG_JZ4760_ANDROID_LCD_USE_2LAYER_FG=y
      CONFIG_FB_JZ4760_ANDROID_TFT=y
      CONFIG_JZ4760_HDMI_DISPLAY=y
      CONFIG_JZ4760B_AOSDC=y

      本題とはあまり関係ないのだが、JZ4760 と共通のものが結構ある。FB や IPU が同じなのは、ユーザランドも基本同じということで結構嬉しかったりする。

    本当にビルドできるのかどうか分からないものの Ronzi A3/V65PRO 用のコードがあるのはうれしい。IQQ M1 はないようで残念。

    なぜカーネルソースを待ち望んでいたか .. というと 改造したいからだ。改造したい内容は Android として使う以外の用途も想定している。

    とりあえずやってみたいこと。

    • USB gadget に ether を追加

      Linux マシンや Windows に USB でつなぐことが多いのだから、その間 Network も HOST からルーティングしたい。

      単独のデバイスだと SmartQ でやったことがあるが、Android として使うのなら、複合デバイスとして 作り直さないといけないかも知れない。設定レベルでできるものなら嬉しいが、まずはソースを見てみないと。

    • NFS や CIFS クライアント , NFS サーバ

      こういったものは、Linux マシンとして使うためには便利なのでビルドしたい。既存のカーネル用のモジュールとして作れるかどうかは、config 見てみないとはっきりしない。

    • binfmt_misc

      これあると開発には便利なはず。組み込んでおきたい。

    • USB ドライバ

      どれだけ標準に組み込まれているのか分かっていないが、足りないものはあるだろう。既存のカーネルは module にしていないように思えるが、これまた調べていない。

        defconfig を grep して整理してみると ...

          CONFIG_USB_HID=y

          CONFIG_USB_SERIAL=y
          CONFIG_USB_SERIAL_GENERIC=y
          CONFIG_USB_SERIAL_OPTION=y
          CONFIG_USB_SERIAL_VIA=y

          CONFIG_USB_NET_AX88772A=y
          CONFIG_USB_NET_CDCETHER=y
          CONFIG_USB_NET_DM9601=y
          CONFIG_USB_NET_QF9700=y
          CONFIG_USB_NET_NET1080=y
          # CONFIG_USB_ACM is not set
          # CONFIG_USB_SERIAL_PL2303 is not set
          # CONFIG_USB_SERIAL_FTDI_SIO is not set
          # CONFIG_USB_SERIAL_PL2303 is not set

          CONFIG_USB_STORAGE=y
          CONFIG_USB_STORAGE_DATAFAB=y
          CONFIG_USB_STORAGE_FREECOM=y
          CONFIG_USB_STORAGE_ISD200=y
          CONFIG_USB_STORAGE_USBAT=y
          CONFIG_USB_STORAGE_SDDR09=y
          CONFIG_USB_STORAGE_SDDR55=y
          CONFIG_USB_STORAGE_JUMPSHOT=y
          CONFIG_USB_STORAGE_ALAUDA=y
          CONFIG_USB_STORAGE_ONETOUCH=y
          CONFIG_USB_STORAGE_KARMA=y
          CONFIG_USB_STORAGE_CYPRESS_ATACB=y

          CONFIG_USB_BELKIN=y
          CONFIG_USB_ARMLINUX=y
          CONFIG_USB_NET_ZAURUS=y
          CONFIG_USB_VBUS_POWER_CALLBACKS=y

        HID は入っているし、USB メモリや 有線 Ethernet も 大丈夫そう。シリアルは貧弱で ACM すらない。かわりにどうでも良さそうなものが入っていたり。

        基本的に =m がほとんどない。そのため、デバイスを追加するのには module だけの addon ではなく、カーネルも置き換えが必要そう。

      とりあえずは、この程度。USB デバイスになる機能は、PC では使えないから 興味深い。

      そのほかだと何だろう?

    • 充電を 50% ぐらいで止める機能

      こういうのがあると良いような気がする。バッテリーを常に充電するのはどうかと思うので。
      開発用専用には バッテリーを外してしまっても良いかも知れないのだが ... Paladin などは、USB からの電力共有だけで動くのかどうか? Rozi A3 は問題ないのだが、殻割りしないといけないし、UPS としての機能が使えないというのも もったいない。

      ところで、なぜ充電中に 残量が分かるのだろう? ときどき充電を止めて測定している? ならば、話は簡単なのかも知れない。

    Wifi と USB

      Ronzi A3 の Wiki は、USB ドングルの中身のようなモジュールが メインボードにつけられている。これを外すことは簡単で Wifi が使えなくなる代わりに USB の HOST 専用 ポートを 1 つ確保できる。たぶん V65PRO も同じ。

      novo7 新機種の legend には、USB HOST の標準コネクタ(Type A メス)がついている。

      よく知らなかったのだが、内臓 Wifi は USB ではなさそう。SDIO ? ちなみに これのドライバは、ソースコードもなく module になっている。

        CONFIG_JZ4770_MSC0_BUS_4=y
        CONFIG_JZ4770_MSC1_BUS_4=y
        CONFIG_JZ4770_MSC2_BUS_4=y

        3 つの SD/MMC が Enable になっている。たぶんこれ。
        (fun さんのコメント 参照 MSC0 : internal Flash / MSC1 : Wifi / MSC2 : microSD )

      そうなると basic や paladin では USB HOST は空いていることになる。... あ、basic には 2 個目のカメラがあった。ちゃんと調べれば分かると思うが、解像度の高いほう (basic では back ) は Jz4770 直付けで 解像度の低いほう は USB だと思う。

      ちなみに、basic は、ここに殻割りを含めた詳細な記事があるのだが、基板の裏 (液晶と反対側)に シリアルらしき パッドがある。

      paladin はどうなのだろう? 探してみているのだが、分解写真を見つけられていない。まぁ、自分で殻割りしてみれば良いのだが、だれか分解するだろうと思って他力本願になっている。

      追記:fun さんに教えてもらった URL に paladin の分解写真がある。


      内部には、USB 引き出し用らしき 4pin コネクタのパターンがある。これは改造の楽しみがありそう。

        追記: 違うかも。抵抗膜式タッチパネルも 4pin で この位置ならそれもあり得る。その場合は、JZ4770 の専用端子に接続されていることになる。GPIO の機能もあれば 他の使い方もできそうだが、残念ながら アナログ専用。

        端子のピッチは、1.0mm (か ひょっとすると 0.8mm) 。適合するコネクタは、フラットケーブル用のような気がする。たとえば これとか。そうであれば、ますます タッチパネルのような気がしてくる。

        そうであっても、カーネルがイジれれば工夫次第でなにかに役に立つかも知れない。たとえば、8 個〜10個のボタン入力(同時押し可能)ぐらいには使えそう。



      こちらは全体。液晶のコネクタに互換性があるものが出れば、入れ替えることも可能かも知れない。ちなみに basic や aurora とは全然違う。(advanced II/elf とも違うのだろうか?) taobao では、結構リプレース(or 修理)用の液晶モジュールが出ているから、後に解像度などが違うものが手に入る可能性も皆無ではない。

      追記: paladin の裏側



      paladin を分解する人がボチボチ出て来ている

      この写真は、裏側をしっかり撮ってくれているのでありがたい。

      よく見れば UART2 TXD と UART2 RXD のシルクが見える。端子は、USB コネクタ近くの 3 つのランドらしい。

    カーネル開発のすすめ

      Jz47xx を使った basic / paladin は、カーネル開発に向いている。USBbootTool を使えば、いつでも元に戻せるから、たとえ動かないカーネルを作ってしまったとしても 文鎮になるリスクは少ない。( ただし、カーネルはなんでもできてしまうから、ハードウェアを壊してしまう可能性がないわけではない。そうなれば、元に戻せても意味はなくなる。)

      一般的に Android は ブートローダ と recovery.cpio.img さえ生きていれば、壊れたカーネルを書き込んでも 元に戻せはする。だが、署名つきの update.zip を作成しないと、作ったカーネルを試せないし 少々手間が増える。それも面倒だが、ブートローダ か recovery.cpio.img が壊れてしまえば、元に戻すのが とても困難になる。

        普通の SoC だと、JTAG という機能で ブートローダ を書きこんだり しなくてはいけないのだが、専用の装置と ツールが必要で 敷居が高い。

        Jz47xx のように 簡単に復旧できる ものは、少数派。

        novo8 の AMLogic AML8726-M は、SD card から 復旧できるようだが、カーネルソースが 入手できるものなのかどうか?

        TeleChips tcc8803/8902 は、USB からリカバリーできるし カーネルソースも入手可能だが、このチップを採用したタブレットは、今は あまり人気がない。

        ついでに書いておくと、Jz47xx を採用した機器は、ほぼ 特定のボタン+リセット で USBbootTool が使えるようになっている。 殻割りなど特殊なことをする必要もない。これは、SoC メーカの Ingenic が このツールを公開していて 十分認知されているのが理由として大きい。

      そして、jz47xx タブレットは、いまのところ NAND Flash を直接使うのではなく、SD カードの中のコントローラを通してアクセスしている。

      これも メリット。SD カードが中に入っているようなものなので、UBI とか yaffs2 とか 一般的ではないレイヤー を使わなくても済む。

        NAND Flash を直接扱うと、構成に関する情報の扱いが面倒なのだ。何回書き換えたかといった情報や代替ブロックの情報を壊さないようにしないと 。

      これらの特長があるので、basic / paladin は カーネルをいじるのに向いているのだ。

      Ronzi A3 や V65Pro もまた 向いてはいる。ただ、入手したカーネルソースでビルドできるかどうか分からない上に Android として動かすには ユーザランドとの互換性とかがあるので、敷居が高そう。Ronzi A3 / V65PRO はまだ入手できるのだが、ファームウェアがアップデートされない。いずれ入手できなくなることを考えると あまり労力をかけたくなくなる。

      追記:いくらかさわって分かってきたのだが、これは 基本 Android 2.2 用のカーネルなのだ。basic/paladin は これをベースに変更していって ICS に対応させたと言える。そうであれば、Ronzi A3/V65Pro 用カーネルはビルドできそうだ。そして flash/sdcard へのアクセスが遅い問題が解決されているかも知れない。インターフェイスの変更にしても、Ronzi A3/V65Pro は、カメラはもとより 3G-sensor すら持っていない。変更があったとしても関係ないだろう。... となると これらも試してみたくなる。

    カーネルビルドを試す(1)

    • android-2.6.32.9.tar.gz ( 新規分 ファイルリスト )
    • android-2.6.32.9.patch.gz ( パッチ ファイルリスト )

      これを linux-2.6.32.9 に適用した上で android2.2-npm701-r9738/kernel のファイルを上書き。

      次にクロスコンパイル環境だが、android-ndk-r6m-linux を使うことにしよう。

        設定するのも面倒なので、toolchains/mips-linux-android-4.4.3/* を /usr に コピー。

        方法は、tar で一旦固めて展開した。
        例:

        tar -C /opt/android-ndk-r6m-linux/toolchains/mips-linux-android-4.4.3 -cvf XXX .
        tar -C /usr -xvf XXX

      で、最初のトライ

      # export CROSS_COMPILE=mips-linux-android-
      # arch/mips/configs/npm701_ab_defconfig .config
      # make oldconfig
      (プロンプトが出るが、とりあえず全部 デフォルト)
      # make

      結構進むのだが、arch/mips/kernel/process.o で

      121: Error: unrecognized opcode `s32i2m xr16,$2'

      でエラー。これは MXU 命令だ。(以前書いた記事

      arch/mips/include/asm/mxu.h で使っている。

      ... 昔のカーネルにはなかった MXUレジスタ (16 個) のセーブリストアが入っている。
      それはともかく mxu_as を as の前にフィルタとして実行すれば良いのだが、さて。

      最初は、ビルドできるかどうかの確認を優先して、arch/mips/include/asm/cpu-features.h の cpu_has_mxu を 0 に固定することにした。

      これでともかくも ビルドは通る。make zImage も OK 。

      ところで、make clean/make distclean はエラーになる。これは、arch/mips/mach-jz4770/boards/Makefile に 存在しない board が含まれているためで、編集すれば OK。

    ファイルを整理

    カーネルビルドを試す(2)

      さて、mxu はどうしよう。

      as をいじくるよりも cc1 の方が楽だと気がついた。cc1 は必ず 標準出力に 出力するから。

      /usr/libexec/gcc/mips-linux-android/4.4.3/

      ここに cc1 があるとする。cc1 を cc1.org に rename して、同じディレクトリに mxu_as を置く。

      そして

        #!/bin/sh

        DIR=`dirname &0`

        $DIR/cc1.org $* > /tmp/$$-xxx
        egrep -i '(S32I2M|S32M2I)' /tmp/$$-xxx > /dev/null
        if [ $? == 0 ]; then
        $DIR/mxu_as < /tmp/$$-xxx
        else
        cat /tmp/$$-xxx
        fi
        rm -f /tmp/$$-xxx

      こんなスクリプトで cc1 を置き換える。わざわざ XMU 命令があったときのみ mxu_as を使うようにしている。よくわからないのだが、こうしないと エラーが出るものがあるのだ。

      このやり方は 適当だから カーネル専用。あまり良い方法でもないが、兎にも角にも MXU 対応カーネルはビルドできるようになった。

      結局編集しないといけないのは、arch/mips/mach-jz4770/boards/Makefile のみになった。

      追記:簡単に分かるとこだけ。
      drivers/usb/gadget/f_mass_storage.c:
       NPM701_V_1_1 だと npm701 にならない。
      arch/mips/mach-jz4770/boards/npm701/npm701-misc.c
       get_board_type() で npm701 という文字列をリターンしている。
       (Paladin のとき修正忘れに注意)

    シュリンク版カーネルソースリスト

      FILES-SHRINKED-BASE-ingenic-2.6.32.9.txt
      というのを作ってみた。

      npm701_ab_defconfig でビルドする際に使用するファイルのリストで、このファイルだけを tarball にすると 10MB ほど になる。

      もっとも config を変更すれば、必要なファイルが増えるので、これを完全に信用するのではなく、ベースとして使う。

      ビルドすると 依存関係のファイルが .xxx.cmd という名前 (xxx はファイル名) で作成されているので、ここから スクリプトで抽出した 使用ファイルと ベースをマージすれば、かなり 信用できる リストになる。

      作ったリストを元に一旦 tarball を作り、ビルドと distclean ができるか確認するようにすれば、完全なものになる。足りないファイルが出るかも知れないが、手動で対応できる数になるはず。

      何故こんなものを作るかというと、改造したものの tarball を小さくしたいため。あと grep して検索するときに、関係ないファイルが出るのを防ぐ目的もある。tarball を作らなくとも リストだけ作っておくのも 有用だ。

    カーネルソースコードを見てみる(1)

      バッテリーをたとえば 50% までで止める ... なんてことはできるのだろうか?

      drivers/power/jz47xx_battery.c
      arch/mips/mach-jz4770/boards/npm701/npm701-misc.c

      このあたりが実際のコードらしいのだが ... 充電を止める機能は実装されていないようだ。
      どうも 充電中と放電中で、% を求めるパラメータが違うだけらしい。

      さらに、CHARG_DETE , CHARG_SET 共に使っていない。USB か DC から電源供給されれば、即充電中 ということになるようだ。

      したがって、今のコードは 充電を止めることはできない。では CHARG_SET をなんとかすれば、止められるのだろうか? これをやってみるためには、充電 IC を確認して そもそも止めるために なにをするのか調べないと。

      あと、スリープしたときには、INPUT_PULL 状態になる。PULLUP か PULLDOWN かは ピンによって決まっている。(npm701v11-pm.c より) 充電を止めるなら、この状態設定も対応しないといけない。

      結論としては、CHARG_SET が機能すれば、コードを書いて対応させることで そういう機能を作れるかも知れない。... といったところ。

    paladin GPIO 調査(1)

      徒労に終わるような気がするが、簡単に調べられるものは調べてみよう。

      まず、実機の /proc/interrupts を cat してみる。... と GPIO に割り当てられたものがすぐ分かる。これでただちに 10 個。

        73: 48262 GPIO mma8452
        94: 2 GPIO end call key
        120: 0 GPIO jz-msc (gpio)
        123: 5348 GPIO ldwzic_ts
        178: 1 GPIO volum down key
        206: 0 GPIO otg-id-irq
        211: 0 GPIO jz47xx_battery_act8600
        221: 0 GPIO volum up key
        230: 1 GPIO menu key
        233: 0 GPIO back key


        npm701 は、GPIO_OTG_ID_PIN GPE14 となっているのだが、paladin は、206 = (6 * 32) + 14 。GPIO が 64 オフセットされていると仮定すると 同じ GPE14 。

        MSC2_HOTPLUG_PIN=GPIO_SD2_CD_N=GPB24 だが、jz-msc も GPB24 。

        GPIO_MMA8452_INT1 は GPA9 だが、mma8452 も GPA9 。ただし、INT2 の方はない。
        GPIO_GT801_INT は、GPB27 だが、ldwzic_ts も GPB27 。

        けっこう互換性があるのかも ... ただ、まだまだある。

      あと、/proc/jz47xx_battery/info
                                        
        capacity: 100
        max_vol : 4050000
        min_vol : 3600000
        dc_chg_max_vol : 4150000
        dc_chg_min_vol : 3740000
        usb_chg_max_vol : 4050000
        usb_chg_min_vol : 3675000
        battery_mah: 4000
        dc_charg_ma: 750
        usb_charg_ma: 400
        update_time: 1326873997
        curve:
        -- NULL --

      これで、npm701-misc.c の jz47xx_battery_info の値が分かった。ただ、npm701-misc.c の値とはちょっと違う。
      basic 実機の jz47xx_battery_info も違った。

        capacity: 99
        max_vol : 4080000
        min_vol : 3600000
        dc_chg_max_vol : 4120000
        dc_chg_min_vol : 3720000
        usb_chg_max_vol : 4120000
        usb_chg_min_vol : 3675000
        battery_mah: 4000
        dc_charg_ma: 750
        usb_charg_ma: 400
        update_time: 1326894417
        curve:
        -- NULL --

      次に実機どうしの dmsg の違いから

        basic:
        jz_i2c0 jz_i2c0.0: JZ4770 i2c bus driver.
        jz_i2c1 jz_i2c1.1: JZ4770 i2c bus driver.
        jz_i2c2 jz_i2c2.2: JZ4770 i2c bus driver.
        i2c-gpio i2c-gpio.3: using pins 153 (SDA) and 156 (SCL)
        i2c-gpio i2c-gpio.4: using pins 6 (SDA) and 3 (SCL)
        i2c-gpio i2c-gpio.5: using pins 103 (SDA) and 102 (SCL)
        Device 0x5a with i2c speed:100K
        act8600_power:
        1 26 1
        4 87 1
        5 49 1
        6 57 0
        7 57 0
        8 36 0
        --
        input: jz-gpio-key as /devices/platform/jz-gpio-key/input/input0
        input: jz-remote as /devices/platform/jz-remote.2/input/input1
        Device 0x62 with i2c speed:100K
        input: ha2605_key as /devices/virtual/input/input2
        input: touchscreen as /devices/virtual/input/input3
        --
        jz_lcd_panel: AT070TN93_panel_probe(): board_pin: LCD_POWERON=0, LCD_RESET_PI
        N=139.
        panel AT070TN93 selected
        --
        mmcblk0: mmc0:0002 CHYUA 3.69 GiB
        mmcblk0: p1 p2 p3 p4
        --
        HDMI-GPIO_I2C: SCL(32*3 + 6), SDA(32*3+7)
        HDMI reset pin :(32 * 0 + 0)
        HDMI hotplug pin :(32 * 3 + 4)
        HDMI hotplug Level: 1 ,connect_active(0)
        HDMI driver in HDMI_HOTPLUG mode !
        HDMI ite6610_drv_probe done!
        HDMI ite6610 driver register done!
        --
        sensor_name:gt2005 id:0 facing:0
        ===gc0308_power_down==
        sensor_name:gc0308 id:1 facing:1
        default is gc0308
        CIM--- get new page!
        CIM--- get_max_mem_size
        CIM--- preview size = 1800KB
        CIM--- capture size = 3750KB
        CIM--- mem_size=12750K
        CIM--- order=12
        Virtual Driver of JZ CIM registered
        android init
        android_probe pdata: 804c11c4
        --
        Gt801 touch screen init!
        Device 0x55 with i2c speed:100K
        input: gt801_ts as /devices/virtual/input/input6
        gt801_ts 2-0055: Start gt801_ts in Interrupt mode
        gt801 ts probe suscess!

        paladin:
        jz_i2c0 jz_i2c0.0: JZ4770 i2c bus driver.
        jz_i2c1 jz_i2c1.1: JZ4770 i2c bus driver.
        jz_i2c2 jz_i2c2.2: JZ4770 i2c bus driver.
        i2c-gpio i2c-gpio.3: using pins 153 (SDA) and 156 (SCL)
        Device 0x5a with i2c speed:100K
        act8600_power:
        4 87 1
        5 49 1
        6 57 0
        7 57 0
        8 36 0
        --
        input: jz-gpio-key as /devices/platform/jz-gpio-key/input/input0
        Device 0x 1 with i2c speed:200K
        input: ldwzic_ts as /devices/virtual/input/input1
        input: jz_touchscreen as /devices/virtual/input/input2
        --
        jz_lcd_panel: AT070TN93_panel_probe(): board_pin: LCD_POWERON=0, LCD_RESET_PI
        N=139.
        panel AT070TN93 selected
        --
        mmcblk0: mmc0:0002 CHYUA 7.40 GiB
        p1
        mmcblk0: p1 p2 p3 p4
        --
        android init
        android_probe pdata: 804b0564

      とりあえず気になったとこを抜き出してみた。

      act8600_power が違うのが気になったが、HDMI I/O 用だったかも。
      タッチスクリーン関係がだいぶちがう。あと i2c-gpio の数。

      android_probe pdata は何の値? 後で調べないと。

      GPIO の割り当ては極力同じになるようにしている印象がある。デバイス関係の違いの方が不安になってきた。

      /sys/platform/devices の違い

        i2c-gpio.4
        i2c-gpio.5
        ite6610-drv.0
        jz-remote.2
        jz_cim.0

        power
        uevent

      ITE6610 は、HDMI 関係。jz-remote は、リモコン。

      cmdline の比較

      basic : mem=224M@0x0 mem=128M@0x30000000 console=ttyS2,57600n8 ip=off
      root=/dev/ram0 rw rdinit=/init memcfg=512M
      rd_start=0x80A00000 rd_size=0x000F1C13 cpu_version=4770v1
      paladin : mem=224M@0x0 mem=128M@0x30000000 console=ttyS2,57600n8 ip=off
      root=/dev/ram0 rw rdinit=/init memcfg=512M
      rd_start=0x80A00000 rd_size=0x000F1CA8 cpu_version=4770v1

      rd_size が違う。これはどこに書きこまれているのだろう? mbr-xboot.bin だとすると paladin の 1.2 GHz 化は、ちょっとまずい。

        これは、mbr-xboot.bin で実際のサイズを元に計算しているから大丈夫だった。


      あと、4770v1 って何? ひょっとして 40nm 版は v2 なのか?

    作ったカーネルを試す (basic)

      USBbootTool:n7b_burn_tool.zip も使える。
       - 右のチェックボックスのチェックを外すと、指定したものだけを書き込む。
       - mbr-xboot.bin , boot.img のみの書き換えも OK

      mkcfw-v65-2.1.zip の src にあるツールで zImage を入れ替えた boot.img を作り 試してみたところ ...

      不完全なドロイド君が表示されたあと 画面が黒(バックライトは付いている)に。

      元の boot.img にしたら、普通に立ち上がった。(元に戻せることの確認)

      そもそも ツールがダメかも知れないので、動くboot.img を バラす → boot.img の再作成で確認しないと。

      厳密にはちょっと違うが、再構築しただけの boot.img は立ち上がった。

        元のやつは、0x240 からの SHA_DIGEST の後ろ 0x260 から 8 バイトの データが入っている。これだけが不一致。

      そうなると、カーネルが全然ダメということに。シリアルとかつなぐの面倒だしどうやって進めよう?。

      FB 変になっているし、まずは、mem の指定が対応しているか見てみよう。

    4.0.3 のファームウェアのカーネル

      Paladin でのサスペンドが調子悪いので、4.0.3 のファームウェア(2 回目のリリースのやつ)からカーネルだけを取ってきて boot.img を作りなおしたものを試してみることにした。

      なんとなく動いているので、adb で dmesg を見たら ...

        Linux version 3.0.8-svn649 (yliu@android10) (gcc version 4.3.2 (Sourcery G++ Lite 4.3-51) ) #3 PREEMPT Fri Jan 13 17:59:41 CST 2012
        bootconsole [early0] enabled
        CPU revision is: 2ed1024f (Ingenic Xburst)
        FPU revision is: 00330000
        CPU clock: 1200MHz
        PCLK: 200MHz
        Memory clock: 200MHz
        H1CLK: 400MHz
        H2CLK: 200MHz
        AUX clock: 400MHz
        REG_CPM_PSWC1ST = 0x00000017
        REG_CPM_PSWC2ST = 0x0000000b
        REG_CPM_PSWC0ST = 0x00000000
        REG_CPM_PSWC3ST = 0x00000000
        JZ4770 NP_M702 board setup
        Power Management for JZ

      カーネルが fake じゃない 3.0.8 になっていた。

      wifi の モジュールはそのままなので

        Version magic maybe different, please check!!!
        dhd: Unknown symbol dma_map_single (err 0)
        dhd: Unknown symbol dma_alloc_coherent (err 0)
        dhd: Unknown symbol dma_free_coherent (err 0)
        dhd: Unknown symbol alloc_etherdev_mq (err 0)
        dhd: Unknown symbol dma_unmap_single (err 0)

      なんてエラーが。折角カーネルソースを手に入れたのに、動かす前に時代遅れとは ...

      まぁ今まで 3.0.8 に見せかけて動かしてきたのだろうから、インターフェイスは同じかも知れないし、Ronzi A3/V65Pro は 3.0.8 では逆に困ったりするかも知れないし。

      3.0.8 のソースが手に入るまで、もう少し調べていこうかと思う。

      ところで、この カーネル 3 つのドライブが見えるようになった。増えたのは CDドライブ。

      あと、ちょっと試してみたが、動画は具合が悪い。scanning が出たまま動画が再生され終了できなくなった。非互換なところもあるみたいなので、4.0.3 のユーザランドで古いカーネルというのは無理がありそうだ。

    Ronzi A3 用 (JZ4760-lynx) がビルドできないか試す。

      Ronzi A3 は、defconfig がない。あればビルドできるのか? という気もするのだが、ちょっとやってみた。

    • config-n7b-tst1.txt (ベースにした basic 用 / ビルドはできたが動かない)
    • config-a3-tst1.txt 作ってみたもの。

      ただ、 arch/mips/mach-jz4760/boards/lynx/lynx-misc.c で、コンパイルエラーが出る。

      __wifi_power_on()/__wifi_power_off() のところ だが、とりあえず これをコメント化してみると ...

      なにやら ビルドできたのだった。だが、ベースとした basic 用すら動かないわけで、動くことはまず期待できない。それでも ビルド出来たというのは進歩なのだから、ここに記録しておく。

      さて、どうやってデバッグしていこう。まぁ、basic 用を動かすのは、第一歩だから それをやるとして ...

        とりあえずは、adb だけ動かす ramdisk イメージを作って 状態を見れものなのかどうか 調べる。これがクリアできれば、なにが問題なのか分かるかも知れない。

        だめなら、デバイスをどんどん減らしていく。adb だけ動かせるようにして、後はモジュールとか。usb device と adb のドライバは、普通は確実に動きそうなものだが .. これでもダメなら、他の手を考えよう。

        うまくいくようなら、A3 も同じやり方で試す。

      こんなところか。ちなみに、Ronzi A3 をばらしてみると ... 4 つのパターンが並んでいるところがある。たぶんシリアル。最悪はここにシリアルつなぐとなんとかなるかも知れない。

      あとは、LCD に なんとか表示することができるかも知れない。panic した後も表示をしつづけるような仕組みを入れないといけなさそうだが ...

      昔にトライしていた libusb 版 usbboot を使ってカーネルのロード / メッセージの表示ができるようにするとか ... ただ、これはうまくいかなくて途中で放置しているし、JZ4770 用をマージしないといけないので 敷居が高い。
posted by すz at 22:07| Comment(5) | TrackBack(0) | Jz47xx(Linux)

2011年12月03日

開発環境の整備(3)

開発環境の整備とかいうタイトルにしてしまったが、Android とはほぼ関係ない。なにをやろうとしているかといえば ... Redhat Enterprise Linux 6 (RHEL6) の mipsel 版 clone を作ること。

しばらくの間、中断していたが CFW も一段落したので再開。

devkit3.tgz と それの元の mkdevkit3

    現状が良く分からなくなっているので、また整理から。

    http://nmj.sumomo.ne.jp/my-rhel6/

    ここの mipsel-devkit3.tgz と それの元の mkdevkit3.tar を新たに置いた。

    今までは元の環境を壊さないようにしていたが、実は libtool など具合が悪いものがある。もう面倒なので、元の環境を上書きするのを前提にした。

    具体的にインストールの仕方を書くと

    • mindev10bin2.iso の中にある mindevel10.tgz を chroot 環境として展開 (tar -zxvpf )
    • i686 パッケージを アンインストール
    • usr/include を 削除するか usr/include-x86_64 などに rename (必須)
    • mipsel-devkit3.tgz をそこに上書き展開。
    • startup.sh で qemu-mipsel を動作させるようにする (起動して1回のみ)
    • /etc/ld.conf.d のファイルを lib64 → lib に修正 して ldconfig (とりあえず)

    この操作で rpmbuild --target mipsel とすることで、ビルドが出来るようになる。

    mkdevkit3.tar には、SRPM や 作った RPM を置いてある。mipsel-devkit3.tgz は ほぼ作った RPM を 元にしている。( gcc も無理やり ビルドして RPM 化した。)

  • 状況は前記事とあまり変わらない。ここから再スタート。

    perl は、config.sh に cppsyms='NO_ASM'=1' なんていう変なのが入っていた。

    初期に gcrypt だったか .. の make でうまくいかないので、/usr/rpm/macros とかに -DNO_ASM を 無理やり入れていた。これが回りまわってこうなったようだ。

      /usr/rpm/macros とかの -DNO_ASM を off にしても同じ現象 -- で 調べると いろいろ伝播している。とりあえず mysql と tcl と icu あたり。あと python と uuid も。

    config.sh を書き換えて make すると最後まで行った。

    あと、地道にビルドしていったら、nspr , nss がビルドできるようになっていた。
    そうなるとついに openldap がビルドできるようになる。

mipsel-devkit4.tgz と それの元の mkdevkit4.tar

    devkit3 の発展形態。作った rpm は 806個 になった。ようやく全体の 1/2 を超えた。

    ついに openldap がビルドできた。これでいろんなものがビルドできるようになって、かなり進んだ。

    mesa はまだ。perl はビルドできたが微妙な状態。x86_64 版とちゃんぽんになっているのがいけないのかも。

    そして ... rpm コマンド が作れた。ここがひとつのマイルストーン。実機で chroot できる環境を作ることができる。次の devkit はセルフベースで、cc1/cc1plus のみクロスに出来るものを目指す。

    ちなみに、openssh-server はできているので 実機では ssh でログインできるものになるはず。ストレージは microSD しかない。相当に遅そうだが novo7 basic ならなんとか。

    もうちょっと詳しくかいておこう。

      x86_64 用に作った rpm の総数は、1500 個ぐらい。だがこれには、カーネルや 立ち上げに必要な ものがふくまれている。chroot してビルドするのに必要なものはもっと少ない。

      次目指すのは、microSD に ext4 パーティションを作って そこに展開した tarball を 使って セルフの環境で 自分自身をビルドできる環境。microSD の I/O 性能や 使えるメモリの量の点で novo7 basic を使うことを想定。

      で、qemu-mipsel と gcc の cc1/cc1plus などをパックしたものも用意して、この上に 展開することで、Linux x86_64 での chroot 環境でも使えるものにする。 devkit4 までは、x86_64 環境に上書きしていたが、これが逆になる。

      セルフの環境用の microSD は、vfat 領域を減らして ext4 と swap パーティションを追加したものになると思う。最初は adb で入って

    • ext4 を mount

    • swapon

    • chroot した上で sshd を起動。

      ここまで済んだら

    • 外部のマシンから ssh を使って ログイン。

      という手順になると思う。

次の作業

    次は、作った rpm を rpm コマンドで インストールしようとして エラーを見る。

    # mkdir newroot
    # rpm -r `pwd`/newroot --initdb
    # rpm -r `pwd`/newroot -Uvh *.rpm

    こんな感じ。で、rpm がないというエラーが出る。このエラーを減らすように rpm を追加していく。
    現状で足りないのは、

      kernel-headers
      kernel
      pcsc-ifd-handler (needed by pcsc-lite-1.5.2-6.el6suz1.mipsel)
      sane-backends-libs-gphoto2 (needed by sane-backends-devel)
      phonon-backend (needed by qt-x11)
      mesa-dri-drivers (needed by mesa-libGL)
      setools-libs-python ( needed by policycoreutils-python)
      text-www-browser (needed by docbook-utils )

    これぐらいまで減ってきた。qt, mesa は強引にビルドしてこうなっている。ちなみに、text-www-browser は、w3m のことで core-dump するので ビルドできていない。

    kernel は無論ビルドできない。

    他にもビルドできていないものがあって、avahi と cups 。数は少なくなったが、結構難物ばかり残っている。

    で、これらをビルドして kernel など無理なもの のみになれば、--nodeps で 無理やりインストールして tarball を作る。これで、ようやく self ベースに切り替えられる。

    その後は、... java 関係。java 関係が一番の難物で不安を感じている。

    ちょっとビルドについてのメモ
  • perl

    perl は、noarch パッケージは基本ビルドしないことに。mipsel パッケージは 全部ビルド。

  • cups

    ./genstrings > sample.c

    で core-dump 。これがクリアできていない。

  • avahi

    checking for python module gtk... no
    configure: error: Could not find Python module gtk

    これの原因は、

    checking for python module gtk... no
    configure: error: Could not find Python module gtk

    ということらしいのだが...
  • w3m

    mktables だったかで code-dump 。たぶん gd が原因。

  • setools

    lib64 を読もうとしてエラー。

  • 掃除

    最初 そのままではビルドできないものを多々あったが、いくつか ビルドしなおして正規のものに置き換えた

      cracklib
      gmp
      libSM
      libxcb
      sane-backends
      unixODBC
      uuid
      nss-softokn
      gstreamer-plugins-base (libtheora )
      nfs-utils

    まだ残っているが、まぁぼちぼち。

mipsel-devroot6.tgz と mipsel-devkit5.tgz と それの元の mkdevkit6.tar (整理中: (仮))

    avahi も cups も devel パッケージを作りたいだけなので、ごまかした。

    で、これを元にとにかく self 版を作ってみたのが、devroot6 。
    devkit5 は、同じ rpm を元に x86_64環境に上書きする従来の発展版。

    devroot6 は、689 個のパッケージをインストールしたもので、直接 chroot 可能なようにしている。実機でも chroot 可能なはずだが未確認。サイズは 400MB弱で まだまだ小さい。

    一応はできたのだが ... 結構動作があやしい。なので、作る予定がなかった devkit も作ることにした。

    mkdevkit6.tar は、すべての元で作った rpm ( 全部で 1013 ) 個が置いてある。サイズも 1.2GB と巨大になってしまった。半分は SRPMS で もう使わないものも置いていたりするので大きくなっている。

    今後は、作ったこれを動かしてみるつもり。あと、これほどのサイズのものを頻繁に置き換えるのは無理があるので 当面これを手直しして使う。次に置くのは最終形態にするつもりで、いつになるか分からない。

ちょっと実機で試す

    32G の microSD にパーティションを3つ作成し、ext4 で mkfs して mipsel-devroot6.tgz を展開

    adb で mount して chroot できた。

    bash-4.1# ifconfig -a
    ifconfig -a
    lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    UP LOOPBACK RUNNING MTU:16436 Metric:1
    RX packets:16 errors:0 dropped:0 overruns:0 frame:0
    TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:0
    RX bytes:1376 (1.3 KiB) TX bytes:1376 (1.3 KiB)

    wlan0 Link encap:Ethernet HWaddr 00:E0:4C:14:E3:67
    inet addr:192.168.0.3 Bcast:192.168.0.255 Mask:255.255.255.0
    UP BROADCAST MULTICAST MTU:1500 Metric:1
    RX packets:42 errors:0 dropped:305 overruns:0 frame:0
    TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:24804 (24.2 KiB) TX bytes:7971 (7.7 KiB)

    ビルド用 しかインストールしていないので、openssh も入れてなかった。

    bash-4.1# rpm -Uvh init*

    error: Failed dependencies:
    /etc/oracle-release is needed by initscripts-9.03.23-1.0.1.el6.mipsel
    bash-4.1# rpm -Uvh init* --nodeps

    Preparing... ########################################### [100%]
    1:initscripts ########################################### [100%]

    bash-4.1# rpm -Uvh openssh-5* openssh-server*

    Preparing... ########################################### [100%]
    1:openssh ########################################### [ 50%]
    2:openssh-server ########################################### [100%]
    bash-4.1#
    bash-4.1# ls /etc/init.d

    avahi-daemon iptables netfs pcscd rpcidmapd snmpd
    functions killall network quota_nld rpcsvcgssd snmptrapd
    gpm lvm2-monitor nfs rdisc sandbox sshd
    halt messagebus nfslock restorecond saslauthd udev-post
    httpd netconsole openct rpcgssd single uuidd
    bash-4.1# /etc/init.d/sshd start

    cat: /proc/sys/crypto/fips_enabled: No such file or directory
    /etc/init.d/sshd: line 50: [: too many arguments
    Generating SSH2 RSA host key: /etc/init.d/sshd: line 69: 890 Segmentation fault $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' &>/dev/null
    [FAILED]
    bash-4.1#

    rpm は入ったけれど、なんかダメみたいだ。... telnet はどうだろう。

    bash-4.1# rpm -Uvh telnet-server*

    error: Failed dependencies:
    xinetd is needed by telnet-server-1:0.17-46.el6.mipsel
    bash-4.1# ls xinetd*
    ls xinetd*
    ls: cannot access xinetd*: No such file or directory
    bash-4.1#

    だめだった。

    ちょっとビルドのテスト

    bash-4.1# su - root

    -bash-4.1# rpmbuild --rebuild mingetty*

    Installing mingetty-1.08-4.1.el6.src.rpm
        :
    + rm -rf /root/rpmbuild/BUILDROOT/mingetty-1.08-4.1.el6.mipsel
    + exit 0
    Executing(--clean): /bin/sh -e /var/tmp/rpm-tmp.p2pk4u
    + umask 022
    + cd /root/rpmbuild/BUILD
    + rm -rf mingetty-1.08
    + exit 0

    -bash-4.1# rpm -Uvh /root/rpmbuild/RPMS/mipsel/mingetty-1* --force
    rpm -Uvh /root/rpmbuild/RPMS/mipsel/mingetty-1* --force
    Preparing... ########################################### [100%]
    1:mingetty ########################################### [100%]
    -bash-4.1#

    いちおう OK 。( su - しているのは、adb から chroot しただけでは、HOME とか最低限度の環境すらないため。)

    ちょっと使ってみたわけだが、Ronzi A3 は microSD の I/O が遅くてレスポンスが悪い。あと adb で作業するのは辛い。やはり最低限の作業環境は最初から入れときたい。

    それはともかく、ついに実機で動かすところまで来た。

    現在の不具合:

      redhat-rpm-config を入れると、self 版では rpm を生成する最後のところで エラーになる。

      INTERNAL ERROR 521 (0.152-Dec 5 2011): cannot read data from file

      elfutils の eu-strip を動かすようになって、それが動かないということらしい。

      ちなみに redhat-rpm-config を入れないと %dist が 入らないので 違うファイル名の rpm が出来てしまう。

      で、x86_64 の環境だと native の eu-strip を使っているはずで、それなら問題ないようだ

      なかなか嫌らしい問題っぽいが、とりあえず rpm -e redhat-rpm-config として、/usr/lib/rpm/macros に
      %dist .el6
      を入れておくことにしよう。

      それ以外に アーキテクチャが対応していないという理由で全然ビルドできないものがいくつかある。

      corosync libatomic_ops openais valgrind fakechroot

      このあたり。( + libgcrypt )

    いろいろ問題があるのだが、作ろうとしていたものは、開発のベース。すなわちこのような問題に直面して、それを直していけるようなもの。そういう意味では あと一息。

    追記:

    # passwd
    Error - unable to connect to audit system

    詳細な原因はわからないが、passwd などが動かないようだ。どうもそのせいで mipsel-devroot6.tgz の作成に失敗している。%pre で groupadd などをしているパッケージがあり、これらは エラーになる。

    ちょっとインチキだが、audit なしでビルドした shadow-utils と passwd を置き換えたら

    /usr/sbin/build-locale-archive: cannot read data from locale archive: Cannot allocate memory
    warning: %post(glibc-common-2.12-1.25.el6suz3.mipsel) scriptlet failed,
    warning: %post(gtk-doc-1.11-5.1.el6.noarch) scriptlet failed, exit status 139

    エラーはこの 2 にまで減った。直せていないが %post なので パッケージが入らないというわけではない。

    ちょっとまずそうなので、作りなおして置き換えることにしよう。


    ビルドできない rpm について
  • fakechroot

      x86_64 以外ではビルドできない。これを必要としているのは、rpm コマンドのビルドで、しかも check する場合のみ。--without check を付ければ良さそう。

  • libatomic_ops

    pulseaudio , gc で必要とされている。

    ググると gentoo には 、libatomic_ops-1.2-mips.patch があるようだ。 で、この libatomic_ops は、gc-7.1 に含まれるもの。gc は無理やりビルドできるが、libatomc_ops がないので実行できなかったようだ。(w3mが ビルドできなかった理由?)

  • pulseaudio

    SDL で必要。.. だが SDL 側で off にできそう。

    あと、先の話だが、java-1.6.0-openjdk 。ただし、これも off にできそう。

  • corosync

    openais で必要。

  • openais

    lvm2 と cluster で必要。 cluster は、lvm2 で必要。

    要するに lvm2 側でなんとかすれば、corosync も openais , cluster は不要。

      lvm2 見てみたら、enable_cluster のときだけ必要で、それが 1 になるのは x86 系だけだった。要するに最初から不要

  • valgrind

    curl , gdb , libmthca libtasn1 , python で必要とされている。

    が 、いくつかの architecture では 必要ないことになっている。

    パッチは見つけた (r11845_mips.tar.bz2)が、最新でも まともにサポートされていないようだ。


      が、libtasn1 は x86 と ppc のみ必要。libmthca は libibverbs-driver のことで librdmam , libnes , corosync あたりが関係ある。





    qemu: Unsupported syscall: 4204

    ls でこんなメッセージが出るようになった。4204 というのは、capget のことで、qemu (1.0)では、

    case TARGET_NR_capget:
    goto unimplemented;
    case TARGET_NR_capset:
    goto unimplemented;

    こんなふうになっている。

    あと、qemu の環境で rpm でパッケージをインストールすると

    File size limit exceeded

    というメッセージが出て 1 つめで終わってしまう。SIGXFSZ を受けている?

    df が表示されない。

    /etc/mtab にそれらしいのを入れれば OK っぽい。
posted by すz at 18:25| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2011年11月05日

開発環境の整備(2)

前記事ではグダグダになってしまったので、一回整理。

開発環境の整備とかいうタイトルにしてしまったが、Android とはほぼ関係ない。では、なにをやろうとしているかといえば ... Redhat Enterprise Linux 6 (RHEL6) の mipsel 版 clone を作ること。ただし、ブート可能なのはとりあえず目標としていない。まずは、RPM をビルドできる環境として root を 展開して chroot するものを目指す。

    何故 他のものではなく、fedora でもなく RHEL なのか? ... というと基本的に RPM を使っているシステムが好きなのだ。で、fedora はでかいし更新が頻繁で、作っているうちに時代遅れになってしまうのが嫌なのだ。RHEL は更新の頻度は低め だし、6 ならしばらく使えそうだ。あと、断っておくが全部をビルドするつもりはない。目指すのはあくまでビルド環境として成り立つ最低限度のもの。

どこまで出来るかは分からないのだが、やってみている。現状は、 RHEL6(clone) の chroot 環境 に qemu-mipsel を入れて セルフだか クロスだかよく分からないような 環境になっている。その環境で、 343 個の rpm をビルドした。最終的に 1000 個ぐらい必要なので、1/3 ぐらいの達成度。

ビルドするにあたっての基本方針

  • 64bit(x86_64) ではもともと i386 環境と共存できるようになっていて、 /lib , /usr/lib は 32bit 環境用に空けてある。

    i386 の代わりに mipsel を突っ込む というのが基本的なアイディア。その環境で qemu の usermode というのを使って mipsel のバイナリを動かす。rpm コマンドとかビルドするのが難しいものは、 x86_64 を使って 親の 環境を流用する。

  • 準備 src.rpm から ビルドして x86_64 の野良クローンを作る。

    この方針だと x86_64 と mipsel が同じバージョンでないと困る。多少のバージョンが違ってもなんとかなるが、まったく同じものをベースにして置き換えていくのがベストなのだ。

    まずは、ベースとなる環境を作ってみることから始める。これも出来ないのでは、mipsel 版なぞ無理な話なわけで、mipsel 版の ビルドの 予行演習でもある。

    また、どこまで作るのか ... 全てを作っていては とても巨大になる。どれを ビルドするのかを見極めることも 同時に行う。

    最低限度必要なのは、自分自身をビルドできるもの 。gnome など当面必要なさそうなものは、はずす。

    この作業は クリアした。まぁ適当なものだが、

    に置いておく。mindev10bin2.iso と mindev10src5.iso だが、どちらも 2GB 弱もある。bin の方は、すべての RPM と rootfs の tarball -- mindev10.tgz が入っている。

    root になるディレクトリを作って そこに root 権限で

    # tar -zxvpf mindev10.tgz

    とする。(いきなり usr とかになっているので 注意)。あとは、chroot して、

    # mount /sys
    # mount /proc

    とすれば、だいたい使える。これ自体 (java 系を除く) すべての x86_64 RPM をビルドできる環境になっている。

      ただし、i686 パッケージが入っている。これは mipsel の環境を作るには邪魔なので、アンインストールしておく。

    ちなみに src の iso はすべての SRPM と minroot.tgz 。

    minroot.tgz は、boot 可能な(はずの)最小の環境。これには rpm コマンドが入っているので、ここから RPM をインストールしていくことができる。

    この root イメージに chroot する親OS のディストリビューションは、あまり関係ない。Linux のバージョンの方が重要だが、2.6.24 以降なら問題ないはず。

    さて、これら以外に mipsel-devkit1-wk0.tar というファイルがあるが、mipsel 版について、いままでの成果をつっこんだもの。ただしまとまってはいない。

mipsel 開発環境

まずは、なにをするのか ... というと qemu のビルド。qemu といっても QEMU user-mode というもので、linux のカーネル機能 binfmt_misc とあわせることで、mipsel などのバイナリを native のように動かせるもの。

    mipsel-devkit1 に qemu-bin.tgz に最低限必要なバイナリを入れてある。

      startup.sh
      usr/bin/qemu-arm
      usr/bin/qemu-mipsel
      usr/bin/qemu-ppc

    mipsel 以外に arm とか ppc も入れてみた。.... mipsel が移植できるなら arm や ppc も同じやりかたでできるはずなのだ。mipsel がうまくいくようなら、これらもやってみるかも知れない。

    このバイナリを作った SRPM も SRPMS-cross に入れてある。

クロス版 binutils , gcc , glibc

最初に必要になるのは、この 3 つ ... なのだが すでに 擬似セルフ環境に移行しているので、あまり重要ではなくなっている。だが、arm などの移殖のために、どうやって作っていったのかをメモしておく。それに GPL はソースだけでなく、どうやって作ったかの情報をも要求している。説明可能になってないと厳密にはまずい。

    まずは、binutils 。これは、オリジナルの SRPM が、クロス用を作れるようになっている。

      rpmbuild --without testsuite --define "binutils_target mipsel-redhat-linux"
      --rebuild binutils-xxx.src.rpm

    これで、できるので、インストールしておく。redhat になっているが、とりあえずなので、気にしない。

    さて、これからが大変

    • 0) 準備 (種となる libc.a と include ファイルを用意)
    • 1) gcc のビルド (最小環境)
    • 2) glibc のビルド
    • 3) gcc のビルド (stdlibc++ を含めた環境)

    という手順。

  • 0) 準備

    ビルドで、実行可能なファイルが作れるかチェックしているので、適当なものでよいから libc.a などが必要なのだ。で、ちゃんとした include ファイルと glibc を用意できれば、標準的なビルドが可能になる。

      mipsel-devkit1 の mipsel-devkit1-lib00.tgz には 3) が可能になる 最低限のファイルを入れてある。( /lib を使うので注意 )

      1) から行う場合は、このうち usr/mipsel-redhat-linux/lib の crt*.o libc.a だけが必要。

    • 1) gcc のビルド (最小環境)

      SRPMS に (変更した) gcc の SRPM を入れてある。これをとりあえず rpmbuild で configure するところまで 進める。

        パッチを当ててくれるし、config.log に config のオプションが残っているので テンプレートとして使えて便利。


      ../configure --prefix=/usr --target=mipsel-redhat-linux \
      --build=x86_64-redhat-linux --host=x86_64-redhat-linux \
      --disable-threads --disable-checking --with-system-zlib \
      --enable-__cxa_atexit --disable-libunwind-exceptions \
      --enable-gnu-unique-object --enable-languages=c,c++ --disable-libgcj \
      --disable-libmudflap --disable-libgomp --disable-libssp \
      --disable-shared --disable-libstdc__-v3

      最初の configure はこれ。ほとんどのライブラリを disable にするし、libc.a しかないのでシェアードライブラリも disable に。

      あと、--disable-fixed-point も入れておくと 使わない固定小数点ライブラリをビルドしないので、ビルド時間を短縮できる。

      これが終わったら、インストールディレクトリを用意して

      # make DESTDIR=xxx install

      これで、一応ファイルをチェック。必要そうなものだけ、選んで / に展開しなおす。(後述)
    • 2) glibc のビルド

      glibc のビルドに gcc は必要だが、ほかに カーネルヘッダーが必要。

      Ingenic のサイトにあった、linux-headers-2.6.24.3.tar.bz2 をおいてある。これを /usr/mipsel-linux/include におく。

      で、gcc と同じように SRPMS においた (変更した) glibc を途中までビルド。これを元に configure しなおして、ビルドする。

      ../configure CC=mipsel-linux-gcc CXX=mipsel-linux-g++ \
      AR=mipsel-linux-ar RANLIB=mipsel-linux-ranlib --prefix=/usr \
      --enable-add-ons=nptl,c_stubs,libidn,ports --without-cvs \
      --enable-kernel=2.6.18 --enable-bind-now --with-tls --with-__thread \
      --disable-multi-arch --disable-profile --enable-experimental-malloc \
      --disable-nss-crypt \
      --host=mipsel-linux --build=x86_64-redhat-linux \
      --with-headers=/usr/mipsel-linux/include

      glibc も インストールするディレクトリを用意するのだが ... オプションが違うので注意。

      make install_root=/tmp/new-glibc install


      mipsel-devkit1-inc0.tgz
      mipsel-devkit1-lib0.tgz

      これらが、作ったもの ... のはず。(実はすでに セルフで RPM が作れているので、そこからとってきている)

      inc0 の方は、クロスでは、/usr/mipsel-redhat-linux に展開し、lib0 は / に展開して /lib と /usr/lib にインストールする。

    • 3) gcc のビルド (stdlibc++ を含めた環境)

      まずは、上記の inc0 を /usr/mipsel-redhat-linux に展開して lib00 を展開する。
      lib0 でも良いかも知れないが、/usr/lib のファイルを /usr/mipsel-redhat-linux/lib に移動しないとだめかも。

      3) のステップでは後ろ 2 行を変更。

      --enable-libmudflap --enable-libgomp --disable-libssp \
      --enable-shared --enable-libstdc__-v3

      だいたい enable にする。libssp は使わないと思うので disable のまま。

      mipsel-devkit1-gcc0.tgz は、これで作ったバイナリ。すべてではなく、必要そうなファイルを選んである。

      以上 ... なのだが、これらのうち 3) で作った gcc の一部 は セルフ環境でも使う。ただし、cc1 , cc1plus 以外の実行形式のファイルはセルフのものと置き換えている。

    擬似セルフ環境

    以上は、x86_64 システム自体は壊さない範囲での作業だった。これからは rpmbuild でパッケージをビルドできるように システムのファイルも書き換えていく。

    そのため、chroot 環境を別に用意する。最終的には、実機で chroot して動かせる 本当のセルフ環境を作るのが目的だが、今は それができない ので擬似セルフ環境としておく。

    擬似セルフ環境は次のステップで作っていく。

    • 1) rpmbuild ができるようにする
    • 2) 作った binutils , glibc , gcc に置き換える。
    • 3) 作った RPM を 手動でインストールしていき、さらに ほかの RPM をビルドできるようにする。

    3) が作業のメインなのだが、一筋縄ではいかない。依存関係が巡回しているのだ。そのため、仮に作った RPM をインストールして 全部そろったところで 再度正規の RPM をビルドしなおすことになる。この作業は非常にたいへんなので、説明が長くなる上、整理できていない。3) は後回しにして その成果物を先に紹介する。

  • 1) rpmbuild ができるようにする

    正確には、

    rpmbuild --target mipsel --rebuild xx.src.rpm

    ができるようにするわけだ。セルフ環境を目指しているわけで、ビルドに必要なものは、/usr/include /lib /usr/lib にインストールされていなければならない。そして、一部のものは、/usr/bin のコマンドを入れ替える必要もある。

    とりあえず、include については、上記のものを /usr/include にインストールする。もとの include は、/usr/include-x86_64 とでもしておいて、参考にしている。

    また、セルフ用のコマンドに置き換えるまでは、/usr/mipsel-redhat-linux/ の include や lib が参照される。include は、/usr/include へのリンクで済むが、lib はちょっと面倒だったりするので、早い段階で binutils や gcc を置き換える。

    /usr/bin の置き換えについてだが、とりあえず mipsel-redhat-linux-xx をすべて xx に置き換える。本当は、 /usr/mipsel-redhat-linux/bin に集めてパスを通すのが正統のような気もするが まぁ今はこれでやっている。

    以上の作業をすれば、一応は rpmbuild はできるようになる。ただし、いくつかの設定が具合が悪い。/usr/lib/rpm/macros , /usr/lib/rpm/redhat/macros , /usr/lib/rpm/rpmrc あたりを編集しなければならないが、ちゃんと整理できていないので説明できない。

  • 2) 作った binutils , glibc , gcc に置き換える。

    最初にビルドすべきなのは、zlib 。ビルドしたのは良いとして、どうやってインストールするかが次の問題。

    全部は置き換えたくないのだ。

    # rpmbuild --target mipsel --rebuild zlib-xxx.src.rpm

    これでできた RPM に対して

    # rpm2cpio zlib-xxx.mips.rpm | cpio -id
    # rpm2cpio zlib-devel-xxx.mips.rpm | cpio -id

    こうやって展開する。このうち /usr/include , /lib , /usr/lib (pkgconfig も) をインストール。

    /lib , /usr/lib は基本的に問題がない。/usr/include も置き換えると決めたので問題なし。 問題なのは、/usr/bin だが as,ld など binutils のコマンド cpp , gcc , g++ , c++ といった gcc のコマンド、 あと pkgconfig と chrpath それに パッケージ固有の xx-config あたりは置き換えることにする。

    glibc のパッケージでは、/sbin/ldconfig と /usr/bin/ldd あたり? ほかもありそうなのだがいまのところこれぐらい。

    こうやって置き換えては、ビルドを続け、さらに置きかえる。x86_64 がすでにインストールされているから、依存関係のチェックは効かない。

    こうやって作っていくのだが、gcc がビルドできないことが最初の壁。

    どうしたものかと思ったのだが、ビルドでエラーになったら 手動で make する。prev-gcc/cc1 をクロスのものと置き換えることを 2 回ぐらいやれば、なんとか最後まで行く。

    で、上記のクロス版とあわせるのだ。実行形式の cpp , gcc, g++ などは置き換えてしまう。ただし、cc1 , cc1plus を置き換えるとビルドが遅くなる。一応切り替えるようにしておいて 問題なければ クロス版を使う。

    *) 現在のバイナリ

    devkit にある

      gcc-bin-self.tgz
      mipsel-devkit1-bin.tgz
      mipsel-devkit1-inc.tgz
      mipsel-devkit1-lib.tgz

    mipsel-devkit1-xx.tgz は、devel-rpms.sh で生成した。不完全であれば作りなおせる。

    ちなみに、cc1-libs.tgz は、将来 mipsel に全部置き換えた上で、cc1/cc1plus のみ クロスを使う場合に使うつもりのもの。今は関係ない。

    こうやって mipsel-devkit1 を作ってはみたが、実際の環境そのものではない。いろいろ不完全なところがあるので、動作を確かめた上で fix していこうと思う。

追記: 問題点多数

    環境を変更したのだが、問題点が多くて.... もういちど作りなおそうとしている。

    まず、gcc 関係の バイナリが足りない。cpp も入れ忘れたし、cc1 , cc1plus も 古いものにしてしまった。

    asis にしてもちょっとひどいので、作りなおす。

      gcc の実行環境は、やっぱりよく分からない。

    • セルフとして作ったつもりだが、/usr/mipsel-redhat-linux/include を要求される。
      /usr/mipsel-redhat-linux には、/usr/include と /usr/lib への シンボリックリンクを作る。

    • 正しく環境設定できれば、PATH_MAX が定義されないという状態にはならない。

      #include <stdio.h>
      #include <limits.h>
      #include <stdarg.h>
      #include <stddef.h>
      main() {
      #ifdef __mipsel__
      printf("hello world (mips) %d\n",PATH_MAX);
      #else
      printf("hello world\n");
      #endif
      }

      たとえばこんな ソースをコンパイルして

      /usr/mipsel-redhat-linux/lib/gcc/mipsel-redhat-linux/4.4.5/include/limits.h
      /usr/mipsel-redhat-linux/include/limits.h
      /usr/mipsel-redhat-linux/include/bits/posix1_lim.h
      /usr/mipsel-redhat-linux/include/bits/local_lim.h
      /usr/mipsel-redhat-linux/include/linux/limits.h

      この順番で linux/limits.h が include されれば OK 。絶対パスで記述したが、実際の読み込みのパスは次のようになっている。

      /usr/mipsel-redhat-linux/bin/../lib/gcc/mipsel-redhat-linux/4.4.5/../../../../mipsel-redhat-linux/include/...

      これは、/usr/mipsel-redhat-linux/bin に gcc などバイナリを置いた場合。/usr/bin に上書きすると、相対パスと絶対パスが入り交じって少々ややこしくなる。

      コンパイルは、gcc , gcc -static , g++ , g++ -static で試す。

      ちなみに、現在の壁は、openldap と python 。python はビルドできたが、モジュール関係のビルド 環境が変。そしてこの 2 つの パッケージのせいで、多数の spec ファイルを書き換えるハメになっている。出来たら解決しておきたい。

        openldap は、nss, nspr と unixODBC を要求する。unixODBC は、qt を要求するのだが、spec を書き換えてユーザインターフェイスをなしに出来て、なんとかビルドできた。だが nspr とかは全然進捗なし。結構厳しい。

      それでも結構な数の RPM は、ビルドできた。現在は 430 個。... といっても SRPM の数で言えば 160 。作ろうとしてる SRPM は全部で 500弱。やっぱり 1/3 ぐらい。

      バイナリを /usr/bin 以外に置く場合、/usr/lib/rpm/ の設定を変更しないといけない。/usr/bin/strip など 絶対パスが入っているものは、都合が悪い。
posted by すz at 11:05| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2010年10月21日

Linux(r237)のテスト

ベースバージョンをr237に変更したが、そろそろテストを開始しようと思う。

まずは、ブートするまでの流れを おさらい。

  • メモリマップ:

    0x80000000
    割り込みベクタとか
    0x80002000
    (8KB) (1)xburst_stage1
    (stack)
    0x80004000
    0x80010000
    0x80100000 (offset 1MB) :
    (u-boot ) : (4)kernel(vmlinux.bin)
    : + initrd
    0x80600000 (offset 6MB) 0x80600000(max)
    (3)kernel (zImage)

    0x81c00000
    (4MB) (2)xburst_stage2
    (stack)
    0x82000000 (32MB の場合)

  • usbboot で boot コマンドを入力すると、xburst_stage1/2 をロードして 実行する。stage1 はメモリとかクロックとかハードウェアの初期化で、stage2 は、コマンド処理。stage1 は実行後不要になる。
  • kernel (zImage) は、0x80600000 にロードして同じアドレスから実行する。改造した usbboot では コマンドラインも渡せるようにしている。
  • kernel (zImage) は、0x80010000 から 内蔵したイメージを展開していく。イメージは、vmlinux.bin + initrd 。
    パラメータ(コマンドラインのアドレスとか) はセーブしていて、vmlinux.bin を実行するときに渡す。
  • vmlinux.bin の開始アドレスは、kernel_entry (arch/mips/kernel/head.S)
  • kernel_entry は start_kernel(init/main.c) を呼び出す。
  • start_kernel では、かなりの初期化を実行した後(printk すら 使えるようになった後)、setup_arch(arch/mips/kernel/setup.c) を呼び出す。ここから プログラムのメモリ(BSS) 以外のメモリの初期化とかが始まる。

次に、前回 (r108) でどこまで実行できたか

  • zImage をロードして制御を渡す 。OK
  • start_kernel 実行開始 OK 。
     - LCD のバックライトを点灯させることで確認
  • setup_arch 実行開始 NG 。
     - setup_arch まで行かない。


今回は、r237 ベースに変更してしきり直す。

今回からは、バックライトに加えて、赤黄の LED が使える。また、ある程度処理が進めば、
LCD へのメッセージ出力 も可能になる予定。

さて、前回と同じところまで行くものなのか確認 -- したら全然動かない。

困った。全く動かない。

過程を書くとちょっと込み入った話になるので、パスして結果だけ。

  • zImage が カーネル(kernel_entry)に処理を渡すのは確認できた。
  • だが、kernel_entry から startup_kernel に処理がわたらない。
  • 細かく調べると 冒頭の mtc0 が動かないことが判った。

      kernel_entry:
      800144f0: 40086000 mfc0 t0,c0_status
      800144f4: 3c011000 lui at,0x1000
      800144f8: 3421001f ori at,at,0x1f
      800144fc: 01014025 or t0,t0,at
      80014500: 3908001f xori t0,t0,0x1f
      80014504: 40886000 mtc0 t0,c0_status

    • c0_status というのは、カーネルモードとか割り込み禁止とかの CPU の動作モードや 割り込み原因などのステータスが格納されているレジスタ。
      このコードは、それのビットを立てたり落としたりしている。

      c0_status の意味:(一部)
    • bit4 UM
    • bit2 ERL (RESET/NMI 発生時に 1)
    • bit1 EXL (通常例外/割り込み発生時に 1)
        - UM=1 かつ ERL = 0 かつ EXL = 0 のときユーザモード。
    • bit0 IE (1: 割り込み許可 / 0: 割り込み禁止)

  • c0_status になにを設定すると動かないのか細かく調べたところ

    もとのデータは、0x1240CE16 が多いが このうち
    0x4 -- ERL ビットを 0 にすると 止まるか暴走する
    ことが判明。
    ちなみに、暴走した後放置しておくと、フラッシュから立ち上がった。

  • 調べると Reset や NMI で実行開始した場合 ERL bit が 1 になる。
    ERL を 0 にするには、

    (1) ERET で復帰
    (2) プログラムで 0 を書き込む

    の 2 通りがあるらしい。(2) では暴走するのだから (1) の方法を使うのか?
  • 頼りになるものは、u-boot のソースコードぐらいだが ... JzRISC では

    /* CU0=UM=EXL=IE=0, BEV=ERL=1, IP2^7 = 1 */
    li t0,0x0040FC04
    mtc0 t0,CP0_STATUS

    としていた。

ERL=1 だと割り込み許可ができない(or 無効) 。困ってしまったが、最初の割り込み許可までは、動作確認できるはず。
とりあえず
  • 先頭の CP0_STATUS の設定 (arch/mips/kernel/head.S)
  • raw_local_irq_disable (arch/mips/include/asm/irqflags.h)
  • raw_local_save_flags (arch/mips/include/asm/irqflags.h)
  • raw_local_irq_restore (arch/mips/include/asm/irqflags.h)
の 0x1f を 0x1b にすることで 先に進むことにした。

  • 大雑把にいうと動作モードには、ユーザモード/カーネルモードがあるが、カーネルモードにも種類があって、ERL=1 は NMI/Reset での実行状態/EXL=1 は 例外(システムコールとか)・割り込みが起きたときの実行状態/UM=ERL=RXL=0, は通常の実行状態。
    上記の対処は、ERL を変更しないようにしたということ。

こうすることで、setup_arch の直前まで来た。

さて、setup_arch の直前には printk が入っている。これをどう表示させるのだろう?

ちゃんと調べてみると arch/mips/kernel/early_printk.c というのがあってここで定義している。で、call する関数は prom_putchar() 。
そして、prom_putchar() は、(現config では) シリアルを使う版が arch/mips/jz4750l/board-a41.c に記述されていた。

ならば、prom_putchar() を LCD を使うように書き換えてみたところ .... 出た。



最後のメッセージは、NR_IRQS:256 で ここから先は、やはり ERL を 0 にしないと無理そうだ。

それはともかく、いくつか気になるところがある。

  • F4750L とあるが、もう分離しているのだから、A-41 / A-33 に変更しなくては。
  • メモリが 64MB 認識されてしまっている。

    usbboot -f /etc/xbufst-tools/a41-boot64M.cfg

    として起動しているので、64MB の RAM は実際にあるし使える状態。だが、

    usbboot> exec arch/mips/boot/compressed/zImage mem=28M

    として起動しているのだ。( exec は、新規で作成した コマンド )
    mem= を認識させないと stage2 が壊れてしまう。
    ... それにしてもなぜ 64MB と分かるのだろう? トータルのメモリサイズは渡していないのに。

      64MB は、JZ4750L では、ハードコーディングされていた。

      zImage だと 0x80600000 にロードして、先頭から実行すれば良いのだが、別の起動方法もある。
      objcopy で vmlinux を 変換し、0x80010000 にロード。
      実行は先頭ではなく、kernel_entry のアドレスを nm で調べて(いつも同じアドレスだが) そこに go する。具体的には、

      # mipsel-linux-objcopy -O binary vmlinux vmlinux.bin

      usbboot> load 0x80010000 vmlinux.bin 0
      usbboot> go 0x800144f0 0 mem=28M

      ... この方法だとテストプログラムで パラメーターを渡す実績もあるのだが.. linux で認識してくれなかった。... バグっているらしい。

テストその2(続き)


これで、どこまで行くか調べたところ、init_IRQ() (init/main.c) から call される arch_init_irq() (arch/mips/jz4750l/irq.c) までだった。

clear_c0_status(0xff04) /* clear ERL */

というのがあって、ここではじめて ERL を clear しているつもりらしい。意味がないので、0xff00 にしておいた。


    これで次に止まるのは、次のところと分かっている。
  • raw_local_irq_enable (arch/mips/include/asm/irqflags.h)
    -- 0x1f を 0x1b に 0x1e を 0x1a にしておく。


最後に止まるのは、calibrate_delay() -- 実際にタイマ割り込みが来ないと 先に進めないようだ。

  • ちなみに、calibrate_delay() が完了すれば、おなじみの BogoMips が表示される。


さてどうしたものか ...Linux カーネル Tree にマージ申請したときの紹介には、

  • The JZ4740 has a mostly MIPS32 4K compatible core (no on cpu timers)

と書いてあるのだが ...

とりあえず、MIPS 4K ファミリーの Software User's Manual というのを見てみる。CP0 のレジスターは、 $0-$31 まで定義されていて、

    $12 STATUS (上記の c0_status のこと)
    $14 EPC (通常の例外・割り込みからの復帰アドレス)
    $30 ErrorEPC (NMI/Reset からの復帰アドレス)

と書いてある。実際に値を読みだしてみると...

    $14 EPC 0xADD273F3 とか 0x8DDA73F3
    $30 ErrorEPC 0x94D5BFFF

なにか初期値がそのまま入っている感じで電源投入の毎に微妙に値が変わるのだが、起動後は、何回読みだしても同じ値。

これらに 適当な値を入れて ERET すると ... ユーザモードになって ... 結局アドレスエラーで 例外が起きそう。では、BEV を 0 にした上で、0x80000180 とか 0x80000200 の一般例外ベクタから 望むアドレスへの ジャンプ命令を書いておけば良いのだろうか?

で、それをどこでやるのが適切なのだろう? やはりブートローダからのカーネル実行?

  • ERET は、カーネルモード(通常 NMI や例外・割り込みで切り替わる)からの復帰命令。


    これをテストプログラムでやってみた。

    0x80000180からの例外ハンドラは、

    3c028000 lui v0,0x8000
    24420170 addiu v0,v0,0x170
    8c480000 lw t0,0(v0)
    8c440004 lw a0,4(v0)
    8c450008 lw a1,8(v0)
    8c46000c lw a2,12(v0)
    01000008 jr t0
    00000000 nop

    こんな命令列にする。その 16バイト前から ジャンプアドレスと パラメータを入れておく。なにか例外が起きれば、ここが実行されるわけだ。例外は故意に起こすが一旦ユーザモードに入らないといけないので、ERET を使う。( ErrorEPC にアドレスエラーを起こす値を設定しておく。)

    プログラムに実行が渡ったときの c0_status は、

    0x1200EE13 -- UM = 1 , EXL = 1, IE = 1

    状態としておかしくない。で、
  • IE を 0 / 1 にするのは OK 。
  • UM を 0 にするのは OK 。
  • EXL を 0 にすると ... 例外。
    という動作になった。... どうも ERL/EXL を変更するのはダメのようだ。

    それはともかくこれで割り込み禁止/許可ができる。

  • ブートローダ(usbboot) で 例外を起こして Linux 実行。
  • Linux では ERL/EXL を変更しない。
      0x1b を 0x19 に / 0x1a を 0x18 に

    という方針でやってみる。...

    ところでなぜこんな変なのか? 推測するしかないが、例えば UM/ERL/EXL の状態に応じたシャドーレジスタがあるとか
    ... 他のものがちゃんと動いているはずだし ... なにか設定があるのだろうが今のところ分からない。

で、やってみた。割り込みが許可できるようになったが、calibrate_delay() で止まる。

ちょっと見たところ jz4750l と jz4750 で time.c が全然違う。 jz4750 や jz4740 の time.c をコピーしてもビルドはできるが、やはり動かない。

    ちょっと CPU の違いをメモ

    OS Timer (32 bit) 16bit PWM
    Jz4740 x 8 8(?)
    Jz4750 o 6 6(0-5)
    Jz4725B o 5 5(0-3,5)
    Jz4755 o 6 4(1-3,5)

  • jz4750 では、タイマー割り込みには、timer5 を使用している。
  • OS Timer は、get_cycles 用に使用。

    jz4750 と互換性はありそうだが、PWM の都合上 timer0-2 にしないと困りそう。
    割り込みには、TCU0-2 の 3 つがあり timer5 は TCU1 ?
    jz4740 では、timer0 / timer1 / timer2-7 で 3 種類の割り込み。

    (linux の分類の) jz4750 と jz4750l では、レジスタの定義が一部違う。

    jz4750:
    #define IRQ_MSC1 13
    #define IRQ_MSC0 14
    jz4750l:
    #define IRQ_MSC1 24
    #define IRQ_MSC0 25

    jz4725B はいったいどっちなのか? それともまた別なのか?
    ちなみに DMA チャネルのの数

     jz4750 12
    jz4755 8
    jz4725B 6

    jz4750:
    #define MAX_DMA_NUM 12 /* max 12 channels */
    jz4750l:
    #define MAX_DMA_NUM 8 /* max 8 channels */


    jz4755/jz4725B は、jz4750l に近そうだし、CONFIG_FPGA で切り分けできるし、jz4750l を間借りして良かったとは思うのだが ... 情報がないし骨が折れそうだ。

    でも usbboot で テストプログラムを動かせるし、実際に割り込みが起きたらどのビットが立つのか調べることはできるから、あまり心配はしていない。

    もうすこし調べてみると、(INTC)割り込みコントローラと(CPM)クロックジェネレータがだいぶ違う。-- この違いは、付いているデバイスの種類と最大数の違いから来るものでやむを得ないようだ。
    あと (CIM)カメラインターフェイス と (IPU)イメージプロセッシングユニットが違う。-- これは、jz4750l が 設計中のもので変なのだろう。

    追記: なんと Jz4755_pm が入手できた。これを見ると 割り込み原因のビット割り当ては jz4750l に合致する。
    Jz4725B は、4755 を shrink したものだろうから たぶん jz4750l で良いはず。
    タイマーの割り込み割り当ては、timer0,3,4,5 が TCU1/timer 1,2 が TCU2 。
    クロック供給の設定も jz4750l に合致。

    ただし、
    #define INTC_ISSR (INTC_BASE + 0x18)
    #define INTC_ISCR (INTC_BASE + 0x1c)
    は存在せず、INTC_ICSSR が変なアドレス(0xB3016000)にある。

まぁ、ここらあたりで一旦整理しようと思う。
usbboot の 起動方法が変わったので いままでの テストプログラムの動作に問題が出るし。

    asis 版
  • linux-jz4725b-r237-wk.tar.bz2
  • usbboot-wk14.tar.gz

    usbboot は、1 回実行すると そこで終わりになった。割り込みをいじったりする場合は仕方ないとしても今までのプログラムも最後に暴走することになる。

    内部で状態を変更してからの実行にしたい。そのためには、少々面倒なことをしないと。
    引数が 使えるから、レジスタをセーブして、引数にセーブエリアをわたして、例外つかって jump 。... みたいな。

    追記:いろいろやってみたのだが、結局

    ERL = 1, EXL = 1 → ERL = 0, EXL = 1

    ならなんの問題もないことが判った。

テストその3(続き)


現在は、calibrate_delay() で止まっている。

タイマー割り込みの処理が実行されて jiffies がカウントUP されば、BogoMips が表示されて先に進むはずだが 割り込みの処理が実行されない。

で、local_irq_enable() call した後 (init/main.c) で、いろいろレジスタを表示させてみた。

    c0_status 10000403 (EXL = 1, IE = 1, only Hard Int 0 is enabled )
    c0_cause 30c00700 (Hard Int 0 is caused, Excepton code = Interrupt)
    CPM_CLKGR 00000000 (All Clock Gate are opened)
    INTC_ISR 00200040 (TCU2 , RTC are pending)
    INTC_IMR ff5fffff (TCU0, TCU2 are not masked)
    INTC_IPR 00200000 (TCU2 is active ?)
    TCU_TSTR 00000000
    TCU_TSR 00000000
    TCU_TER 00008004 (OS Timer , timer 2 are enabled)
    TCU_TFR 00000004 (timer 2 is FULL comparison matched)
    TCU_TMR 003f003b (Os Timer, timer 2 are not masked FULL comparison match intr)
    TCU_TCNT2 00000a42
    TCU_TCNT2 0000099f

なんだか正常そうなのだ。timer 2 を使って 周期的に割り込みを起こし、TCU2 の割り込みが発生する設定なのだが、timer 2は進んでいるし、TCU2 の割り込みも発生していて pending になっている。

割り込みも許可できているつもりだが ... 違った。ERL と EXL ともに 0 でないと割り込みは来ない。結局最初の問題に戻る。

いろいろやってみたら... write_c0_cause(0) をしてから EXL = 0 にすると ... 先に進んだ。

... で mtd が組み込まれてしまい。

bad eraseblock 210 at 697f000
Bad eraseblock 2598 at 5137f000
Bad eraseblock 2600 at 5147f000

こんなメッセージが ... まだオリジナルのファームウェアを壊すつもりはないので焦ったが、一応立ち上がった。

とりあえずメッセージが流れてしまったので、途中で止めて BogoMips をみてみた。

226.91 BogoMips 

だそうだ。CPUクロックを 228MHz にしているので、CPUクロックにほぼ一致する値になるらしい。

結局、arch_init_irq() (arch/mips/jz4750l/irq.c) の

clear_c0_status(0xff04) /* clear ERL */

write_c0_cause(0);
clear_c0_status(0xff1f) /* clear ERL */

に変更するだけで良かった。(ここまで ERL=1 / EXL=1 で来るので、割り込み禁止とかの変更はイキ)

次は、console とか パラメータとかをキチンとしよう。

    asis 版
  • linux-jz4725b-r237-wk2.tar.bz2
  • usbboot-wk15.tar.gz

    たいして変わっているわけではないのだが、ここまでの分のバックアップ。
    usbboot-wk15 は、wk13 ベースに戻した上で wk14 のテストコード追加。


追記: 結局 write_c0_cause(0)は、usbboot でもすることにした。これで、c0_status 周りを元に戻しても問題なくなった。.. のだが別に悪影響があるわけではないので当面すのままにしておく。

さて、今は usbboot での環境を整備しようかと思い、jz47xx の reg.h と ops.h を見ている。jz4740 や jz4750 といったチップ毎に reg.h ops.h があるのだが、どこまで同じで、なにが違うか分かるようにするため、チップ毎のファイルを コントローラ毎に してみている。

  • ひとつ重大なことを発見。.. jz4740 と jz4750l の rtc のコードにバグがあった。jz4750 だけ直してあった。

  • コントローラ毎に してみると ほぼ同じものもあるが、全然違うものもある。SLCD (Smart LCD) はあまり変わらないのだが、LCD (Generic LCD) は、機能が大幅に拡張されていて レジスタの数が 2倍ぐらいになっている。全然違うのは、他には CIM (カメラ) , ICDC (internal CODEC) 。あと SSI や MSC(SDカード), DMAC(DMA コントローラ)は、コントローラーが複数になっていて マクロが変更になっている。
  • INTC (割り込みコントローラ) , CPM(クロック) などは、周辺デバイスの構成が変わっているので チップ毎に違う部分がある。

  • ICDC (internal CODEC) は、Jz4740系 と Jz4750系ではまったく違う。Jz4740系 は、レジスタが普通にメモリにマッピングされているが、Jz4750系は、まるで別デバイスのようだ。
  • IPU のヘッダファイルは変。他のと違う。アプリケーションからとってきて突っ込んだ感じ。Jz4750 と Jz4755 も違うので困惑したが、デバイスそのものは同じだった。編集して 他のに合わせることにした。
    ついでに jz4740 の pm を見て比べたところ、互換性はだいぶあるが、随分拡張されている。
  • OTP(One Time Programmable Module というのがあって、そこにチップの情報が格納されている。
    プロダクトID やら ユニークな ID を作れる情報もある。

まぁこんな感じ。この作業を通じて だいぶ分かってきたような気がする。

Linux については、ちょっとお休み。パラメータはちゃんと渡っていることは確認できた。... が xburst_stage2 に callback すると panic することが分かった。ちゃんと panic まで来ているのだが、なぜなのかまでは分かっていない。これをどうにかしないと... 先に進めない。

ついでに書いておくが、手持ちのなかで Neo Slim 3000 だけが採用している HSYN/VSYNC インターフェイスの LCD は、なかなか使うのが難しいことが判った。DMA も必要だし 周期的に表示するため タイマも動いていないといけない。-- 要するに最初のデバッグに利用するのは困難。

posted by すz at 19:02| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2010年09月20日

FLASHの使い方(案)

MTDのパーティションについて

    細かく分けてしまうと、ウェアレベリングをそのパーティション内でやらざるを得ないという問題が出る。スワップは領域が小さい上に書き換え頻度が多くなることになり、持つこと自体が厳しくなる。そのため、大きな領域にして UBI パーティションとして、その後の分割は後で考えることにしたい。

    UBI 以外は、ブート用と カーネル用のパーティションに分ける。
    ただし、使うのは先頭だけで、隙間をたっぷり取っておく。(
    隙間の使い道はあとで考える。)

      4MB ブート用 (代替ブロック 2)
      60MB カーネル用 (代替ブロック 2)
      残り UBI 用 (代替ブロック 10)

    こんなところでどうだろう。

と書いた。これについてもう少し考察しておきたい。

    最新の案:

    4MB ブート用 (代替ブロック 2)
    60MB カーネル用 (代替ブロック 2)
    残り UBI 用 (代替ブロック 200 for 4Kpage,2GB)




E7002(tcc8902) のファームウェアアップデート方法についてちょっと調べた。ポイントだけ書くと、

  • FWDN というツールでアップデートするが、tcc8902 の USB boot にも対応している。
  • 書き込むデータはいくつかに分割されている。その種類は、
    Boot Loader , Kernel Image, Ramdisk File, MTD(tcc8900_mtd.img :121MB)
  • >MTD については、NAND Data.fai (730KB) というファイルも必要。

FWDN が MTD を外部から書くのだとすれば、バッドブロック処理は必須で、そのための情報が NAND Data.fai のような気がする。(違うかも知れない)。
Boot Loader , Kernel Image, Ramdisk File についても バッドブロック処理があるのかも知れないが、簡単なものではないかと思える。

いま作ろうとしているものも事情は同じ。上記も参考にしよう。

まず、ブート用、カーネル用 の書き換え頻度は少ない。 バッドブロックが新たにできる確率は小さい。それでも 初期状態ですら存在する確率は 0 ではないので、対処だけはしておく。

対処は、簡単なもので良く、mtd ドライバのバッドブロックに対応すれば十分。対応は、書き込みツールと Boot Loader など読み込むコードで行う。Linux の方法を採用しているだけだから、Linux 自体は なにもしなくて良い。

さて問題は、UBI 用である。手持ちの SSD は、32GB/2Kブロック (16K 個のブロック)に対して、1000個ほどの代替ブロックを用意している。2GB/512B ブロック なら 4K 個のブロック数なので、250 個ほどは 代替ブロックが必要という計算になる。にもかかわらず 10個ほどしか用意しないのは、mtd の仕組みは 使わないと思っているから。

問題は バッドブロックだけではない。たとえ再インストールしても いままでの書き換え回数の情報は残したい。

で、それをするためには、UBI は、Linux で必ず更新する..ということにしまうのが一番簡単である。

インストールする際にも、Linux を動かして Linux が自分で UBI を初期化することになる。

そう決めたときの課題は、インストールする内容をどこから持ってくるか。

  • USB から
    インストールは、USBBOOT だけで行なおうと考えている。それならば自由度は高く USBBOOT 経由でデータを転送することが可能ではある。

    ただそうした場合、ドライバーを作成しなくてはならない。これは大分面倒。

      もうひとつは、microSD/SD から。

      これは、どこに置くか決めるだけで面倒ではない。だが、操作のほうが面倒だ。データは PC にあるので、microSD/SD にいちいち書きこまなくてはならない。

      スターンドアローンで アップデートできるなら microSD/SD に置いても良いのだが.. 一部は PC / 残りは microSD/SD というのは避けたい。

    • カーネル用パーティションから

      これが一番簡単。ただ、容量が足りなくなるのが心配だし、容量が無駄に使われるのが嫌な点。

      足りなくなる点については、少し考察してみよう。オリジナルのファームウェアは、圧縮して 20-30MB 。android 2.1(tcc8902) は、60MB ほど。ubuntu を採用した SmartQ5 では、170MB ほど。

      android ですら 60MB なら、個人が用意できる基本ファームウェアがそれ以上になるとは思えない。それでも超える場合は、上の方法を使うということでどうだろう。

    まぁ.. こういうわけで、圧縮したイメージを カーネル用パーティションの隙間におくことにしよう。

    次の問題は、インストーラ。インストーラ用のカーネル と initrd を別に持つというのもひとつの方法だが、正規の initrd に 組み込んでしまうのはどうか?

      あるボタンを押して立ち上げれば、initrd がそれを認識して、インストールを行う。初期化できたところで、正規の mount 処理を動かす。

    こんなかんじ。新しくなっていれば、自動的にインストールするのでも良い。

    どうしても panic するという自体になってしまったら、初期化すれば立ち上がる。

    ただ、ユーザのデータと その下位構造の UBI は勝手に壊さないようにする。ユーザのデータや UBI まで壊れた場合は、確認を求める。No! の場合、その場は電源を切る。後で USBBOOT を使った修復ツールを動かすとか別途考える。

    パーティションの容量配分は、これで良いか?


      4MB ブート用 (代替ブロック 2)
      60MB カーネル用 (代替ブロック 2)
      残り UBI 用 (代替ブロック 10)


    と書いたが、これで良いのだろうか? まず、代替ブロックとはどういう単位で代替するのか? 代替ブロックのために 容量がどれだけ犠牲になるのか知らないといけない。

      ちょっとコードを見てみる。代替ブロックの定義は、get_jz_badblock_table() を call することで取得する。

      これは、mtdblock-jz.c の mtdblock_zone_init() で行っている。
      で、reserved_sectors という変数に 得た値 を (phys_erase_shift - 9) だけ左シフトして格納している。

      どうも reserved_sectors は 512B 単位で 代替ブロックの単位は、消去ブロックサイズ (4Kpage なら 512K)らしい。

        そうなると 4MB の ブート用パーティションは 1MB 取られていることになる。

      次に管理領域。
       total_virt_block = total_phys_block - bad_block_num
      (単位:消去ブロック, total_phys_block は、mtd の size(バイト単位) を phys_erase_shift している。)
      となっているから、reserved_sectors に管理領域が含まれているようだ。

      さて、エラーを見つけたら マークを付けるようだ。これは nand_base.c の nand_default_block_markbad() 。見ると OOB に対して 2 バイト分 上書き?している。

      それはともかく、それをどう変換するのか .. 関数は、mtdblock-jz.c の mtdblock_address_translate() らしい。これは block_lookup[] という配列を使って virt → phys の変換をしている。512KB 単位なら 4GB でも 8K エントリで 32KB しか消費しないからこれで良いのだろう。 --- 問題はそれをどう作っているか? ということになる。

      どうも nandblock-jz.c の mtdblock_block_lookup_map_entry() というのが更新する関数らしい。そして、badblock を見つけたときに どこを割り当てるかというのは、mtdblock_find_free_block() ということらしい。

      なにをしているかというと block_info[] を頭からサーチして、free block の マークが付いているものをさがしている。

      block_info[] をどう作っているのか調べないといけない。ちなみに、erase すると block_info[].lifetime を +1 している。

      このデータをいつどう書き戻しているのかというのは結構重要そう。
      block_info は、

      struct mtdblk_block_info {
      unsgined int lifetime;
      unsgined char tag; /* 0x01: FREE 0x02: BAD 0x04: EMPTY*/
      };

      という構造。mtdblock_zone_init で read_oob して メモリ上の配列として構成しているようだ。

    ここまでの理解は、

    • read エラーを見つけたら 消去ブロック単位で代替する。
    • 代替ブロックは oob を線形サーチすれば見つかる。(管理のための領域は、データブロックにはない)

    カーネル用の領域は、こういう仕組みが役に立つだろう。普通なら 5% の代替エリアが必要だとすれば、6 個ぐらいあった方が良い。書き換え頻度が少ないが 代替の単位が大きいので 2 個では不安なのだが、これで行くことにする。

    それに対して ブート用はどうだろう? カーネルでの書き換えは 4Kpage の場合 512KB 単位になるわけで、4MB で 8 つの エリアがある。壊れれば代替してくれるわけだが、先頭が壊れた場合 代替してくれても困るかもしれない。でも、なにか物理的な先頭ページにアクセスする手段があるのだろう。そうだとすれば、壊れていた場合に mtdblock の先頭にアクセスすると、代替されて 無駄に 1 ブロック使われるという弊害がでるが、気にしないことにする。

    8 個のブロックのうち ブートローダが 1 個。代替に 2 個。5 つのエリア(2.5MB) は自由に使えることになる。

    5 つのうち 少なくとも 1 つはカーネルパラメータを入れたい。(
    2 つ 3 つあっても良い。)

    残りは、u-boot を使いたくなった場合に使うことにする。一応 2 個のエリア (1MB) 確保できているから大丈夫だろう。

    最後に UBI 用についてなのだが、512KB 単位で代替しているわけがない。10 個あっても UBI を通して使う限り関係ないはず。

    mtdblock としてアクセスした場合に 代替されてしまうかも知れないのだが、そういう場合も、UBI を通せば関係ないような気がする。

    というわけで UBI もこのままで良いだろう。

      追記: どうも良くないようだ。

      badblock の処理は 下位レイヤに従う。... どうも badblock が出来にくくするために ウェアレベリンングを行うのであって、badblock が出来てしまえばすなおに代替するようだ。

      そうであれば 5 % の 200 個 必要そうだ。これは 4Kpage,2GB の場合で 2Kpage や 4GB なら倍の 400 個。


      実際の OOB の代替ブロックを示すデータについて:

      OOB に格納する形式は、

      struct mtdblk_fake_fsbuf {
      unsigned int block_addr_field1;
      unsigned int block_addr_field2;
      unsigned int lifetime;
      };

      という形式で、oob のオフセット 2 から格納されている 。
      block_addr_field1 , block_addr_field2 に virt_block 番号が入っていて、読み出したとき同じなら正しいデータと見做す。
      lifetime は 消去回数。

      このデータがどこにあるかというと、各消去ブロックの先頭ページに対する oob 。次のページから CONFIG_MTD_OOB_COPIES 分だけ同じデータがあり、壊れていたら コピーを見ることになっている。

      あと、代替ブロックが出来ていたら、代替ブロックの方を常に見ないと整合性が取れない。壊れているという mark はどこにあるのか?

      どうも nand_default_block_markbad() という関数でこの処理をやっているらしい。

      .. 見てみると、代替する場合は、各消去ブロック の 127ページ 目の oob の先頭から 2 バイトを 0 にする。判断は、先頭の 1 バイトが 0xff 以外だったとき 代替されていると判断する。
      (そういえば、バッドブロックのコードは、usbboot にもあった)

      これで、OOB の 先頭から 14 バイト分がどう使われるかは分かった。( そして 4Kpage で 8bit-BCH の場合は、 オフセット 24 から 最後まで ECC が入る。)

    (つづく)
posted by すz at 16:58| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2010年09月15日

ベースバージョンをr237に変更

qi-hardware が ingenic が出しているソースを Ingenic Linux 2.6.31.3, READ ONLY: live Ingenic development tree として管理している。

いままでベースにしていた r108 は 4 月頃にここから svn で取得したものだが、大分違ってきているので、再度 svn でダウンロードした。(r237) 。

どうせ全然動かせていないし、(追加はしたが)変更もしていないに近いので今のうちにベースを上げておこうとおもう。

例によって 次に整理したものを置いておく。


これをベースにして、いまで使ってきた config ベースでビルドできるようにして、さらに ソース Tree の シュリンク版も作る。

さて、最初の問題は、JZ4750L ではビルドできない所がある点。あと、JZ4750L だけサポート外にされている Kconfig がある JZCHAR と MMC(HOST) 。

jz_ubcomm は入れずに、これらだけを直す変更をしたパッチを作ることにする。

また、JZ4750 がどのようにコンパイルされるか知りたいので、JZ4750 の apus もビルドできるようにしておく。(ただし USB HOST や ETHERNET , WIRERESS , YAFFS 関係 と NFS_V4関係は入れない )

ECC 関係で変なところがある。CONFIG_HW_BCH_ECC=y とすると YAFFS の中のコードを call するのだ。

    -- 適当に取ってきたスナップショットなので、コードが中途半端なのかも。

.. それはともかく、JZ4725B は JZ4750 と同じ機能を持っているのかどうかが重要だ。

データシートを見てみると、JZ4725B は、4/8/12 bit ECC をサポートしているのに対して JZ4725 は 4 bit ECC しかサポートしていない。データシートを見ると記述がいろいろ違うのだが、

  • JZ4740 まで Hamming or Reed-Solomon ECC をサポート。
    -- CONFIG_MTD_HW_HM_ECC or CONFIG_MTD_HW_RS_ECC
  • JZ4750 4/8/12 bit BCH ECC をサポート
    -- CONFIG_MTD_HW_BCH_ECC (CONFIG_MTD_HW_BCH_4BIT or CONFIG_MTD_HW_BCH_8BIT)

ということなのだろう。APUS は CONFIG_MTD_HW_BCH_8BIT を使っており、JZ4725B も同じで良いはず。

JZ4750L(JZ4725B) を同じにするには、ソースで JZ4750L が仲間はずれにされているところを修正していかなければならない。Kconfig だけでなく nand_base.c にもこのようなコードがあった。

    drivers/char/Kconfig の RTC_JZ , drivers/usb/gadget/Kconfig の UDC_USE_LB_CACHE , あと、driver/usb/gadget/udc_hotplug.c
    他にもあるが、touch-panel サポートなど、JZ4725B にない機能とかは外す。

ところで、ECC の種類の意味が判ったが、それがどのように OOB に格納されるのか?

used free
off len off len
2Kpage
Hamming 40 24 22 38
Reed-Solomon 28 36 2 26
4bit-BCH(?) 24 28 2 22

4Kpage
Hamming 80 48 2 78
Reed-Solomon 28 72 2 26 100 28
4bit-BCH 24 56 2 22 80 48
8bit-BCH 24 104 2 22

nand_base.c に テーブルがあって こんな風に定義されていた。(Hamming はオリジナルからあるが、それ以外は ingenic が定義している)

  • 8bit-BCH は、4Kpage で 104 バイト使用する。512B あたり 13バイト。4bit-BCHは、512B あたり 7 バイト。RS は 9 で、HM は、6 。

  • あとオフセット 0,1 の 2 バイトは free じゃないし特定の目的に使われるようだ。

  • 2Kpage では、8bit-BCH は 4bit-BCH と同じ定義 .. 入らないのだが ..

それはそうとして、USBBOOT の OOB の定義はこれとどう関わるのだろう? あと NAND からの boot では、ECC をチェックすると書いてあるが、どの ECC を使うか分かるのだろうか?
疑問は尽きない。特に JZ4750 系の資料を持っていないので、カーネルのコードから推測する以外にないのがつらい。

まぁ、ここではコードの詳細に入りたくないのだが ... この部分が変なので、ベースとしてどう扱おうか 困っているので、ちょっと見ているわけだ。でも、ついでなので続ける。

前からの疑問がある。USBBOOT の config で NAND_ECCPOS という項目があるのだが、これだけどう扱って良いのかわからない。

512B 毎に ECC を取って 6-13 バイトのデータを OOB に格納するらしいということは分かった。で、オフセットはどうも ECC の種類や ページサイズ で違うということも分かった。

で、NAND_ECCPOS とどう関係してくるのだろう?

    ちょっと USBBOOT の方を見てみる。

    NAND_ECCPOS は、stage2 で使う。これが nand_4750_init() のパラメータとして渡り eccpos という変数に格納される。(もし 0 なら 3 を入れておく)

    nand_4750_init() では、bchbit という変数も持っていて、それもパラメータで受ける。デフォルトは 8bit 。
    -- config に NAND_BCHBIT というのがあった。

    これが 8bit の場合 par_size = 13 としていて、それ以外(4bit) では 7 としている。

    オリジナルファームウェアがどのように使っているのか定かではないのだが、どうも 24 をいれればよいらしい。

    2Kpage だと 入らないので 4bit 以外の選択はないが、4Kpage はどうなのだろう? 8bit なのか 4bit なのか?

      対応しようと思っているものはほとんど 4Kpage なのだが、Neo Slim 3000 だけが 2Kpage。config で定義しないといけないので、とりあえず 4bit としておく。

    もうすこし見てみる。パラメータに NAND_BADBLOCKPOS(defualt 0) と NAND_BADBLOCKPAGE(default 127) がある。

    これは、消去ブロック(128ページ分) 全体を バッドブロック とするための情報で 127ページの oob の先頭 1 バイトが 0xff でなければ バッドブロックと判断している。

    それとは別に nand_mark_bad_page() という 関数があって page 単位で バッドブロックとする処理がある。これは、データと OOB に対して 0x00 を Write する。(バッドブロックなので 結果が 0x00 になるとは限らない )

    消去ブロック全体を バッドブロックとする nand_mark_bad_4750() では、nand_mark_bad_page() を NAND_BADBLOCKPAGE に対して行っている。

      NAND_BADBLOCKPAGE を 128 にすると、ブロックの最初 2 ページと 最後 2 ページに対して nand_mark_bad_page() する。

    ちなみに、Jz4740 では、PAR_SIZE は define で 9 になっている。ecc_pos は設定できるがデフォルト 6 で 2Kpage を想定。Reed-Solomon 固定ということなのだろう。ただし、offset のデフォルトは (ingenic の)Linux と合わない。

だいぶ分かってきた。

YAFFS の中のコードを call する点については、r108 → r237 で、nand_sw_bch_ops() という関数が追加されたことに関係するもので、nand_base.c と jz4750_nand.c だけを r108 ベースに戻してしまえば問題なくなる。

これで、コードのベースを確定できた。



ingenic オリジナル r237 の ソース tree に対して、linux-jz4725b-r237-base.patch を当てたもの から FILES-shrinked.list のファイルだけにしたものが開発のベース。

付属の config_jz4725b_base, config_apus_test, config_lyra_test で ビルドできることを確認。(その他の config はたぶんファイルが足りない)


こちらは、上記のパッチをあてて、shrink した
ソース tree 。

さて、OOB についてもう少し。

    A-41 や P5-5 の OOB を dump すると次のようなデータになっている。

    A-41
    011700 ff ff ff ff ff ff ff ff 57 59 4b b0 8b e5 53 90
    011710 9e 57 e5 96 be 61 37 3e 97 c8 45 27 dc 88 1d c6
    011720 14 58 75 2d 33 8a d6 f5 55 fe c5 62 53 09 3f 85
    011730 e3 b4 ac 14 bc 67 42 d0 77 64 0e 8d 39 f3 e6 98
    011740 96 bc 00 53 97 3b b8 0e 16 57 59 4b b0 8b e5 53
    011750 90 9e 57 e5 96 be 61 37 3e 97 c8 45 27 dc 88 1d
    011760 c6 14 58 75 2d 33 8a d6 f5 55 fe c5 62 53 09 3f
    011770 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
    P5-5
    026180 ff ff ff ff ff ff ff ff 77 6d 9f 45 e5 81 c5 4e
    026190 14 c6 58 f0 9e 81 bb 91 79 8a 41 9b bf 82 5d ce
    0261a0 1d 91 8f 5f cd 5f a2 29 eb de 63 1e 87 2a 13 b6
    0261b0 ce ce d8 36 96 ae 3c 74 3e 99 75 78 e0 a4 f3 33
    0261c0 95 5b 31 19 55 6e 5b c0 cc 27 85 c0 fc 4b b5 6d
    0261d0 6f a6 31 57 f7 31 7b f6 83 fd ab 17 7f ca 32 d4
    0261e0 b7 5b 23 e0 2d 5f f2 a8 66 96 f9 eb 16 8c 7f b7
    0261f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
    A-33
    061400 ff ff ff ff ff ff ff ff 2a 18 bd 90 dd e4 90 3d
    061410 6d f2 d3 fd 53 44 aa 74 52 9e cf 9b b0 71 81 77
    061420 6f 05 44 aa 74 52 9e cf 9b b0 71 81 77 6f 05 44
    061430 c8 a1 c2 41 0f af ba e1 ab 6a 7c 73 44 aa 74 52
    061440 9e cf 9b b0 71 81 77 6f 05 44 aa 74 52 9e cf 9b
    061450 b0 71 81 77 6f 05 33 86 fb 18 0a ce 41 84 a3 5f
    061460 b4 1f 60 44 aa 74 52 9e cf 9b b0 71 81 77 6f 05
    061470 44 aa 74 52 9e cf 9b b0 71 81 77 6f 05 44 aa 74

    先頭 8 バイト目からデータがはじまり、(最初の2つ)後ろ 16 バイトは 0xff 。データの量は 104 バイト。

    -- ということは、8bit BCH を使っており OOBPOS=8 ということだ。

    104 バイト以外が全部 0xff ということは、書き換え回数などの管理データは、まだ初期状態? (A-33 は、後ろ 16 バイトにデータが入っている )

    こういうデータだから Linux の管理に合わず Linux で NAND を使うなら共有できない。( ECC の位置だけ無理やり合わせても、管理データの使い方が同じとは思えないので無理 )

    ちなみに、2Kpage の Neo Slim 3000 を見てみたが、全然パターンが違う。原則にも合わない。ひょっとしたらバグで ちゃんとデータが取れていないのかも。

    Neo Slim 3000 の分析は後回しにしようと思う。


追記:jz_ubcomm-001 パッチを作った。

linux-jz4725b-r237-base をいれた上でこのパッチを当てる。

jz_ubcomm は、とりあえず作った分まで 入れた(= 動かない)。

いままでは、f4750l を借りて入れていたが、
CONFIG_JZ4725B_NS3K=y
とかした上で、board-ns3k.c board-ns3k.h なども作って入れることにした。

追加した config は、
CONFIG_JZ4725B_NS3K
CONFIG_JZ4725B_A41
CONFIG_JZ4725B_A33
CONFIG_JZ4725B_P55
の 4つで、board は、board-ns3k , board-a41 だけ作った。
(一応将来の変更も考えて、JZ4750L_NS3K ではなく、JZ4725B_NS3K とした。使わないが、SOC_JZ4725B も作ってある。)

あと デバッグ用に jz_backlight() というのを作ったが、apus , lyra にはないのでビルドできなかったので、スタブを入れてビルドだけはできるようにした。

board-ns3k.h をチェック

    JZ_EXTAL : 水晶の周波数を入れる。

    APUS は、24MHz , LYRA(4740) は 12MHz 。-- では JZ4725B は? ... とりあえず USBBOOT で 12MHz の設定で動作しているので、12MHz で良いだろう。( 動かし出したら時刻のずれから正確な値が分かるはず。)

    GPIO_XX : 各種 GPIO の定義

    GPIO_SD1_VCC_EN_N
    GPIO_SD1_CD_N (MSC1_HOTPLUG_PIN)
    GPIO_SD1_WP (MSC1_WP_PIN)
    GPIO_DC_DETE_N
    GPIO_CHARG_STAT_N
    GPIO_DISP_OFF_N (LDC_REV ?)
    GPIO_USB_DETE (GPIO_UDC_HOTPLUG)
    GPIO_LCD_PWM

    MMC/SD に 電源を供給する スイッチがあるらしい。-- 考慮してなかった。Write Protect も。充電IC の STAT にも普通つながているものらしい。DC デテクトも USB の専用機能でできるものだとばかり思っていた。LCDの OFF 機能だけは、LCD の線から選ぶはずだとは思っていた。どうも 思っていたより 4-5 本余計に必要なようだ。 --- JZ4725B では、とても厳しいはずだ。

    ちなみに LCD 関係は、drivers/video/jz4750_lcd.h で定義する。

    それ以外にオーディオ関係(スピーカ ON/OFF)があるはずだが .. どこでるのだろう?


追記:NAND のパーティション

NAND の パーティションは、drivers/mtd/nand/jz4750_nand.c で定義している。

機種情報を定義したので パーティションも一応定義しておこうと思う。

まず、最初の問題は、オリジナルファームウェアと 共存するか否かを決めないといけない。

今まで調べてきた限りでは、無理という結論で。好きなように使おうと思う。

APUS を見てみると、2GB を

    4MB ブート用 (代替ブロック 2)
    4MB カーネル用 (代替ブロック 2)
    504MB rootfs 用 (代替ブロック 10)
    512MB DATA 用 (代替ブロック 10)
    1024MB VFAT用 (代替ブロック 10)

としている。

こうやって細かく分けてしまうと、ウェアレベリングをそのパーティション内でやらざるを得ないという問題が出る。スワップは領域が小さい上に書き換え頻度が多くなることになり、持つこと自体が厳しくなる。そのため、大きな領域にして UBI パーティションとして、その後の分割は後で考えることにしたい。

UBI 以外は、ブート用と カーネル用のパーティションに分ける。
ただし、使うのは先頭だけで、隙間をたっぷり取っておく。(
隙間の使い道はあとで考える。)

    4MB ブート用 (代替ブロック 2)
    60MB カーネル用 (代替ブロック 2)
    残り UBI 用 (代替ブロック 10)

こんなところでどうだろう。

ところで、カーネルは、zImage を カーネル用パーティションの 先頭から 置く ことにして、ブートローダをどうするか?

実をいうと U-BOOT は使うのをやめることにした。

開発用は USBBOOT でいける。NAND からのブートも stage1/stage2 をベースにすれば自分で作れる。

U-BOOT が持っている高度な機能は使わない/使えない。

  • ファイルシステムからの読み込み
    UBI の上に構築された 、ファイルシステムを読めないといけないので無理と判断。その機能を使わないなら ベタイメージのロードなので、stage2 でもできる。
  • シリアルのオペレーション
    普通は開発用に シリアルを使うのだが、使わずに USBBOOT でなんとかすると決めた。USBBOOT を使うのであれば NAND に プログラムを置く必要はなく、U-BOOT の出番はない。


ちなみに、stage1 は、メモリの初期化など最低限度のハードウェアの初期化をする。それ以降なら メモリを使える。

stage1 の先頭は、ハードウェアの config 情報が入っている。これをバイナリに埋めておけば、ロード→実行 で 最低限度のハードウェアの初期化が終わるわけだ。

現在のサイズは 6KB 。stage2 をロードするコードを入れないといけないが 8KB 以内にできそうだ。

stage2 といっても 最低必要なのは、カーネルとカーネルパラメータをロードして 制御を渡すだけのもの。

とは言っても多少の機能は付けるつもり。

  • USB-BOOT に使うボタン(A-41/33 なら MENU) と ソフトウェア電源ボタン (A-41/33 なら PLAY/PAUSE) だけは 全部の機種で使えるので、多少のオペレーションもできるだろう。

  • LCDを扱うのは面倒だが、バックライトだけは使える。点滅させたりして、エラーを知らせることは出来る。


ところで、Nand からの ブートについて。

Jz4725 を使う SAKC のページに 0x80000004 から開始するということが書いてあったのだが ...

Neo Slim 3000 の先頭は

00: ff 55 55 55 55 55 55 55 ff ff ff ff 01 00 11 04
01: 00 00 00 00 21 e0 e0 03 00 00 e9 8f 21 e0 20 01
02: 00 80 1d 3c 00 40 bd 37 00 80 19 3c b8 06 39 27

となっていて、命令が入っているとは思えない。不思議に思っていたのだが ... u-boot のコードを見たら理解できた。

u-boot の cpu/mips/start.S を説明すると...

    オフセット
    0-3 : NAND が 8bit バスの場合 0xff,0x55,0x55,0x55
    4-7 : 常に 0x55,0x55,0x55,0x55
    8 : NAND_ROW_CYCLE==3 の場合 0xff
    9 : NAND_PAGE_SIZE!=512 の場合 0xff
    10 : NAND_PAGE_SIZE==2048 の場合 0xff
    11 : 不明
    12-15 : 最初の命令

ということらしい。上記 は、Neo Slim 3000 の例だが、A-41, A-33 ともに全く同じだった。

オフセット 8-11 は all 0xff なので、上記とは少し意味が違うようだが、とにかく 元の機種と同じもの -- all 0xff にすれば良いのだろう。

逆に 0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55 で始まっていないものは、Jz4750系の ROM イメージではない。

    実をいうと、各機種の ROM イメージのバックアップを取ってあるのだが、P5-5 だけ全然違う。... どうも失敗したようだ。

    追記:何回やっても違う。
    先頭はこんなパターン。

    00: 80 80 1f 3c 00 00 ff 27 00 90 80 40 00 98 80 40
    01: 80 00 09 3c 00 68 89 40 40 00 08 3c 00 fc 08 35
    02: 00 60 88 40 03 00 08 24 00 80 88 40 00 80 08 3c
    03: 00 40 09 35 00 e0 80 40 00 e8 80 40 00 00 08 bd

    256MB を 2 回 ダンプして cmp をかけ 不一致が起きるのは、107950 MB のところ。(USBBOOT で電源を入れるだけでなぜ不一致が起きるのか分からないが 他のマシンでも起きる ... それはともかく 頭の方はいつも同じ )
    だからと言ってこれでブートできるとは思えないのだ。... うーん困った。(バックアップが確定しないとイジる気が起きない)

ここまで分れば、nandbootの head.S などを参考に自作したほうが、見通しが良く便利。

jz_ubcomm-002 パッチ

まだまだ整理途中。動かそうともしていないし、ubcomm も無変更。


linux-jz4725b-r237-base をいれた上でこのパッチを当てる。

  • 常に base からの差分でパッチを作る予定 。
  • もし shrink 版で足りないファイルが出てきても、パッチは存在するものとして作成する予定で、エラーになったらオリジナルから取ってくる必要がある。
posted by すz at 23:12| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2010年09月14日

ソースをシュリンク

Linux のソースコードは大きい。bzip2 を固めたものでも 61MB もある。これを展開すると 420MB にもなる。

    420MB は、du で調べた値。ファイルシステムの消費量としてみる場合は、展開する前後で df で調べる。ext3 で試してみると ... 414MB で差はあまりなかった。ext3 は良いが、VFAT の microSD に 閲覧用として展開すると ひどいことになりそう。

ディスクスペースを使うのも問題だが、これだけのファイルを作ったり消したりするのは、SSD や (SD/microSD) ではやりたくない。

さらに diff をとったり grep するのに、対象ファイルが多いのは 遅くて不便。あと、grep で関係ないファイルがヒットすることも無くなる。-- これができると便利なときがあるかも知れない。(常に便利とは限らない)

... というわけでシュリンクした ソース tree を作ってみた。

方針として、ファイルを変更しないという条件を付ける。変更すると 差分が違ったりして diff を見るのが面倒になるだけでなく、何度も同じことをするのが億劫なのだ。自動化するツールがないとやってられない。

さて、どのようにやるか ...

ソースコードの依存関係は、ビルドした後 .xxx.cmd ファイルに含まれている。(注意:ビルドするときに作られるので、モジュールも含め 一度完全にビルドしないといけない)

.xxx.cmd ファイルを cat で全部くっつけて、sort したものをまず作る。


cat `find . -name .*.cmd -print` | sort | uniq > file

こんな感じ。

できたファイルを エディタで 編集する。 $(wildcard ...) から始まるものと ホストのファイル を削除すると ... ソースコードがある ディレクトリのヘッダファイルが先頭になる。そして相対パスの ソースコードが続き $(deps...) で始まる行になるので、$(deps ...) 以降を削除する。

これを元にして

  • 一部 .. が含まれているので手動で変更。
  • 絶対パスを linux からの相対パスに変更(スクリプト等で変換)。
  • 最後の スペース + \ を削除(スクリプト等で変換)。
  • モジュールは .mod.c とかになっているので .mod を 削除

という作業をする。

できたものに対して sort + uniq すると 2000 行ほどのファイルになる。

これが第一のファイル群。


tar -zcvf ../file1.tar.gz `cat file`

などとして、tar で固める。

次に Kconfig* Makefile* Kbuild* を tar で固める。

tar -zcvf ../file2.tar.gz `find . -name Kconfig\* -print` `find . -name Makefile\* -print` `find . -name Kbuild\* -print`


これが第二のファイル群。これも 2000 個ほどになる。


あと scripts と arch/mips/boot と drivers/video/logo を tar で固める。

tar -zcvf ../file3.tar.gz scripts arch/mips/boot drivers/video/logo

これが第三のファイル群。

TOP ディレクトリを作成し、第一〜第三のファイル群を展開。

コンパイルしてみる。

まずは、make distclean がエラーにならないか確認。.. たぶん

    include/asm が シンボリックリンクになっていないのでエラーになる。asm を消す。

これで通るはず。

次に make zImage してみると ...

  • make は進むが、arch/x86/include/asm/unistd_32.h がないと言われるので、コピーしておく。
  • 次に kernle/timeconst.pl がないと言われるのでコピー
    これでだいぶ進むが ..
  • drivers/char/cp437.uni がないといわれるのでコピー。fs/nls に nsl_cp932.c nsl_cp936.c nsl_cp437.c のどれかはないはずなので ついでにコピーしておく。
  • drivers/char/defkeymap.c がないと言われる。defkeymap.c_shipped と defkeymap.map をコピー
    これで .. zImage まで作成できたはず。


さて、これはこれで良いのだが ... config を変更するとファイルが足りなくてエラーになる。

第一のファイル群を作成するときに、複数の config で 作ると良い。

作成中の JZ4725B 用の config と lyra から YAFFS2 を抜いた config で 作った シュリンク版とオリジナルの規模比較

tar+bz2 のサイズ 展開後サイズ ファイル数
オリジナル    61.5MB 420MB 29652
シュリンク版 7.4MB 63MB 5770


展開後サイズで 15 % 程 (ファイル数で 20% ほど) に縮小できた計算。

    ファイル数が相対的に多いのは、余計な Kconfig/Kbuild/Makefile が含まれているため (平均ファイルサイズが小さくなる) 。

    必要なものだけ 選び出すスクリプトを作れば、多少減らせるのかも知れない。さらに自動で編集してくれて、本当に必要なものだけに出来るのであれば、それを使っても良いとは思っている。--- だがそういうのを作るは面倒だしいまのところはパス。


ファイルのリストを linux-2.6.31.3-ingenic-r108-shrinked.files.gz に置いておく。参考まで。

追記:

arch にある Kconfig とか があるのでターゲットでない arch も残しているわけだが ... 試してみたら

    ia64 mips s390 um x86

を残せば良さそう。

試し方は、1つのディレクトリを mv で rename して make distclean が通るかどうかを見る。エラーになれば消せない。

最終的には、実際にカーネルをビルドしてみる。だめなら tar ファイルからファイルを戻す。

まぁそこまで消せたとしても 減るファイル数は知れている。
drivers にディレクトリが沢山あるのでこちらのほうが効いてくる。-- だが subdir の Makefile が drivers/Makefile からインクルードされているので、ファイルの編集をしないと消せない。( arch は基本 TOPみたいなものだから 例外を除いて消すことができる。)
posted by すz at 00:14| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2010年09月09日

configのチェック

Jz4725B 用のカーネルを作るには、正しい config ファイルが必要。他の Jz47xx のボードの config は参考にするものの、自分用の config を 作っていかないといけないと考えている。

とりあえずは、f4750l_defconfig をベースにしているが、デバイス周りは全然だめだと思うし、参考にする ボード を 1 つ決めておこうと思う。

Jz4730 のものは古そうなので除外。Jz4750D は laptop みたいなものがターゲットのように見えるので除外。Jz4750 は良さそうだが、機能が多いので むしろ Jz4740 のほうが良さそう。

というわけで、Jz4740 に どういうものがあるかまずチェック。

  • leo SUSPEND, UBI が disable
  • lyra SUSPEND, UBI が定義されている。
  • pavo SUSPEND, UBI が disable
  • virgo SUSPEND が disable


どういうボードなのか理解したわけではないが、lyra を基準にしてみようと思う。

まずは、 f4750l のチェック。あとで lyra との違いをチェックしようと思う。

一般的な設定:CPU関係

    CONFIG_JZ_FPGA=y -- JZ4725B は FPGA ではないから 外したいが、なにをするのに使っているかチェックした後にする。

      使っていない。外してよい。

    CONFIG_CPU_HAS_PREFETCH=y -- prefetch を持っているが果たして性能が上がるのか? SDRAM は、BANK を使いこなすと アクセスをオーバラップさせてスループットを向上できるが、Jz47xx では BANK が上位ビットで 使う物理ページがランダムにならないと オーバラップできない。その条件は 使っているうちにランダムに近くなるのでクリアできそうだが。そもそも Jz47xx のメモリコントローラに オーバラップできる機能があるのか疑わしい。
    それでも どうせアクセスするようなデータなら prefetch しておくのは有効かも知れない。Linux が動いた後の話になるが、外してどう性能が変わるか見てみたい。

    CONFIG_HZ_100=y -- HZ=100 なのか。これも覚えておこう。

    CONFIG_ARCH_HIBERNATION_POSSIBLE=y
    CONFIG_ARCH_SUSPEND_POSSIBLE=y
    CONFIG_PM=y
    CONFIG_PM_SLEEP=y
    CONFIG_SUSPEND=y
    CONFIG_SUSPEND_FREEZER=y
    # CONFIG_HIBERNATION is not set

    このあたり、サスペンドがちゃんと動くかどうかをチェックする時のキーワード。

    ところで、SIMD 命令の XMUが使う 専用のレジスタについて、カーネルは感知しないことになっているようだ。CONFIG がなにもない。-- 1 プロセスが使うことのみが前提で、それを守る仕組みもないから自己責任で使うことになる。

    Linux カーネルで でコンテキスト切り替えしてくれたら、描画ライブラリでも使えるし、カーネルでのメモリコピーにも使えるのに とか思う。
    ただ、フローティングポインタレジスタの制御ように、最適化しないと使わないプロセスの プロセススイッチが遅くなってしまう。
    でも、そういうコードを作るには、情報が足りていない。

    JZ4725(無印)の config があった。(dipper)

    CONFIG_JZ4725_DIPPER=y
    CONFIG_SOC_JZ4740=y
    CONFIG_SOC_JZ4725=y

    なんて定義している。

    CONFIG_JZ4725B_NS3K=y
    CONFIG_SOC_JZ4750L=y
    CONFIG_SOC_JZ4725B=y

    なんてするのが良いのだろうか?



一般的な設定: Linux


    FAT_DEFAULT_CODEPAGE=437

    CONFIG_NLS_CODEPAGE_437=y
    CONFIG_NLS_CODEPAGE_936=y
    # CONFIG_NLS_CODEPAGE_932 is not set

    このあたり修正しておくべき。

    CONFIG_NET

    NET は入れる。いれないのは論外だと思うが、例えば lyra は入っていなかったりする。

    CONFIG_NFS_FS=y
    CONFIG_NFS_V3=y
    CONFIG_NFS_V3_ACL=y
    CONFIG_NFS_V4=y
    # CONFIG_NFS_V4_1 is not set
    CONFIG_ROOT_NFS=y
    CONFIG_NFSD=y
    CONFIG_LOCKD=y
    CONFIG_LOCKD_V4=y
    CONFIG_NFS_ACL_SUPPORT=y
    CONFIG_NFS_COMMON=y
    CONFIG_SUNRPOC=y
    CONFIG_SUNRPC_GSS=y
    CONFIG_RPCSEC_GSS_KRB5=y

    NFS は使いたいが、V3 までで良い。V3_ACL もいらない。
    NFS を root にできるようにしておく。
    NFSD/LOCKD は module で良い。

    # CONFIG_CIFS is not set

    CIFS は、モジュールで いれておく。PC 側で共有設定すると、PC のファイルにアクセスできる。こちらの設定は、実際に使っている PC 用のものを参考にする。


次に、lyna で定義されているが、f4750l で定義されていないもの。調べかたには、diff に対して lyra 分を grep し、 "=y" を grep する観点と f4750l 分を grep し、"not set" を grep する観点の 2 つがある。

まずは、lyna で "=y" となっているもの

    CONFIG_JZ4740_LYRA=y
    CONFIG_SOC_JZ4740=y
    CONFIG_KALLSYMS_ALL=y
    CONFIG_FREEZER=y
    CONFIG_PM=y
    CONFIG_PM_SLEEP=y
    CONFIG_SUSPEND=y
    CONFIG_SUSPEND_FREEZER=y

    ここまで 一般的なもの。SUSPEND 関連はコピーする。KILLSYMS_ALL は 勝手に y になった。

      CONFIG_CPU_FREQ_JZ=y
      CONFIG_CPU_FREQ=y
      が無くなっていることに気がついた。

      arch/mips/Kconfig (の Power Management の上) に

      215 +menu "CPU Frequency scaling"
      216 +
      217 +config CPU_FREQ_JZ
      218 + tristate "CPUfreq driver for JZ CPUs"
      219 + depends on JZSOC
      220 + default n
      221 + help
      222 + This enables the CPUfreq driver for JZ CPUs.
      223 +
      224 + If in doubt, say N.
      225 +
      226 +if (CPU_FREQ_JZ)
      227 +source "drivers/cpufreq/Kconfig"
      228 +endif
      229 +
      230 +endmenu

      が入っていなければならない。
      これをいれた上で、
      CONFIG_CPU_FREQ_JZ=y
      CONFIG_CPU_FREQ=y
      CONFIG_CPU_FREQ_TABLE=y
      CONFIG_CPU_FREQ_STAT=y
      CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
      CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
      CONFIG_CPU_FREQ_GOV_USERSPACE=y
      とする。

    CONFIG_MTD=y
    CONFIG_MTD_CONCAT=y
    CONFIG_MTD_PARTITIONS=y
    CONFIG_MTD_CHAR=y
    CONFIG_MTD_BLKDEVS=y
    CONFIG_MTD_BLOCK=y
    CONFIG_MTD_MAP_BANK_WIDTH_1=y
    CONFIG_MTD_MAP_BANK_WIDTH_2=y
    CONFIG_MTD_MAP_BANK_WIDTH_4=y
    CONFIG_MTD_CFI_I1=y
    CONFIG_MTD_CFI_I2=y
    CONFIG_MTD_BLOCK2MTD=y
    CONFIG_MTD_NAND=y
    CONFIG_MTD_NAND_JZ4740=y
    CONFIG_MTD_NAND_MULTI_PLANE=y
    CONFIG_MTD_HW_RS_ECC=y
    CONFIG_MTD_NAND_IDS=y

    ここまで MTD 関連。Jz4750 用も見た上でいれる。

    CONFIG_INPUT_MOUSEDEV=y
    CONFIG_INPUT_MOUSEDEV_PSAUX=y
    CONFIG_INPUT_EVDEV=y

    PSAUX は入れないが 他は入れておこう。

    CONFIG_RTC_JZ=y
    CONFIG_JZCHAR=y
    CONFIG_JZ_TPANEL_ATA2508=y
    CONFIG_WATCHDOG=y
    CONFIG_JZ_WDT=y
    CONFIG_FB_JZLCD_4730_4740=y
    CONFIG_JZLCD_AUO_A030FL01_V1=y
    CONFIG_I2S_ICODEC=y

    このあたりは JZ4750 も見ていれてみる。

    CONFIG_USB_GADGET_DEBUG_FILES=y
    CONFIG_USB_GADGET_JZ4740=y
    CONFIG_JZ_UDC_HOTPLUG=y
    CONFIG_UDC_USE_LB_CACHE=y

    USB GADGET は入れる。

    CONFIG_EXT3_FS=y
    CONFIG_EXT3_FS_XATTR=y
    CONFIG_JBD=y
    CONFIG_UBIFS_FS_LZO=y
    CONFIG_UBIFS_FS_ZLIB=y
    CONFIG_UBIFS_FS_DEBUG=y
    CONFIG_YAFFS_FS=y
    CONFIG_YAFFS_YAFFS1=y
    CONFIG_YAFFS_YAFFS2=y
    CONFIG_YAFFS_ECC_RS=y
    CONFIG_YAFFS_AUTO_YAFFS2=y
    CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK=y
    CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
    CONFIG_DEBUG_FS=y

    EXT3 は入れる。UBIFS は モジュールにする。YAFFS2 は入れない -- できるだけ多くのエリア を UBI にする予定で、UBI の上に YAFFS2 は載らない。載るのは一般のFS か UBIFS 。

    CONFIG_REED_SOLOMON=y
    CONFIG_REED_SOLOMON_ENC8=y
    CONFIG_REED_SOLOMON_DEC8=y

    これはなんだろう?


f4750l で not set として出てくるもの。上記を除く。

    # Thu Sep 9 12:49:31 2010
    # CONFIG_JZ4740_LYRA is not set
    # CONFIG_POSIX_MQUEUE is not set
    # CONFIG_TASKSTATS is not set
    # CONFIG_AUDIT is not set

    #
    # Networking options
    #
    (net 関係は 量が多いのでザックリ省略)
    lyra は NET なしらしい。NET なしではちょっと困る。

    # CONFIG_FB_JZ4750_LCD_USE_2LAYER_FRAMEBUFFER is not set
    # CONFIG_FB_JZ4750_TVE is not set
    # CONFIG_FB_JZ4750_SLCD is not set
    # CONFIG_JZ4750_LCD_SAMSUNG_LTP400WQF01 is not set
    # CONFIG_JZ4750_LCD_SAMSUNG_LTP400WQF02 is not set
    # CONFIG_JZ4750_LCD_FOXCONN_PT035TN01 is not set
    # CONFIG_JZ4750_LCD_INNOLUX_PT035TN01_SERIAL is not set
    # CONFIG_JZ4750_LCD_TOPPOLY_TD025THEA7_RGB_DELTA is not set
    # CONFIG_JZ4750_LCD_TOPPOLY_TD043MGEB1 is not set
    # CONFIG_JZ4750_LCD_TRULY_TFTG320240DTSW_18BIT is not set
    # CONFIG_JZ4750_LCD_TRULY_TFT_GG1P0319LTSW_W is not set
    # CONFIG_JZ4750_SLCD_KGM701A3_TFT_SPFD5420A is not set
    # CONFIG_JZ4750D_VGA_DISPLAY is not set

    LCD は、JZ4750 用は別のものとしてあるらしい。後回し。

    # CONFIG_USB_G_SERIAL is not set

    あたらしい USB GADGET 。モジュールで 入れる。
    -- ただ USB GADGET は 1種類しか使えないはず。そうなると G_ETH しか選ばないのだが ...


      USB GADGET には、USB_CDC_COMPOSITE というものがある。

      説明には、CDC Ethernet(ECM) + CDC ACM(serial) の機能だそうだ。昔からあるものは、E_ETH だが、これも CDC Ethernet 。

      CONFIG_USB_CDC_COMPOSITE=m にしといたほうが良さそう。

        ... どうも 複合デバイスを作るためのフレームワークがあるようだ。f_xx.c u_xx.c g_xx.c という風に機能やら何やらを分離しているように見えるし、config.c というのも独立している。



    # CONFIG_CRYPTO_DEFLATE is not set
    # CONFIG_CRYPTO_LZO is not set
    # CONFIG_CRC16 is not set


作ってみた。myconfig-100908.gz

これについてのメモ:

  • CONFIG_JZ_FPGA=y を外し忘れてた。
  • CONFIG_J4750L_NS3K とかボードの定義はしたものの使ってない。-- 出来たら同じバイナリにしたいし削るかも。
  • CONFIG_JZ_UDC_HOTPLUG=y は関数が足りないのでリンクできず外した。
  • CONFIG_KEYBOARD_JZ=y は コンパイルエラーになる。
  • CONFIG_MTD_NAND_MULTI_PLANE=y をしてるのは少数だったので外した。
  • CONFIG_MTD_HW_RS_ECC=y とか ECC 関係はよくわからない。とりあえず JZ4750 の方を参考にして定義した。

    -- HM は Hamming の略、RS は Reed-Solomon の略ということが分かった。そして JZ4750 や JZ4725B は 4/8/12 bit BCH ECC をサポートしており
    CONFIG_MTD_HW_BCC_ECC=y
    CONFIG_MTD_HW_BCC_8BIT=y
    とするのが正しいらしい。
posted by すz at 22:24| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2010年09月05日

jz_ubcomm

条件がそろったので、そろそろ Linux の方に手を出していこうと思う。

まずは、ingenic から提供されている Linux をビルドしてみる。

だいぶ前に qi-hardware 経由で 取ったスナップショットだが、

をベースにすることにする。

kernel.org の linux-2.6.31.3 を展開した上に files-2.6.31.3-ingenic-r108.tar.gz を展開して、linux-2.6.31.3-ingenic-r108.patch.gz をパッチすればよかったはず。

次に config 。JZ4725B は、JZ4750L だと思うので、これを y にしている arch/mips/configs/f4750l_deconfig をベースにすることにして .config にコピー。

で、make menuconfig とかして make zImage とかすると なにか出来る。

ただし、f4750l は、評価ボードですらない よく分からない ものみたいなので、ビルドできただけでは 動かない。少しづつ修正していこうと思う。

修正 1) drivers/char/jzchar/Kconfig

JZ4750L だけ仲間はずれなので、追加しておく。

ここまでが準備。本題は コンソールドライバの作成。

USBBOOT に組み込んだプロトコルを使って コンソールの代わりをさせるためのドライバを作成しなくてはならない。

    一から作るのは面倒だからベースとなりそうなドライバを探してみたところ bfin_jtag_comm なんてドライバがあることが分かった。

    まずは、bfin_jtag_comm.c を jz_ubcomm.c にリネームして、drivers/char/jzchar に置く。

    次に namespace だけ 変更。 変更するということは 命名しなくてはならない。"JZ USBBOOT COMMUNICATION CONSOLE DRIVER" ということで ファイル名を jz_ubcomm.c , prefix を ubcomm/UBCOMM にしようと思う。

    で、drivers/char/jzchar の Kconfig と Makefile を bfin_jtag_comm とかを参考にしながら追加。

    一応ビルドできることを確認。


ここまでが第二の準備。形式だけ整ったドライバが出来た。

いよいよ 中身をみて変更していく。

Linux とのインターフェイス

Linux とのインターフェイスには、3 段階ある。ひとつは通常の TTY 。もうひとつは、console としての登録。最後に 初期化完了前の インターフェイス。

ここが最も行数が多い。そして、元のドライバには全部揃っている。

通常の TTY として登録するには、struct tty_driver に必要なものをセットして、tty_register_driver() で登録する。

tty_driver には、関数テーブルもあって、open,close,write,flush_chars,write_room,chars_in_buffer,wait_until_sent といった関数を用意して 登録する。

コンソールとして登録する場合は、struct console に必要なものを セットして register_console() で登録する。必要なものの中には、TTY ドライバも含まれる。

初期化中のメッセージを 表示するには、struct console に 初期化中に使う関数をセットしなければならない。登録の方法は不明。
(作っておくだけでよいような気がするが詳しくは知らない)

基本は、TTY ドライバ。これがちゃんとできれば良さそうな感じ。

bfin_jtag_comm でどのような処理をしているか見てみる。

まず、jtag 経由の通信は、一度に大量のデータを扱うものではないようだ。よく分からないのだが、4 バイトづつデータをおくっている。

4バイトづつでは、大量のメッセージを直接扱えない。一旦バッファリングして、カーネルスレッドで徐々に送り出すようになっている。( 割り込みは使っていない )

USBBOOT では、バッファのサイズを 4KB にしているが もっと大きくもできる。大きなバッファを、USB で一度に 吸いだすようなことは問題ないが、stage2 の関数を定期的に call してやらないと USB の処理自体が止まる。また、ホスト側のプログラムが read してくれないと表示はできない。問題なのは PANIC 。カーネルが止まった後でも ポーリングがされないと USB が動かない。

このあたりの性質の違いを考慮すると

  • console(TTY) への write は、直接 通信エリアのバッファーに追加していくようにして、ローカルなバッファは持たないようにする。
  • カーネルスレッドは利用するが、メインは stage2 関数の ポーリングにする。

こんな感じで処理を作るのが良さそう。たぶんオリジナルよりさらに簡単な処理になるはず。
ただし PANIC 後どうするのか? これは調べないとわからない。

PANIC 処理について:

panic の本体は kern/panic.c

panic したしたあと、panic_notifier_list に登録されている関数を順次 call するようになっている。-- これは 1 回限りなので使いにくい。

あと、panic_blink という 関数ポインタがあり、reboot するまでの間 1msec 間隔で call するようだ。

この関数、誰も使っていないように見える。これを使おう。

とりあえずは、make zImage で、なにか出来た。一応 途中まで動く可能性があり、メッセージが見える可能性があるはじめてのものだ。

だが、成功すればメッセージが出るが、ダメだとなにも起きない。-- これでは デバッグのしようがないのだ。

メッセージが出るまで、デバッグのために使えるのは、LCD のバックライトのみ。

バックライトを使ってどこまで動いたか調べないと。

まずは、起動シーケンスのおさらい

1) zImage の自己解答後の最初のエントリ -- kernel_entry (arch/mips/kernel/head.S)
2) start_kernel (init/main.c)
 3) setup_arch (arch/mips/kernel/setup.c)

setup_arch に来るまで、結構 start_kernel で関数を call している。

さて、backlight を点灯させる関数を作成して、start_kernel の先頭で call するようにしてみた。

... NG 。まだ、マシン依存のコードは動作していないにも係わらず 点灯してくれない。そうなると .. zImage の作り方自体に問題があるのかも知れない。

    まず、zImage は 0x80600000 にロードする。それは正しい。で、zImage が動作すると、decompress_kernel を call して、カーネルを展開する。

    展開アドレスは、vmlinux の 先頭アドレスと同じ 0x80010000 。展開が終わったら vmlinux の開始アドレスである kernel_entry に制御を渡す。

    これだと 0x80010000(offset 64K) - 0x80600000(offset 6M) の間に、カーネルと initrd が入らなければならないという条件になる。そして (展開後の)カーネルのサイズは、4MB +α。なかなか厳しい。

    心配なのは、スタックはどこに取られるのか? stage2 を壊してしまわないかということ。zImage の 展開部分は、スタック用のエリアを配列で持っているから大丈夫。vmlinux 自体も似たようなもので、init_thread_union (arch/mips/kernle/init_task.c) 上に取られる。

    もうひとつ心配なのが、上記の アドレスやサイズが正しく設定されているかどうか。

    zImage のスタートアップでは、

    la a0, __image_begin
    la a1, IMAGESIZE
    la a2, LOADADDR

    という風に ビルド時に定数が埋め込まれる。この値が実際どうなのか というと次のようになっていて正しい。

    -DIMAGESIZE=1792767
    -DKERNEL_ENTRY=0x800144f0
    -DLOADADDR=0x80010000


initrd のサイズを気にする必要はあるが、正しそうだ。

もうひとつ可能性がある。点灯は一旦するが、初期化で消されてしまうケース。(どういうケースはよく分からないが)

とりあえず 点灯後無限ループしてみたところ ... start_kernel の先頭にいれた jz_backlight() で点灯した。

-- とりあえずは、Linux に制御が渡ったので 一安心。

次に setup_arch を call する所まで行くかどうかを試したが.. ダメ。

どこまで動くか jz_backlight() を入れる場所を変更しながら 動かしてみると ..

:
boot_init_stack_canary();

cgroup_init_early();

local_irq_disable();
early_boot_irqs_off();
early_init_irq_lock_class();
-- OK
lock_kernel();
tick_init();
-- OK
boot_cpu_init();
-- NG
page_address_init();
-- NG
printk(....);
setup_arch();



static void __init boot_cpu_init(void)
{
int cpu = smp_processor_id();
/* Mark the boot cpu "present", "online" etc for SMP and UP case */
set_cpu_online(cpu, true);
set_cpu_present(cpu, true);
set_cpu_possible(cpu, true);

boot_cpu_init() は、このようになっている。smp_processor_id()は、0 に展開されている。set_cpu_online() などの関数は、ただの bit 操作。最終的には set_bit() になる。

この程度のものがなぜ動かないのか?

ちょっとここで スナップショットを取っておく。動かないけれども 。


(つづき)
page_address_init() も単に データの初期化で、普通なら 動作するのが期待できるコード。で、次に最初の printk を call している。そうすると既に console の最初の初期化が call されていることになる。

posted by すz at 23:25| Comment(0) | TrackBack(0) | Jz47xx(Linux)

2010年04月15日

開発環境を構築

Neo slim 3000 の開発環境を 遊んでいる eeePC 701SDXに構築することにした。

OS は、Vine-5.1にした。DVD イメージファイルを USBメモリに RAW で書き込むと DVD boot と同じようにインストーラが起動する。

    いままで diskboot.img を使ってきたのだが、同じようにやろうとしてはまった。どうも diskboot.img は、使えないようだ。


mips 用の toolchain は、

にある dingux_toolchain_20091022.tar.bz2 を /usr に展開して使うことにした。

    export PATH=$PATH:/usr/mipsel-linux-uclibc/bin:/usr/mipsel-linux-uclibc/usr/bin
    export CROSS_COMPILE=mipsel-linux-

こんな環境変数の設定で使う。

つぎに、dingoo-linux のカーネルを試しにビルドしてみることにした。

svn で全部のソースを取って来ることになっているのだが、どうしても途中でエラーになる。関係ありそうなディレクトリを個別に取って来ることにした。

    もういちど取り直して作ってみた。(新しいのは bzip2 で圧縮)

とりあえず次の3つにまとめた。



1) linux-2.6.24.3 を展開して TOP デレクトリに cd
2) files-2.6.24.3-dingoo-r171.tar.gz を展開
3) mtd-utils-dingoo-r171.tar.gz を展開
4) linux-2.6.24.3-dingoo-r171.patch.gz を -p1 で当てる。
5) make a320_defconfig
6) make menuconfig
7) make zImage

これで、ビルドだけはできた。ただし、それらしいというだけで動くものかどうかは分からない。

さて、カーネルに付属のドキュメント README-JZに目を通してみたのだが、


+-----------+ +-------------+ +-------------+
| YAFFS2 | | UBIFS | | FAT or EXT2 | Filesystems
+-----------+ +-------------+ +-------------+
\ | / \
\ | / \
\ | / \
\ | +-----------------+ +-----------------+
\ | | UBI Block Layer | | MTD Block Layer |
\ | +-----------------+ +-----------------+
\ | / /
\ | / /
\ +-------------+ /
\ | UBI | /
\ +-------------+ /
\ | /
+-------------------------------------------+
| MTD |
+-------------------------------------------+
|
+--------------------+
| nand_base.c |
+--------------------+
|
+--------------------+
| jz4740_nand.c |
+--------------------+

なんていう図が載っている。ブロックデバイスの上に UBI というレイヤがあって、どうも ウェアレベリングのようなことをしているようだ。そしてその上に UBIFS という専用のファイルシステムがある。

それとは別に YAFFS2 も載せているようだ。

ようだと書いているのは、dingoo-linux には、それらが含まれていないため。Ingenic が出しているパッチは 20090506 が最新のようだが、ダウンロードできないので確認できていない。

まぁ dingoo-linux がサポートしていない以上 DINGUX を動かすだけなら必要ではないのだが... Neo Slim 3000 のファームウェアがどうも UBIFS を使っているっぽいのだ。中を覗いたりするのに欲しいような気がしている。

ところで、ビルドしてみたカーネルは、Neo Slim 3000 では動作するはずもない。ビルドしたのは、A-320 でどういうカーネルになっているかを確認するのが目的。

ベースにしようと思っているのは、

こちらの方。Jz4725 を使っている SAKC用のカーネル をベースにしようと思う。

情報は、SAKC : Development_Tools にあるようだ。

    linux は出来ていると勝手に思っていたのだが、Qi-U-BOOT までみたいだ。だが、手順として、
    1) Create config Files
    2) Modify existing Drivers
    と書いてあるだけだし、新チップに対応するような大変さは感じられない。 大丈夫なんだろう。

ちなみに上の projects の リンクから、Ingenic が出している最新のカーネルソースも取れるようだ。

SAKC のカーネルと書いたが、Ben-NonoNoteBuilding_Software_Imageをみると openwrt-xburst を git で取って来ることになっているらしい。

とりあえずとって来てみたら linux-2.6.32 用のパッチがあったので、同じように整理してみた。


ビルドしてみた。

基本は dingoo-linux と同じだったのだが、defconfig がないので、全部自分で設定しないといけない。

Ingenic のオリジナルを http://projects.qi-hardware.com/ を見て git で落とせたので 同じように整理。dingoo-linux の方がオリジナルに近い感じ。オリジナルは、YAFFS2 と UBIFS が入っているので files-xx が大きい。2.6.31.3 ベースの files-xx は、UBIFSが linux 自体に入っているので 小さくなっている。ちなみに rxx は git に登録されているリビジョン。

xburst-tools を ビルトしてみる。



上の projects のリンクに Xburst Tools がある。これに usbboot が含まれている。



autogen.sh を実行 して configure するようになっている。最初 CentOS 5.4 とかを使ってみたが CentOS が使っている autoconf が古くてエラーになった。

あと、libconfuse-devel (と check-devel) が必要で、Vine だと VinePlus に含まれている。あと libusb-devel も必要で DVD には含まれていない。

一応ここまでで、開発環境は構築できたとしよう。

追記:メモ


IPU -- イメージプロセッシングユニットの説明は、Programming Manual にあった。

概要は、YUV や YCbCr フォーマットのデータを resize 付きで フレームバッファに転送する機能。(それだけで他の機能はない)

フレームバッファは、R8G8B8 か R5G6B5 / R5G5B5 である必要がある。

あと Xburst は SIMD 命令 (x86 の MMX とか SSE のようなもの?) を持っているが、詳細は分からない。

どうも

  • アセンブラ のソースは公開されているから、それを見れば 一覧と形式は分かる。
  • Mplayer とか jpeg6b に移植されているので 使い方はそれを参考にできる。

ということらしい。

追記:

u-boot も置いておく。u-boot-1.1.6 からの差分。
posted by すz at 00:44| Comment(1) | TrackBack(0) | Jz47xx(Linux)