私は組み込みLinuxドライバーの作成について勉強していて、本 (LDD3、chap9.4.1) を正しく理解するために、いくつかのGPIOを起動することにしました。
意図したとおりに正しいGPIOピンを制御できます(高低にして、マルチメーターでプローブしました)。ただし、2つのコードをテストしました。1つはrequest_mem_region()
あり、もう1つはなしです。私はそれがないと失敗することを期待していますが、どちらもうまくいきます。
_request_mem_region
_を使用したコード:
_if( request_mem_region( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF,DEVICE_NAME ) == NULL )
{
printk( KERN_ALERT
"GPIO_140_141_conf_phys error:%s: unable to obtain I/O memory address 0x%08llX\n",
DEVICE_NAME, PIN3_CONF_PHYS );
return -EBUSY;
}
pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
//-----------------------------------------------------------------
if( request_mem_region( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5,DEVICE_NAME ) == NULL )
{
printk( KERN_ALERT
"error:%s: unable to obtain I/O memory address 0x%08llX\n",
DEVICE_NAME, GPIO_BANK5_PHYS );
return -EBUSY;
}
gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );
//some iowrite32() functions continue...
_
request_mem_region()
なしのコード:
_pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );
//some iowrite32() functions continue...
_
両方のケースで確認できる唯一の違いは、_cat /proc/iomem
_を実行した結果です。request_mem_region()
を使用すると、_49056000-49056097 : GPIO3
_を示す追加の行が表示されます。
私の質問は、request_mem_region()
だけでハードウェアアドレスと通信できるため、ioremap()
が必要な理由です。では、実際にrequest_mem_region()
を使用する必要があるのはいつですか?
返信ありがとうございます!
request_mem_region
は、ドライバーがこの範囲のI/Oアドレスを使用することをカーネルに通知します。これにより、他のドライバーがrequest_mem_region
を介して同じ領域を重複して呼び出すことができなくなります。このメカニズムはいかなる種類のマッピングも行いません。これは純粋な予約メカニズムであり、すべてのカーネルデバイスドライバーがNiceでなければならず、request_mem_region
を呼び出し、戻り値を確認し、ケースで適切に動作する必要があるという事実に依存していますエラーの。
したがって、コードがrequest_mem_region
なしで機能することは完全に論理的です。それは、カーネルコーディングルールに準拠していないというだけです。
ただし、コードがカーネルコーディングスタイルに準拠していません。さらに、gpiolibという名前のGPIOを処理するための既存のインフラストラクチャがあり、GPIOバンクレジスタを手動で再マップする代わりに使用する必要があります。どのプラットフォームに取り組んでいますか?
デバイスドライバーでのrequest_mem_region()およびioremap()の使用は非推奨になりました。代わりに、以下の「マネージ」関数を使用してください。これにより、ドライバーのコーディングとエラー処理が簡素化されます。
devm_ioremap()
devm_iounmap()
devm_ioremap_resource(), Takes care of both the request and remapping operations
https://bootlin.com/doc/training/linux-kernel/linux-kernel-slides.pdf スライド276