目次: Raspberry Pi
Raspberry Pi 3のAudio Outの最後の謎がわかりました。
その6(2021年5月12日の日記参照)にてRaspberry Pi 3の回路図が間違っているのでは?と疑っていましたが、違いました。ケーブルに入っている抵抗のせいでした。
今まで測定に使用していたオーディオケーブルにはプラグ内に抵抗が入っています。そもそもなんでこんなの買ったんだろ……?プラグの見た目からはわかりませんので、テスターで各端子間の抵抗を計測した結果は下記のとおりです。
| ミニL | ミニR | ミニG | RCA L | RCA G | RCA R | RCA G | |
|---|---|---|---|---|---|---|---|
| ミニL | --- | 294 | 147 | 46.7k | 147 | 46.7k | 147 | 
| ミニR | --- | 147 | 47.0k | 147 | 46.4k | 147 | |
| ミニG | --- | 47.0k | 0 | 47.0k | 0 | ||
| RCA L | --- | 47.0k | 94.0k | 47.0k | |||
| RCA G | --- | 47.0k | 0 | ||||
| RCA R | --- | 47.0k | |||||
| RCA G | --- | 
測定結果から想定される回路図です。左がミニジャック側、右がRCAプラグ側です。
この結果を踏まえてシミュレーションすると実測値とほぼ一致しました。

Audio Out回路のシミュレーション結果(125Hz矩形波を入力に設定)ケーブルの抵抗を考慮

Audio Out回路の実測値(黄色Audio Out、水色PWM信号125Hz矩形波)
気づいてみれば何とも初歩的なミスでしたが、ケーブルは0Ωと思い込んで見落としました。他人(RasPiの回路図)を疑う前に自分を疑えという良い教訓ですね〜。
 この記事にコメントする
 この記事にコメントする
目次: RISC-V
買い物メモです。先日(2021年5月28日の日記参照)SiFive HiFive Unmatchedを購入しました。このボードはmicroSDからブートしますが、追加のストレージとしてNVMe SSDが装着できます。
Western DigitalのWDS100T2B0C-ECを購入しました。Amazonで13,000円くらいでした。容量1TB、規格M.2 2280、接続NVMeです。コストパフォーマンス重視のWD Blueシリーズです。
WD BlueシリーズはWD Blackシリーズと比較すると速度で見劣りするものの、そもそもHiFive UnmatchedのCPUはそれほど速くないですしWD Blueで十分でしょう。きっと。
 この記事にコメントする
 この記事にコメントする
目次: OpenCL
引き続き、独自アクセラレータのテンプレート実装pocl/lib/CL/devices/accelの細かな問題を調べます。次の問題はOpenCLの初期化です。clGetPlatformIDs() から初期化関数pocl_accel_init() に辿り着いたところでabort() が呼ばれクラッシュします。
| GENERAL | accel: accelerator at 0x1000 with 0 builtin kernels Could not open /dev/mem
テンプレート実装の意図としては /dev/memをopen() してメモリマップされたハードウェアのレジスタを読み書きしたいようです。今回は実際のハードウェア相手ではないので、レジスタの読み書きではなく /dev/memの代わりにバイナリファイルを開いてもらうように書き換えます。
// pocl/lib/CL/devices/accel/accel.cc
cl_int pocl_accel_init(unsigned j, cl_device_id dev, const char *parameters) {
...
  POCL_MSG_PRINT_INFO("accel: accelerator at 0x%zx with %zu builtin kernels\n",
                      D->BaseAddress, D->SupportedKernels.size());
  int mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
  if (mem_fd == -1) {
    POCL_ABORT("Could not open /dev/mem\n");  //★★このabortでクラッシュ
  }
...
ファイル名を書き換えて突破するとデバイスが持っているメモリのサイズを取得し、メモリマップしようとする部分で怒られます。
| GENERAL | accel: accelerator at 0x1000 with 0 builtin kernels a.out: ../lib/CL/devices/accel/accel.cc:196: void MMAPRegion::Map(size_t, size_t, int): Assertion `Data != MAP_FAILED && "MMAPRegion mapping failed"' failed.
サイズを取得している箇所は下記のとおりです。
// pocl/lib/CL/devices/accel/accel.cc
cl_int pocl_accel_init(unsigned j, cl_device_id dev, const char *parameters) {
...
  uint32_t ctrl_size = D->ControlMemory.Read32(ACCEL_INFO_CTRL_SIZE);
  uint32_t imem_size = D->ControlMemory.Read32(ACCEL_INFO_IMEM_SIZE);
  uint32_t dmem_size = D->ControlMemory.Read32(ACCEL_INFO_DMEM_SIZE);
  uint32_t pmem_size = D->ControlMemory.Read32(ACCEL_INFO_PMEM_SIZE);
  uint32_t max_region =
      std::max(std::max(ctrl_size, imem_size), std::max(dmem_size, pmem_size));
  D->InstructionMemory.Map(D->BaseAddress + max_region, imem_size, mem_fd);
... 
バイナリファイルを書き換えて何か適当な値が読めるようにしてやりすごすか、面倒ならばD->ControlMemory.Write32(ACCEL_INFO_CTRL_SIZE, 0x2000); のように固定値を書いておくと次に進みます。今は実際のデバイスが相手ではないので、とりあえず先に進めて後で考えましょう。
 この記事にコメントする
 この記事にコメントする
目次: Linux
TwitterでGUIの話をしている人を見かけて思い出した話です。私はGNU/Debian LinuxのGUIをLightDM + GTKにして使っています。
GUIにこだわりはなく一時期デフォルトだったLightDMを使い続けているだけです。デフォルトになっただけあって、良くできていると思うし特に不満はないです……が、1点だけ言わせてもらえば、ウインドウサイズ変更の判定が厳しすぎませんか?
特に左辺、上辺、右辺が1pxしか反応してくれないので、マウス操作が非常にシビアです。手が震えてきます。
Twitterで上記の話をしていたところ、Alt + 右マウスボタンでウインドウサイズを変えられるよ、と教えてもらいました。今度からそうします。1pxに合わせるのは手が疲れる……。
 この記事にコメントする
 この記事にコメントする
目次: Zephyr
JTAGが繋がった(2021年6月5日の日記参照)記念にZephyrをHiFive Unleashedで動かしてみました。使うハードウェアはUARTだけ、コードもJTAGでITMにロードして動作させるだけなら楽勝だろと思いきや、全然UARTから文字が出力されず1日掛かってしまいました。
*** Booting Zephyr OS build zephyr-v2.6.0-39-g2bf63134e8f0 *** thread_a: Hello World from cpu 0 on hifive_unleashed! thread_b: Hello World from cpu 0 on hifive_unleashed! thread_a: Hello World from cpu 0 on hifive_unleashed! thread_b: Hello World from cpu 0 on hifive_unleashed! thread_a: Hello World from cpu 0 on hifive_unleashed! thread_b: Hello World from cpu 0 on hifive_unleashed!
原因はコアのPLL設定が間違っていて、コアクロックから分周して作るUARTのボーレートもおかしな周波数になっていたからです。
FU540のリセット直後は外部クロック源(33.33MHz)をそのまま使って動きます。起動後PLLを1GHz(33.33 / 1 * 120 / 4 = 999.9MHz)に設定し、コアクロックをPLL側に切り替えなければなりません。
PLLの設定はFSBLという2段目のブートローダーが行うので、通常はOSが気にする必要はありません。しかしRTOSは大抵ブートローダーを経由しませんから、ブートローダーに隠れた設定も拾ってきて実装しないと動かないことがあります。
ブートローダーがあって当たり前のリッチ系SoCでRTOSを動かそうとすると、大抵この「暗黙のうちに設定されている何か」が抜け落ちて動かなかったりおかしくなったり、何かと面倒が起きます。
幸いなことにSiFiveのブートローダーはコードが公開されており、完全ブラックボックスのSoCと比べれば、難易度は低い部類です。ありがたいですね。
メモ: 技術系の話はFacebookから転記しておくことにした。加筆。
 この記事にコメントする
 この記事にコメントする
目次: RISC-V
昔買ったHiFive Unleashedというボード、JTAGはちょっと特殊なコネクタが必要だと思っていて接続を諦めていました。ところが今日、ファンを掃除したあと動作確認をした際に、USB Serialと一緒にUSB JTAGも用意されていることに気づきました。
HiFive Unleashedはディスコンでもう手に入りませんし、後継機種のHiFive Unmatchedも買った今となっては、かなり今更感ありますが……。
ちょっと試したところ、簡単にOpenOCDが繋がりSMPモードにすると5コア(rv64imacなE51とrv64gcなU54 x 4)が見えました。
adapter speed 10000
adapter driver ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010
ftdi_layout_init 0x0008 0x001b
ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000913
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME -rtos hwthread
target create $_TARGETNAME.1 riscv -chain-position $_TARGETNAME -coreid 1
target create $_TARGETNAME.2 riscv -chain-position $_TARGETNAME -coreid 2
target create $_TARGETNAME.3 riscv -chain-position $_TARGETNAME -coreid 3
target create $_TARGETNAME.4 riscv -chain-position $_TARGETNAME -coreid 4
target smp $_TARGETNAME.0 $_TARGETNAME.1 $_TARGETNAME.2 $_TARGETNAME.3 $_TARGETNAME.4
init
halt
SiFiveのSoCはFU540も後継のFU740も命令セットの違うコアを混載するのが好きですね。混載は良いとしてせめて同じ命令セットにしてほしかったです。単純なSMPしか持ってないOSだと制御できないじゃん……。
メモ: 技術系の話はFacebookから転記しておくことにした。加筆。
 この記事にコメントする
 この記事にコメントする
目次: OpenCL
引き続き、独自アクセラレータのテンプレート実装pocl/lib/CL/devices/accelの細かな問題を調べます。デバイス数の取得の問題を回避すると、次はデバイスのパラメータを渡す問題に遭遇します。
// pocl/lib/CL/devices/accel/accel.cc
void pocl_accel_init_device_ops(struct pocl_device_ops *ops) {
  ops->device_name = "accel";    //★★デバイス名はaccel
  ops->init = pocl_accel_init;
...
// pocl/lib/CL/devices/devices.c
cl_int
pocl_init_devices ()
{
...
  dev_index = 0;
  /* Init infos for each probed devices */
  for (i = 0; i < POCL_NUM_DEVICE_TYPES; ++i)
    {
      if (pocl_devices_init_ops[i] == NULL)
        continue;
      str_toupper (dev_name, pocl_device_ops[i].device_name);    //★★dev_nameはデバイス名を大文字に変換したACCELになる
      assert(pocl_device_ops[i].init);
      for (j = 0; j < device_count[i]; ++j)
        {
...
          /* Check if there are device-specific parameters set in the
             POCL_DEVICEn_PARAMETERS env. */
          POCL_GOTO_ERROR_ON (
              (snprintf (env_name, 1024, "POCL_%s%d_PARAMETERS", dev_name, j)    //★★環境変数名を生成する箇所
               < 0),
              CL_OUT_OF_HOST_MEMORY, "Unable to generate the env string.");
          errcode = pocl_devices[dev_index].ops->init (
              j, &pocl_devices[dev_index], getenv (env_name));
...
実装ではpocl_accel_init() にて環境変数の値をパースしてデバイスのパラメータを取得します。環境変数名はデバイス番号によって変化しますが、0番目のデバイスであればPOCL_ACCEL0_PARAMETERSという名前になります。環境変数名は上記にあるとおりpocl_init_devices() で決めています。
困ったことに環境変数が見つからないとabort() してしまうので、環境変数には最低でも何か1つ数値を渡す必要があります。なお1つ目の値はレジスタ領域のベースアドレスだと解釈されるようです。
他の実装(pthreadとcuda)は環境変数を使わないので、同様の問題は存在しません。最終的にはaccelも環境変数に頼らない実装に変えていく必要がありますが、今はそのままにしておきます。
 この記事にコメントする
 この記事にコメントする
| < | 2021 | > | ||||
| << | < | 06 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 | 
| - | - | 1 | 2 | 3 | 4 | 5 | 
| 6 | 7 | 8 | 9 | 10 | 11 | 12 | 
| 13 | 14 | 15 | 16 | 17 | 18 | 19 | 
| 20 | 21 | 22 | 23 | 24 | 25 | 26 | 
| 27 | 28 | 29 | 30 | - | - | - | 
 25年10月27日
 25年10月27日
 23年4月10日
 23年4月10日
 25年10月15日
 25年10月15日
 25年10月18日
 25年10月18日
 22年5月5日
 22年5月5日
 25年10月19日
 25年10月19日
 23年4月11日
 23年4月11日
 06年4月22日
 06年4月22日
 25年10月17日
 25年10月17日
 25年10月6日
 25年10月6日
 25年10月13日
 25年10月13日
 20年10月23日
 20年10月23日
 25年10月12日
 25年10月12日
 20年8月29日
 20年8月29日
 19年1月13日
 19年1月13日
 18年10月13日
 18年10月13日
 18年9月3日
 18年9月3日
 18年8月20日
 18年8月20日
 18年7月23日
 18年7月23日
 18年7月22日
 18年7月22日
 wiki
 wiki Linux JM
 Linux JM Java API
 Java API 2002年
 2002年 2003年
 2003年 2004年
 2004年 2005年
 2005年 2006年
 2006年 2007年
 2007年 2008年
 2008年 2009年
 2009年 2010年
 2010年 2011年
 2011年 2012年
 2012年 2013年
 2013年 2014年
 2014年 2015年
 2015年 2016年
 2016年 2017年
 2017年 2018年
 2018年 2019年
 2019年 2020年
 2020年 2021年
 2021年 2022年
 2022年 2023年
 2023年 2024年
 2024年 2025年
 2025年 過去日記について
 過去日記について アクセス統計
 アクセス統計 サーバ一覧
 サーバ一覧 サイトの情報
 サイトの情報合計: 
本日: