[組み込み] レジスタ制御しようぜ

# はじめに
Qiitaや他の技術ブログとかもWeb系、アプリ系とかの記事が多いじゃないですか。
組み込みの記事ってめちゃ少ないですよね。
どうにかならんのかね？
ということで僕がちょっとでも増やせればという意気込みで組み込みの話を書きます。

で、今回なにをするのかと言うと、直接レジスタを制御をします。(HAL層は使いません)
組み込み屋はやっぱりレジスタを弄らないと的なノリで今回いきます。

※記事が長いのでもしかすると説明不足な箇所も出てくると思います。
　「わからん！」って箇所が出て来たら質問していただければと。回答しますので。

# 動作環境
PC：MacBook Pro(M4 Pro)
OS：Sequoia 15.1
IDE：STM32CubeIDE 1.17.0
コード生成ツール(CMSIS)：STM32CubeMX 17.0.11
評価ボード：Nucleo-F446RE

ボードは秋月とかで3000円ぐらいで売っています。

https://akizukidenshi.com/catalog/g/g110176/

※IDEはWindows版もありますので大丈夫です。(むしろMac版ある方が珍しい)

# 設計&実装
まず、全体のソースコードのリンクを貼っておきます。

https://github.com/kiiisy/cortexM4_reg_sample


今回の記事の書き方としては、メイン処理等全体的なことをこの記事に記載します。
で、各処理を別記事に分割して記載したいと思います。(結構量が多いので)

### 参照資料
作成するにあたりデータシート等が必要になってきます。
以下のリンクから取得しておいてください。

https://www.st.com/ja/microcontrollers-microprocessors/stm32f446/documentation.html

・STM32F446xx advanced Arm®-based 32-bit MCUs
　(記事内ではRM0390と呼称)
・Arm® Cortex®-M4 32-bit MCU+FPU, 225 DMIPS, up to 512 KB Flash/128+4 KB RAM, USB OTG HS/FS, seventeen TIMs, three ADCs and twenty communication interfaces
　(記事内ではDS10693と呼称)
 
https://www.stmcu.jp/design/hwdevelop/nucleo/51836/

・UM1724
　(記事内ではUM1724と呼称)
・MB1136-DEFAULT-C04 Board schematic
　(記事内ではMB1136と呼称)

### 仕様
なにかのレジスタ制御モジュールだけ作成して終わりだと面白くないため、
簡易的なシステムを作成してその中でレジスタ制御を活用する方針で進めたいと思います。

まずは今回作成するモノの仕様を決めたいと思います。
わかりやすくLEDを使用したモノにしましょう。
概要：LED点灯装置
動作概要：PCからシリアル通信でLEDのON/OFFを制御する
　　　　　LEDの状態が変わった際はシリアル通信でその旨を伝えること
動作詳細：
・PCからUART通信を使用し、評価ボード上のLEDを制御する
・送信するデータは"1:点灯" or "0:消灯"とする
・他のデータを送信した場合は無視すること
・前回からLEDの状態が変化しなければなにも処理をしないこと
・LEDの状態が変化した場合はPC側へその旨を通知すること
・通知するデータは固定のデータとし、DMAで転送を行うこと
・割り込みで受信/送信を処理すること
備考：
・LED：評価ボード上のLEDを使用する
・シリアル通信：UART通信を行う
　UART仕様
　データビット：8bit
　パリティ：なし
　ストップビット：1bit
　ボーレート：115200

・全体イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290770/89dd0029-a92f-d21c-4b09-e48b3659140a.png)

これを作成するのにあたり以下のモジュールを作成とします。
<table>
    <tr>
      <td>GPIO</td>
      <td>GPIOの制御を行う。今回の用途はLEDの点灯。</td>
    </tr>
    <tr>
      <td>UART</td>
      <td>UARTの制御を行う。今回の用途はPCとの通信。</td>
    </tr>
    <tr>
      <td>DMA</td>
      <td>DMAの制御を行う。今回の用途はUARTデータの転送。</td>
    </tr>
</table>

では、全体の制御の流れを決めていきましょう

・全体制御フロー
![デバドラ_led制御-制御のフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290770/abd9e8bc-5475-1851-04a5-367063fce806.png)
ざっくり全体の制御フローを説明すると、以下の手順になります。
1 . 初期化処理(DMAやUARTなどの初期化処理)
2 . PCからのデータの受信
3 . 割り込みハンドラで受信データをバッファにセット
4 . バッファのデータを解析し、前回から変更があるかを確認しレジスタにセット
5 . DMA転送を開始
6 . CPUからPCへデータ送信

### 事前準備
プロジェクトにCMSISを追加しないといけないので、そこだけ説明しておきます。

1\. 空のプロジェクトを作成する(Start new STM32 Projectで作成してください)
2\. 以下からCMSISライブラリを取得する

https://github.com/STMicroelectronics/STM32CubeF4

3\. 以下のフォルダを自身のプロジェクトへ持って来て追加する
　Drivers/CMSIS/Device
　Drivers/CMSIS/Include
4\. 先程のフォルダをインクルードパスに追加する
　4-1\.「Properties」を押下
　4-2\.「C/C++ Build」を押下
　4-3\.「Settings」を押下
　4-4\.「MCU/MPU GCC Compiler」の「Include paths」を押下し追加


### 各処理詳細
それでは先ほど記載した各モジュールの処理を作成していきましょう。

| 番号 | モジュール      | リンク |
|:---:|:-------------:|:------:|
| 1   | GPIOモジュール  | https://qiita.com/T_ksy/items/5679175448ddbd20dee4　|
| 2   | UARTモジュール  | https://qiita.com/T_ksy/items/1e1ede1f14aedc092100　|
| 3   | DMAモジュール   | https://qiita.com/T_ksy/items/619fced7568b6e2b4a84　|

### メイン処理&全体説明
```c
init_gpio();
init_uart2();
init_dma1();
config_int_dma1();
enable_dma1_steam6();

for (;;) {
    compare_led_status();
}
```
メイン処理としては各モジュールを初期化して無限ループしています。
無限ループ内はGPIO編で作成したcompare_led_status関数を使用して監視しているだけです。

# 終わりに
これにて作成は完了となります。
今回、ソースコード自体はそこまで難しいものではなかったと思います。
たぶんデータシートを読むのが難しかったのではないかと思います。
ページ数多いし、英語だしで色々難しかったとは思いますが、こればっかりは色々読んで慣れていくしかないです。

まぁ数こなせば取捨選択しながら読める様になって来ますので、安心してください。

まだまだ組み込みネタは書きたいことがあるので、今後色々出して行ければなと思っています。