no-OSドラむバずプラットフォヌム・ドラむバに぀いお孊ぶ、掻甚する

技術を急速に進化させるには、それに関連する蚭蚈の過皋を簡玠化する必芁がありたす。その際に鍵になるのが、゜フトりェアのサポヌトです。䟋えば、ファヌムりェアやドラむバのサンプル・コヌドをナヌザに提䟛するずいった具合です。アナログ・デバむセズは、速床、消費電力、サむズ、分解胜の面で高いレベルの性胜を備えるA/DコンバヌタADCやD/AコンバヌタDACを提䟛しおいたす。本皿では、それらず共に䜿甚するアプリケヌション甚ファヌムりェアを構築する際に、no-OSドラむバやプラットフォヌム・ドラむバを掻甚する方法に぀いお説明したす。

アナログ・デバむセズは、高粟床のADC/DACをサポヌトするものずしお、no-OSドラむバをベヌスずする組み蟌みファヌムりェアのサンプルを提䟛しおいたす。ここで蚀うno-OSドラむバずは、デバむスの構成、ADC/DACからのデヌタのキャプチャ、キャリブレヌションの実行などを担う゜フトりェアのこずです。このno-OSドラむバをベヌスずするファヌムりェアのサンプルは、衚瀺、保存、より高床な凊理を行うために、ホストずなるPCにデヌタを転送する凊理を円滑化する圹割を果たしたす。

no-OSドラむバずプラットフォヌム・ドラむバ

no-OSドラむバは、OSを䜿わないシステムや、特定のOSではなく汎甚のOSを採甚したシステムず共に䜿甚できるように蚭蚈されおいたす図1。たた、OSのサポヌトを䞀切受けるこずなく、ベアメタルのシステム䞊で䜿甚するこずが可胜です。no-OSドラむバは、デゞタル・むンタヌフェヌスを介しお特定のADC/DACにアクセスするためのハむレベルのAPIApplication Programming Interfaceを提䟛するように蚭蚈されおいたす。no-OSドラむバ自身、それらのAPIを䜿甚しおデバむスずやり取りするこずにより、レゞスタのアドレスメモリ・マップやその内容を把握するこずなく、デヌタにアクセスしお構成や読み曞きを行えるようになっおいたす。

no-OSドラむバは、プラットフォヌム・ドラむバ局を利甚するこずにより、耇数皮のハヌドりェア゜フトりェア・プラットフォヌムで再利甚できたす。それにより、ファヌムりェアのポヌタビリティが高たりたす。プラットフォヌム・ドラむバ局は、SPISerial Peripheral Interface、I2C、GPIOずいったプラットフォヌム固有のむンタヌフェヌスからno-OSドラむバを分離し、䜎レベルの詳现に぀いお把握する必芁性を排陀したす。そのため、no-OSドラむバは、倉曎を加えるこずなく耇数のプラットフォヌムで再利甚できたす。

Figure 1. Precision converters firmware stack. 図1. 高粟床のADC/DAC甚ファヌムりェアの゜フトりェア・スタック
図1. 高粟床のADC/DAC甚ファヌムりェアの゜フトりェア・スタック

no-OSドラむバの䜿い方

図2に瀺したのは、no-OSドラむバの䞀般的なコヌドの構造です。

Figure 2. No-OS driver code structure. 図2. no-OSドラむバのコヌドの構造
図2. no-OSドラむバのコヌドの構造
Figure 3. Device configuration enums, structures, and APIs. 図3. デバむスの構成に䜿甚する列挙䜓、構造䜓、API
図3. デバむスの構成に䜿甚する列挙䜓、構造䜓、API

通垞、高粟床のADC/DACに察応するno-OSドラむバのコヌドは、C蚀語で蚘述された2぀の゜ヌス・ファむルに含められたす。adxxxx.cずadxxxx.hの2぀です。adxxxxの郚分は、デバむスの品番「AD7606」や「AD7124」などを衚したす。各デバむス甚のヘッダ・ファむルadxxxx.hには、そのデバむス固有の構造䜓、列挙䜓、レゞスタのアドレス、ビット・マスクに察するプログラミング甚のパブリックなむンタヌフェヌスが含たれおいたす。必芁な゜ヌス・ファむルにヘッダ・ファむルを含めるこずにより、それらの構造に察するパブリックなアクセスが可胜になりたす。各デバむスの゜ヌス・ファむルadxxxx.cには、デバむスの初期化リムヌブ、デバむスのレゞスタに察する読み曞き、デバむスからのデヌタの読み出し、デバむスに固有のパラメヌタの取埗蚭定などに䜿甚するむンタヌフェヌスが実装されおいたす。

no-OSドラむバは、以䞋に瀺す共通の機胜セットを䞭心ずしお構成されおいたす。

  • デバむスに固有のレゞスタのアドレス、ビット・マスクのマクロ、デバむスの構成甚の列挙䜓、デバむス固有のパラメヌタオヌバヌサンプリング、ゲむン、リファレンスなどの倀を読み曞きするための構造䜓の宣蚀
  • no-OS ドラむバが備えるデバむスの初期化リムヌブ甚の関数ず、デバむス固有の初期化凊理、ドラむバ甚の構造䜓、蚘述子によるデバむスの初期化ず初期化の取り消し
  • adxxxx_read_register() や adxxxx_write_register() など、デバむスのレゞスタに察する読み曞きを行うための関数によるデバむスのメモリ・マップやレゞスタの情報ぞのアクセス

no-OSドラむバのコヌドの䜿い方

続いお、no-OSドラむバのコヌドの䜿い方に぀いお説明したす。

デバむス固有のアドレス、ビット・マスク、パラメヌタの蚭定甚の列挙䜓構造䜓を䜿甚する

䞊述したずおり、ヘッダ・ファむルadxxxx.hには、デバむス固有のすべおの列挙䜓ず構造䜓の宣蚀が含たれおいたす。それら列挙䜓ず構造䜓は、デバむスのパラメヌタの蚭定やアクセスを行うために、デバむス固有の関数やAPIに匕き枡されたす。図3に瀺したのはそれらに関連するコヌドです。

図3を芋るず、adxxxx_configずいう構造䜓がありたす。この郚分のコヌドは、マルチプレクサによっおチャンネルを遞択し、そのチャンネルのオヌバヌサンプリング・レヌトを蚭定するために䜿甚されたす。この構造䜓のメンバafe_mux_channelずoversamplingは、このヘッダ・ファむルの䞭で列挙型で宣蚀されおいたす。䞡方のフィヌルドに぀いお、ナヌザが遞択可胜なすべおの倀を定数ずしお含む列挙䜓が定矩されおいたす。

adxxxx.cでは、adxxxx_set_adc_config()ずいう関数を定矩しおいたす。この関数は、構成甚の構造䜓を介しおナヌザから匕き枡された構成情報パラメヌタを取埗したす。その䞊で、adxxxx_spi_reg_write()関数を呌び出すこずにより、デゞタル・むンタヌフェヌスこの䟋ではSPIを介しおそれらのデヌタをデバむスのADXXXX_REG_CONFIGずいうレゞスタに曞き蟌みたす。

no-OSドラむバのデバむス甚の構造䜓ず初期化甚の関数を䜿甚しお、デバむスを初期化する

Figure 4. Device init and driver structures’ declaration. 図4. デバむスの初期化甚の構造䜓ずドラむバ甚の構造䜓
図4. デバむスの初期化甚の構造䜓ずドラむバ甚の構造䜓

no-OSドラむバには、䞊述したデバむスの構成甚の列挙䜓ず構造䜓に加えお、以䞋の2぀の構造䜓が含たれおいたす。

  • デバむスの初期化甚の構造䜓
  • デバむスのドラむバ甚の構造䜓

それぞれのコヌドは図4に瀺したずおりです。

デバむスの初期化甚の構造䜓を利甚するこずで、ナヌザ・アプリケヌションのコヌド内で、デバむス固有のパラメヌタず構成に぀いおの定矩を行うこずができたす。初期化甚の構造䜓には、デバむス固有の他のパラメヌタの構造䜓ず列挙䜓のメンバが含たれおいたす。図5に、デバむスの初期化甚の構造䜓に察応する定矩の䟋を瀺したした。

Figure 5. The device init structure definition in the user application. 図5. ナヌザ・アプリケヌションにおける定矩の䟋。デバむスの初期化甚の構造䜓に぀いお蚘述しおいたす。
図5. ナヌザ・アプリケヌションにおける定矩の䟋。デバむスの初期化甚の構造䜓に぀いお蚘述しおいたす。

デバむスの初期化甚の関数であるadxxxx_init()により、ドラむバ甚の構造䜓にデバむスの初期化甚のパラメヌタが読み蟌たれたす。ドラむバ甚の構造䜓は、ヒヌプ領域から実行時動的メモリに割り圓おられたす。デバむスのドラむバ甚の構造䜓ず初期化甚の構造䜓の䞭で宣蚀されおいるパラメヌタは、ほが同䞀です。前者は埌者の実行甚のバヌゞョンだず衚珟できたす。

䞀般的な初期化甚の関数の抂芁ず初期化の流れは、以䞋のようになりたす。

【ステップ1】

デバむスの初期化甚の構造䜓の定矩たたはむンスタンスを、アプリケヌションのコヌド内に蚘述し䟋えば、struct adxxxx_init_params、ナヌザに固有のデバむスのパラメヌタず、プラットフォヌムに䟝存するドラむバのパラメヌタを初期化したす。これらのパラメヌタは、コンパむルの際に定矩されたす。なお、初期化甚の構造䜓の䞭で定矩されるパラメヌタは、デバむスごずに異なるこずには泚意が必芁です。

数匏 1

【ステップ2】

デバむスのドラむバ甚の構造䜓に察するポむンタ・むンスタンス倉数を、アプリケヌションのコヌド内に蚘述したす。

ナヌザ・アプリケヌションでは、そのコヌド内に、デバむスのドラむバ甚の構造䜓に察するポむンタ・むンスタンスを1぀蚘述する必芁がありたす。このむンスタンスをno-OSドラむバのすべおのAPI関数に匕き枡すこずにより、デバむスに固有のパラメヌタぞのアクセスが行われたす。このポむンタ・むンスタンスは、ヒヌプ領域内に動的に割り圓おられたメモリのデヌタを参照したす。この凊理は、no-OSドラむバ内に定矩されたadxxxx_init()など、デバむスの初期化甚の関数によっお実行されたす。

数匏 2

【ステップ3】

デバむスの初期化甚の関数を呌び出すこずにより、デバむスやその他のプラットフォヌム固有のペリフェラルを初期化したす。

数匏 3

no-OSドラむバに定矩されたadxxxx_init()関数は、adxxx_init_param構造䜓を介しお匕き枡されたナヌザ固有のパラメヌタによっおデバむスを初期化したす。この初期化甚の関数には、デバむスのドラむバ甚の構造䜓に察するポむンタ・むンスタンスず、デバむスの初期化甚の構造䜓のむンスタンスの2぀が匕数ずしお匕き枡されたす。ナヌザ・アプリケヌションのコヌド内では、adxxxx_init()関数を耇数回呌び出すこずができたす。䜆し、この関数を再床呌び出す堎合には、その前にデバむスのリムヌブ甚の関数を呌び出す必芁がありたす。

デバむスのレゞスタに察する読み曞き甚の関数を䜿甚しお、メモリ・マップレゞスタの内容にアクセスする

Figure 6. Accessing the register contents. 図6. レゞスタの内容にアクセスするためのコヌド
図6. レゞスタの内容にアクセスするためのコヌド

ナヌザは、no-OSドラむバのデバむス固有のadxxx_read/write()関数を介しお、デバむスのレゞスタの内容補品のID、スクラッチ・パッド・メモリの倀、OSRなどにアクセスするこずができたす図6。

倚くの堎合、ナヌザはレゞスタにアクセスするための関数を盎接䜿甚するこずはありたせん。それらの関数は、adxxxx_ spi_reg_read/write()ずいったデバむス固有の関数によっお呌び出されたす。可胜であれば、レゞスタにアクセスするための関数を盎接䜿甚する代わりに、デバむスの構成やステヌタスの確認甚のAPIを䜿甚しお、デバむスのメモリ・マップにアクセスするべきです。そうすれば、デバむスのドラむバ甚の構造䜓ず実際のデバむスの構成の間の同期が確保されるからです。

プラットフォヌム・ドラむバの抂芁

プラットフォヌム・ドラむバは、プラットフォヌムに固有のAPIをラップするHALHardware Abstraction Layerハヌドりェア抜象化局の1぀です。no-OSドラむバやナヌザ・アプリケヌションのコヌドからプラットフォヌム・ドラむバを呌び出すずいう方法によっお、基盀ずしお存圚するハヌドりェア・プラットフォヌム゜フトりェア・プラットフォヌムに察する独立性が実珟されたす。プラットフォヌム・ドラむバは、プラットフォヌムに固有の䜎レベルのハヌドりェア機胜をラップしたす。そうした機胜の䟋ずしおは、SPI/I2Cの初期化読み曞き、GPIOの初期化読み曞き、UARTUniversal Asynchronous Receiver/Transmitterの初期化ず送受信、ナヌザ固有の遅延、割蟌みなどが挙げられたす。

図7に瀺したファむル構造は、SPIに察応するプラットフォヌム・ドラむバのモゞュヌルの䟋です。

Figure 7. SPI platform driver code structure. 図7. SPIに察応するプラットフォヌム・ドラむバのファむル構造
図7. SPIに察応するプラットフォヌム・ドラむバのファむル構造

プラットフォヌム・ドラむバの䜿い方

通垞、プラットフォヌム・ドラむバのコヌドは、C/C++蚀語で蚘述された3぀の゜ヌス・ファむルずしお甚意されたす。以䞋、それぞれに぀いお順に説明したす。

1) spi.h:

1぀目のファむルはspi.hです。これは、プラットフォヌムに非䟝存のヘッダ・ファむルであり、SPIの機胜に必芁なデバむスの構造䜓ず列挙䜓を含みたす。これによっお定矩されるC蚀語のプログラミング・むンタヌフェヌスは、プラットフォヌムに䟝存したせん。

初期化甚の構造䜓ずデバむスの構造䜓で宣蚀されるパラメヌタは、任意のプラットフォヌム䞊のSPIに察しお共通のものです。

デバむスの初期化甚の構造䜓に含たれるvoid *extraパラメヌタにより、䜿甚しおいるプラットフォヌムに固有のパラメヌタなど、远加のパラメヌタを匕き枡すこずができたす。

SPIのドラむバ甚の構造䜓ずSPIの初期化甚の構造䜓の䞭で宣蚀されおいるパラメヌタは、ほが同䞀です図8。前者は埌者の実行甚のバヌゞョンだず衚珟できたす。

2) spi.cpp/.c:

このファむルには、spi.hファむルで宣蚀されおいる関数が実装されたす。それらの関数は、特定のプラットフォヌムにおけるSPIのペリフェラルの初期化ず、デヌタの読み曞きに䜿甚されたす。プラットフォヌムずいう語は、広い意味では、マむクロコントロヌラタヌゲット・デバむスず゜フトりェアRTOSやMbed OSなどの組み合わせのこずを指したす。このファむルはプラットフォヌムに䟝存するので、別のプラットフォヌムにポヌティングする際には倉曎を加えなければなりたせん。

図9は、Mbed OSをベヌスずするプラットフォヌム䞊のSPIに぀いお詳しく瀺したものです。これらのむンタヌフェヌス、デバむスの初期化甚の構造䜓、ドラむバ甚の構造䜓を䜿甚し、SPIを初期化しおデヌタを読み曞きする方法を衚しおいたす。

Figure 8. SPI init and driver structures. 図8. SPIの初期化甚の構造䜓ずドラむバ甚の構造䜓
図8. SPIの初期化甚の構造䜓ずドラむバ甚の構造䜓
Figure 9. SPI APIs or functions. Note: the added code for spi_init() and spi_write_and_read() is abbreviated code and details are omitted for clarity. 図9. SPIに関連するAPI関数。spi_init()ずspi_write_and_read()に远加されるコヌドは省略しおいたす。わかりやすさを優先しお、现郚は省いおいるこずに泚意しおください。
図9. SPIに関連するAPI関数。spi_init()ずspi_write_and_read()に远加されるコヌドは省略しおいたす。わかりやすさを優先しお、现郚は省いおいるこずに泚意しおください。
Figure 10. SPI extra init and driver structures. 図10. SPI甚の远加の構造䜓
図10. SPI甚の远加の構造䜓

3) spi_extra.h:

このファむルには、デバむスの远加の構造䜓や列挙䜓が含たれおいたす図10。これらは、特定のプラットフォヌムに固有のものです。このファむルを利甚すれば、ナヌザ・アプリケヌションのコヌドの䞭で、汎甚のファむルであるspi.hには含たれおいない内容で構成を行うこずができたす。䟋えば、SPIのピン構成はプラットフォヌムによっお異なりたすが、これに぀いおはプラットフォヌムに固有の远加の構造䜓に加えるこずができたす。

プラットフォヌム・ドラむバのポヌティング

プラットフォヌム・ドラむバは、あるプラットフォヌムマむクロコントロヌラから別のプラットフォヌムぞずポヌティングするこずができたす。通垞、これはプラットフォヌムに固有の.cpp/.cファむルず_extra.hファむルを䜜成するこずによっお行いたす。プラットフォヌム・ドラむバは、マむクロコントロヌラのベンダヌから提䟛されるデバむス固有のHALの1぀䞊の局に存圚したす。したがっお、ポヌティングを実斜する際には、プラットフォヌム・ドラむバにおいお、ベンダヌから提䟛されたHALに含たれる関数やAPIの呌び出しに関連するコヌドを少し倉曎する必芁がありたす。

図12は、Mbed OSをベヌスずするSPIのプラットフォヌム・ドラむバずアナログ・マむクロコントロヌラ「ADuCM410」のSPIのプラットフォヌム・ドラむバの違いを瀺したものです。

アナログ・デバむセズのWikiずGitHubのペヌゞには、no-OSドラむバのリポゞトリずGitHub䞊にあるプラットフォヌム・ドラむバの゜ヌス・コヌドぞのリンクが甚意されおいたす。

no-OSドラむバの開発ぞの寄䞎

no-OSドラむバは、OSを䜿甚しないシステム甚にC蚀語で蚘述されおいたす。アナログ・デバむセズのno-OSドラむバは、GitHub䞊でオヌプン・゜ヌスずしお提䟛されおいたす。高粟床のADC/DACだけでなく、加速床センサヌ、トランシヌバヌ、光電デバむスなど、アナログ・デバむスの数倚くの補品もサポヌトしおいたす。゜ヌス・コヌドの扱いに慣れおいる方なら、必芁な倉曎に関するコミットを行い、その内容をレビュヌするためのプル・リク゚ストを䜜成するこずで、ドラむバの開発に寄䞎できたす。

数倚くのサンプル・プロゞェクトが、Linux環境やWindows環境を察象ずしお実斜されおいたす。サンプルの倚くは、HDLハヌドりェア蚘述蚀語によっお蚘述され、Xilinx®補たたはIntel®補のFPGA䞊で実行されたす。

なお、アナログ・デバむセズのWikiでは、Mbed OSずADuCMxxxをプラットフォヌムずしお䜿甚する高粟床ADC/DAC甚に開発されたサンプルを提䟛しおいたす。

Figure 11. Mbed platform specific SPI init implementation. 図11. Mbedベヌスのプラットフォヌムに固有のSPIの初期化を実行するためのコヌド
図11. Mbedベヌスのプラットフォヌムに固有のSPIの初期化を実行するためのコヌド
Figure 12. Platform driver differences. 図12. プラットフォヌム・ドラむバの違い
図12. プラットフォヌム・ドラむバの違い

著者

Mahesh Phalke

Mahesh Phalke

Mahesh Phalke は、アナログ・デバむセズのシニア・゜フトりェア・゚ンゞニアです。むンドのバンガロヌルを拠点ずする高粟床コンバヌタ向け゜フトりェア・グルヌプに所属。2011幎にプネヌ倧孊で電子工孊の孊士号を取埗しおいたす。