2020年4月30日木曜日

STM32のmbed環境でSPIに使えるピンは?

STM32のペリフェラルピンはやや特殊で、SPIやI2Cみたいな特殊機能は特定の数種類のピンにのみリマップできます。さらにわかりにくいことに、SPIユニットが内部に1~4まであり、それぞれ繋がっているバスが違ったりします…

データシートを熟読しながらcubeMXでリソースを割り当てる覚悟があれば問題ないんですが、手っ取り早くSPIを使いたいときにどのピンを使っていいのかよくわからなくて困ります。

で、調べたところ、mbedのSPIライブラリで対応しているピンならどれでも、いちいち対応するユニット番号を覚えてなくてもSPIとして使うことができます。単に

SPI device(D4, D5, D3);

みたいに書くだけで、MOSIがD4, MISOがD5, ClockがD3として動きます。対応してないピンを指定するとエラーをUSBシリアルポートに吐いて止まります。じゃあどのピンなら対応しているのかというと、nucleoを買うと付いてくるピンアウト表(こんなの↓)を見て、SPI3_MISOとか書いてあるところなら対応しています。
とはいえSPIxのxのところはそのピンに割り当てるときにライブラリ内部で使われるSPIユニット番号を挿しているので、宣言時に与える3本のピンが全て同じユニット番号に属している範囲でしか割り当ては許されません。(SPI1_MISOとSPI2_MOSIを同じライブラリ宣言に突っ込んで使うようなことはできません)

あと、この図を見ていてわからないのはピン番号の記述方法でして、SPI2_MISOといった名前はカラフルな表にそう書かれていますが、mbedライブラリで宣言はされていません。(なんせ選択肢が複数ピンあるので宣言しようもない)
宣言されているのはD2,D3 (nucleoピン番号)とかPA_3, PA_4 (GPIO番号)なので、これらを使ってピンを指定します。


さらにわかりにくいことに、SPI_MISOとかSPI_MOSIというピンは宣言されています。それって何番ピンのことなのよ!と思いますが、それは各CPUのPinNames.hに記述されていいまして、STM32F446REならここを参照するとそれぞれPA_6, PA_7であると書かれています。
まあSPI1ユニットのデフォルト割り当てピンなので妥当ではありますが… 事情をよく知らない状態で参考にしたコードがこの記法のピン指定を使っていると、他のピンにリマップする方法がさっぱりわかりませんよね。


さらに!nucleo基板の落とし穴というのがあって、いくつかのピンは既に割り当てがあるので注意が必要です。マニュアルに書いてはありますが、ありがたいことにF446REについて日本語情報でまとめてくれている方がいます。
たとえばSPI1の割り当てなんて、LEDにかぶるわSWDにかぶるわで…まあ機能はするので気にしなくても最初は困らないんですが…

2020年4月17日金曜日

STM32F446RE めいっぱい速くPWM出力

IOトグルだけで最高速が出ることがわかったので別に必要ないんですが、PWMでめいっぱい速くIOを上げ下げする方法を調べてみました。

どうもSTM32は、どのピンにでも機能を割り当てられるわけではなく、タイマ番号ごとにいくつか割り当てられるピンの種類が決まっていて、その中から選択するみたいです。しかもそのタイマも対照的にずらっと並んでいるのではなくそれぞれ個性があるみたいです。趣味的には楽しそうだけど学習コスト高そう…

まあ、とにかく見やすいところでLEDピンのPA5にPWM出力をしてみることにしました。
nucleoのパッケージにもあるピンアサイン画像によると、PA5にPWMを出す場合はタイマ2か1らしいです。1は特殊らしいのでまあタイマ2を選んでみます。
次にマニュアルを確認すると、タイマ2はAPB1に繋がっています。

APB1のクロックは残念ながら最大45MHzなのですが、cubeMXのクロック設定画面でよく見るとAPB1であってもタイマークロックだけは2倍の90Mhzが使われるようです。しかしAPB2なら2倍の90Mhz/180Mhzが使えるのか…まあ後でわかるように今回の場合別のボトルネックがあるので意味ないんですが。


で、cubeMXでTIM2設定のChannnel1をちまちまと入れていきます。下の画像ではプリスケーラPSC=1, カウンタ周期1, パルス幅カウント値1です。それぞれ0が最小なので、これらの意味するところはプリスケーラが2分周、カウンタ周期が0~1の2クロック、パルス幅はそのうちの1クロック、てことでデューティ比50%で最速のPWM(を2分周してるのでその半分速)ということです。
タイマのPWM出力設定を入力して、具体的にどのピンに出すかは同じ入力欄のGPIO Settingsタブでも選べますが、CPUの絵のピン番号のところで左クリックでこうやって選ぶこともできます。



ここでコード生成をするとcubeMXが上記の設定コードを吐いてくれるので、あとはmain関数の中にタイマスタートのHAL関数コールを書くだけで動きます。 
  if (HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1) != HAL_OK)
{
  Error_Handler();
}
その結果がこちら。確かに45Mhzで上げ下げして22.5MhzのPWMが出ていますが、残念ながらGPIOモードの時と違ってIOの速度が自動的にLOWにセットされちゃうので立ち上がりが非常にトロいです。

プリスケーラを0にすることで本当の最高速である、90Mhz上げ下げの45Mhz矩形波が出るのですが…

さすがにこれじゃもう波形が出せてるとは言えません。

ピンによって違うかどうかまでは全部試してませんが、数種類のタイマーで試した限り、PWM出力モードの時はどれもピンのIO出力速度がLOWになっていて変更できませんでした。CPU負荷なしで波形が出せるのはいいんですが、ちょっと残念です。

参考:cubeMXが出力したタイマ設定のコード
static void MX_TIM2_Init(void)
{
  /* USER CODE BEGIN TIM2_Init 0 */
  /* USER CODE END TIM2_Init 0 */
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  /* USER CODE BEGIN TIM2_Init 1 */
  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 1;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */
  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);
}

2020年4月16日木曜日

Lチカ最速を求めて STM32F446RE

久々にcubeMXまで引っ張り出してSTM32をいじっているのには理由があって、ちょっと短かいパルスのゲート信号を好きなように生成したいのです。クロック生信号やPWM出力とかなら簡単に高周波を出せますが、1発だけとか、少しずつディレイを変えながら2発とか、そういったちまちましたことをやるのにマイコンは向いています。

そう考えると、単なるベンチマークみたいなIOトグルのLチカ最速周波数が、自由に出力できるパルスの最短を示しているわけで、どうでもいい数字ではないわけです。

arduino勢の速度を丁寧に計ってくれているひとがいて、それによると矩形波の周波数でarduino UNOが500Hz, DUEが17.85Mhz, ESP8266が6.25Mhzだそうです。やっぱりDUEは速いです。

STM32F446のハードウェアを振り返ると、まずCPUクロックが168Mhz~180Mhzです。そしてGPIOはAH1Bに繋がっています。そしてなんとAH1Bの上限はCPUと同じ180Mhzなのです!

あとは、ポートアクセスで無駄なくたたけば1クロックで状態が変わるはず。ということでcubeMXの助けを借りて下のように書いてみました。

IO初期化
  /*Configure GPIO pins : LD2_Pin D7_Pin */
  GPIO_InitStruct.Pin = LD2_Pin|D7_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

IO出力部
  while (1)
  {
    /* USER CODE END WHILE */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);   //LED
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);   //D7
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
   
    GPIOA->ODR = 65535;
    GPIOA->ODR = 0;
    GPIOA->ODR = 65535;
    GPIOA->ODR = 0;
    GPIOA->ODR = 65535;
    GPIOA->ODR = 0;
    GPIOA->ODR = 65535;
    GPIOA->ODR = 0;

    /* USER CODE BEGIN 3 */
  }
その結果がこちら。HALでトグルした遅いパルス2発と、ポートたたきで出した高速パルス4発が見えます。負荷の影響有無も確認したかったのでLEDポートと空きポートD7の2か所に出しています。(特に違い無かったです)

高速パルス4発の拡大がこれ。パルス数で88Mhzということは、確かに2倍の180MhzでIOの上げ下げができているということです。STM32F4すげー。波形はほぼsin波にしか見えないほどなまってるけど、そもそも立ち上がり設定の最速が100Mhzとされてるので文句は言えません。
ちなみにレジスタ操作のところを "GPIOA->ODR ^= GPIO_ODR_5" みたいにオシャレに書く方法がありますが、これはコンパイルするとIO状態リード→論理演算→ライトの3工程に分かれるので数倍遅くなります。

Lチカ速度を調べたいだけだったのに、がんばってググってもいまいちぴったりの例が無くて実演する羽目になりました。でもすっきりして良かった。STM43F4は速いですよ。

STM32 やってます nucleo F446RE

やっつけ組み込み仕事で、初めてつかうデバイスをSPIとかI2Cで使うときによくarduinoを使うことがあります。サンプルコードが付いてたりしますし。

だんだんマイコン側にいろいろやらせたくなり、さすがにarduino UNOでは速度的にきつくなってくると次に何に移行するかが問題です。石自体はarduino DUEが高性能だったんですが、ほぼディスコンだし意外と高いし、今後標準的に使っていくには不安。

他にメジャーどころではESP32が安くて速いですがクセがありすぎる… 優等生なところでは、Teensy3.2~3.6がとても高性能で、海外では流行っています。arduinoIDEに独自命令やらライブラリを追加しまくっているのでもはやarduinoではない気もしますが、実用的なライブラリが揃っていてとても使いやすい。

…が、我々ジャパニーズとしては、秋月でいつでも安く買えちゃうSTM32の、マイコン系では最高速のnucleoF446REが自由に使えるとより良いのです。


というわけでnucleoF446を何かというと使ってるのですが、開発環境が基本的にmbedのWEBコンパイラです。arduinoほどユーザーは多くないですがまあそれなりに普及していて、使い方も簡単で重宝しています。

唯一の問題は、STM32F4特有のIOを直に叩いて最高速を出したり、DMAであれやこれやしたときには、mbedを使ってる人の参考資料は劇レアで、たいていHALライブラリやcubeMXを使った環境なのです。

cubeMXは今では↓こんなIDEになっていて、巨大ですがこれをインストールしてあればコード生成だけじゃなくビルドもデバッグもできちゃいます。いいんです。いいんですが、こんな巨大なツールをどのマシンにでも入れてあるわけではないので、たいしたことないコードならmbedでちゃちゃっと済ませちゃいたいのです。

ふだんはmbedで楽をして、たまに難しいことをやるときだけcubeMXの自動生成コードをコピペしてきてうまうましたい…という虫のいいことが、基本的に可能です。というか、単にcubeMXで生成したプログラムのmain.cとmain.hをまるごと持ってきてmbed環境でビルドすればそのままビルド通ります。main以外のライブラリソースは持ってこなくてもmbedコンパイラ側にあります。(cubeMXはHALを呼びまくるコードを生成するので、それには当然対応したcpuのstm32f4xx_hal.hが必要ですが、それはmain.hの先頭で呼ばれているので問題ありません)


ただしビルドできるからと言ってそのまま動くとは限らないので、いくつか注意が必要です。えらいひとがこのような教えを書き残しているので従いましょう。確実にハマるのはcubeMXが生成したSystemClock_Config()です。クロック設定がよく見えないmbedレベルでどこからか呼ばれてしまっているので、わたくしはとりあえずcubeMXが吐いたSystemClock_Config()を使わないようにコメントアウトしました。

一応mbed側のソースをぐぐって確認したら、mbedは180Mhz、cubeMXは(USBホスト機能に配慮して)168Mhzで初期化されているみたいですが、それ以外には今のところ大きな違いは無かったです。ペリフェラルをどんどん使うようにしたらどこに初期化コードが書かれるのかまだわからないので、いずれは単にコメントアウトってわけにはいかなくなるのかも。

こんな具合でちまちまと使ってみて、F446REならではのことができたら書き残していきたいと思います。

2020年4月15日水曜日

久々の投稿 Hantekの200Mhzオシロ

久々の投稿です。しばらく在宅勤務でやることがないのと、今年度のおしごとは久々に電子工作系が多いので調べてわかったことをちびちび書いてきます。

しばらく前に職場でUSBオシロの Hantek 6204BD というのを買いました。てきとうにamazonを眺めていたら、200Mhzの4chで2万円台というかなり破格なおねだんで、SDKもあるようなのでロガーとして使えたらいいなあ、もし万が一本当に200Mhzの実力があったらもうけもん、と思って。今は新型の250Mhzのモデルが同価格くらいで売られています。
ちなみにUSBオシロで定評があるのはPicoscopeで、SDK経由でコントロールする使い方も実績があります。だいぶ安くなったけどそれでも200Mhzモデルは秋月で13万円します。なおハイエンドは等価サンプリングオシロですが25Ghzモデルまで出ています。


まず、SDKについては期待できなさそう。一応オフィシャルにSDK一式がありますが、ビルドにVC6とか信じられない環境されるし、ドキュメントも貧弱。もっと新しいモデルはC#のサンプルもあるみたいですが、picoscopeみたいに割り込みをちゃんと使ってソフトが書ける気がまったくしません。labviewで使うくらいならできるかも。

アナログ帯域については、うれしい誤算できっちり200Mhz出ています。サイン波で試したら200Mhzはほとんど減衰無しで、300Mhzくらいまでは減衰しながらついていきます。400Mhzは無理。

下の画像はToFライダーのパルス光を1Ghzのフォトダイオードで眺めた波形。波形の立ち上がりはもっとシャープなはずですが200Mhzすなわち2nsecくらいになまって見えています。2万円なら立派なものです。

SDKに手を出さず、単純にUSBオシロとして使うにはおすすめです。添付ソフトも画面は安っぽいですが良く見たら機能はかなりあるし、反応がきびきびしていて使い勝手は実オシロより良いです。だいぶ前に買ったRIGOLのDS1054Zは要らなかったかもなぁ…


追記:一つ異常動作を発見。3チャンネル以上を同時取り込みすると、画面の横軸スケール表記が正しくない値で表示されます(2チャンネル時500MSPS ⇒ 3チャンネル時250MSPSなのに、それが考慮されてないかんじ)
品評なに見てんの!

2016年1月2日土曜日

MinGWでC++11 (to_string)

ちょっとテキストファイルを別形式にコンバートする小物ツールを作る話がありました。

最終的にはギガバイト級のデータを扱いたいみたいなので、あとで速度を上げやすいようにC++で (なんと自分で選ぶのは初) やってみようかと思い、まずは速度度外視でアルゴリズムを作る段階。

生Cと違ってそれなりのstringクラスはあるようだけど、splitが無かったりしてあまり高機能では無いです。
とはいえ、c++11仕様をONにするとそれなりにいろんな機能が揃ってるようなので、-std=c++11オプションをつけてlinuxでちまちまと開発。


・・・と、そこまではよかったんですが、
年始でちょっと暇ができたところで、windows環境でのビルドも試そうと思って同じものをmingwでビルドしてみたら、無情にも

error: 'to_string' was not declared in this scope

と無常にもto_stringごときでエラーが出ました。


そんなわけないしー、ほかのc++11機能はとおってるしー、としばらく悩んだ末にぐぐってみると、MinGWのバグらしい…
This is a known bug under MinGW. Relevant Bugzilla. In the comments section you can get a patch to make it work with MinGW.
This issue has been fixed in MinGW-w64 distros higher than GCC 4.8.0 provided by the MinGW-w64 project. Despite the name, the project provides toolchains for 32-bit along with 64-bit.
(http://stackoverflow.com/questions/12975341/to-string-is-not-a-member-of-std-says-so-g)


パッチは出ているようですが、MinGW-w64を使えば問題ないみたいなのでそっちに乗り換え。
nuwanディストロ (http://nuwen.net/mingw.html) を拾ってきてただパス通すだけでOKでした。

2015年12月25日金曜日

VirtualBoxのアップデート後になぜかGuest AdditionsのCDがマウントできない

VirtualBoxのGuest AdditionsはVirtualBoxアップデートのたびに更新しないといけないですが、いつからか、メニューからマウスでCDを挿入してもマウント失敗するようになってしまいました。

https://forums.ubuntulinux.jp/viewtopic.php?id=13601

にあるように、sudo mount /dev/sr0 /mnt で手動マウントすればうちでは大丈夫でした。

2015年8月21日金曜日

小ネタ: vivadoのアンインストール

vivadoのバージョンを巻き戻そうと思ってアンインストールしようと思ったのですが、マニュアルを見ると「プログラムグループからアンインストールを選んで…」とか書いてあります。

Linuxの生xwindowでそんなの無いよ!という環境ではコマンドラインでアンインストーラ起動だそうです。

[installPath]/.xinstall/Vivado_2015.1/ xsetup –Uninstall

2015年8月10日月曜日

VirtualBoxで仮想シリアルポート(com0com)を使う

最終的にはzynqでシリアルポートを使うソフトを作りたいんですが、開発はVirtualBox内のLinuxが楽ちんなのでそっちでやっています。

というわけで、VirtualBoxのシリアルポートを外に取り出してあれこれする方法。

パイプ→ethernetというルートでもダメではないんですが、windowsにはせっかくcom0comという素晴らしい仮想シリアルドライバがあるのでこれを使います。


com0comを使うと仮想シリアルポートのペアをwindows内に好きなだけ作ることができて、ペア間はクロスケーブルで繋がっているかのように見えます。
注意点は、フレーミングエラーやビットレート設定違いのときの挙動なんかはエミュレートされてないので正常動作ルートのみが開発可能、という点です。


まず64bitのwindows8だとcom0comの最新(現時点で3.0.0.0)は署名なしなので拒否られてしまいます。無理に最新版でなくても全く問題ないと思うので、ひとつ前の2.2.2.0にはレジスタード版が用意されているのでそっちを使いましょう。


com0comが無事入ったら、正統派のCUIなど無視してGUIを開いてぽちぽちとポートのペアを作りましょう。ここでは2ペア作りました。

名前はCOM**じゃないと面倒が生じることが多いのでGUI上でリネームしてあります。


そしたらVirtualBox側でこのペアの片側を使うように指定するわけですが、com0comのポートはちと表記に注意点があります。 (参考 http://homepage2.nifty.com/nonnon/Link/Null-Modem-Win8.html)


パス名として \\.\COM17  みたいに書いてあげましょう。

あとはゲスト側で/dev/ttyS0 , ttyS1にアクセスすると、ホスト側のペア(com18とか20)とシリアル通信ができます。

3つ以上使えたらいいのに…

2015年7月29日水曜日

ZYNQのMIO GPIOをLinuxから使う

ZYNQのMIOピンは、わりと制限事項があって割り振り自由度もそう高くないので、だんだんPL部が高機能になってくると最終的にはMIOのどうでもいいピンがデバッグ用に残ったりします。

ZYBOだとMIO7にLEDと、MIO50,51にスイッチが着いてます。

で、このMIO7のLEDをGPIOとして光らそうと思ってえらく苦労したのでメモを残します。



まず、日本人ならほとんどの zynq ユーザーが参考にしてそうな marsee さんの以下の記事
http://marsee101.blog19.fc2.com/blog-entry-2203.html

によると、ベースアドレス0xE000A000以降に必要なレジスタが割り振ってあって、方向指定、アウトイネーブルを1にしたあと出力レジスタのビットを1にすれば良さそうです。
んが、この通りにやっても反応がありませんでした。読み出し方向も全く反応が無く、全レジスタ0が読めるだけです。

Linuxからだと上位1Gの空間にアクセスするのに制限があるのか? とか勘違い迷宮にはまり込んで、LEDドライバを流用したカーネル空間からあれこれトライするも、やっぱりダメです。



ベアメタルでMIOのGPIOを使うサンプルはxilinxにもいろいろあるので、ためしにFSBLのカスタマイズ部分  ( fsbl_hooks.c の FsblHookBeforeHandoff の中 ) に、marseeさんと同じ書き方で
volatile unsigned int* mio_base;
mio_base = 0xe000a000;
*(mio_base + 0x81) = 0x80;
*(mio_base + 0x82) = 0x80;
*(mio_base + 0x10) = 0x80;
と書いてみると、みごとにMIO7のLEDが光ります。


つまりPLのコンフィギュレーションやレジスタの使い方は合っていて、Linuxが起動しちゃうと動作しないわけですから、上記のレジスタ以外の上位概念のせいで動作しなくなっているようです。

テクニカルマニュアル
http://japan.xilinx.com/support/documentation/user_guides/j_ug585-Zynq-7000-TRM.pdf
のgpioセクションをきれいな心で読み返してみると、上位概念は
  • モジュール単位のリセット
  • モジュール単位のクロック
  • 出力ピンのトライステート指定
の3つがあるようです。

今困ってる現象では読み出しもまったく機能せずレジスタが0に見えているので、Linuxがリセットかクロックのどちらかを操作してGPIOモジュールを止めたままにしてるんではないかと思います。



強制的に slcr を操作してモジュールを動かすこともできるかもしれませんが、Linux流のやりかたはLinuxにちゃんと用意されてる gpio-zynq ドライバで初期化する、という方法だと思います。


xilinxドライバ参考資料
http://www.wiki.xilinx.com/Linux+GPIO+Driver
これに加えてxilinx ZYNQ用のGPIOドライバ( gpio-zynq.c )をmenuConfigで有効にしておきます。

dtsにはzynq用ものなら最初からgpioについて書かれてるのでそのままでOKです。


起動すると、特にdmesgにgpioドライバのメッセージはありませんが、なんとなく起動してるっぽくて /sys/class/gpioを見ると gpiochip906 というフォルダが増えました。

が、使い方がよくわからないまま、xilinxの参考資料のとおりに
  >echo 240 > /sys/class/gpio/export
とかやっても特に制御用のgpio204フォルダが出現するわけでもなく、正しく動いてるのかどうかわかりません。

まあ、ドライバは起動してるんだから行けるかな、と思ってここで冒頭のmarseeさんの記事にあったコードを (MIO10ピンを意味する0x400はMIO7相当の0x80に変更して) 実行しても、やっぱり無反応のまま…というところでまた途方にくれていました。



が! その後しばらくぐぐっていたら、xilinxフォーラムに
http://forums.xilinx.com/t5/Embedded-Linux/Zynq-Petalinux-hangs-on-GPIO-access/td-p/645008
という記事があり、一番下の方のデバッグ出力を見ると
GPIOs 906-1023, platform/e000a000.gpio, zynq_gpio:
という箇所があるのを見つけました。906って、さっき出現したgpiochip906と同じです。
つーことは、zynqのmio/emio用gpioモジュールは、ドライバ内ではピン番号906~にマップされてる、てことみたいですね。


それなら! というわけで、MIO7相当の
  >echo 913 > /sys/class/gpio/export
とやってみると、見事にgpio913というフォルダが出現し、その中のdirectionやvalueに1を書き込むとMIO7のLEDが点灯しました。


また、一度このexport操作をすると、後はmarseeさんのコードの通りにレジスタを操作する方法でもLEDのON/OFFが可能でした。

つまり、906以降のどこかのピンに対して最初にexportをしたときにgpioモジュールのクロック供給が開始されてる、てことみたいです。

これでやっと、MIOピンを無駄にせずLinuxからIOとして使えるようになりました。