Contents
C 言語の組込み向け基礎知識
1. 固定幅整数型とメモリ配置
| 型 | ヘッダー | 用途例 |
|---|---|---|
int8_t / uint8_t |
<stdint.h> |
レジスタマスク、フラグ領域 |
int16_t / uint16_t |
<stdint.h> |
16 ビットタイマカウンタ |
int32_t / uint32_t |
<stdint.h> |
アドレス計算、データバッファ |
ポイント
固定幅型を使うことで、コンパイラがターゲット MCU のビット幅と符号付きを自動的に合わせてくれるため、サイズミスマッチによる不具合を防げます。
|
1 2 3 4 5 |
#include <stdint.h> int32_t counter = 0; // 32‑bit 符号付きカウンタ uint8_t flag = 0xFF; // ビットマスク用フラグ |
2. 演算子の優先順位とビット操作
- ビット演算子 (
&,|,^,~,<<,>>) はレジスタ制御で頻繁に使用します。 - 複合代入 (
&=,|=) を活用すると、コードがシンプルになり可読性も向上します。
|
1 2 3 4 |
/* GPIOA の 3 ビット目をセットし、5 ビット目をクリア */ GPIOA->ODR |= (1U << 3); // SET GPIOA->ODR &= ~(1U << 5); // CLEAR |
3. ポインタと volatile の正しい使い方
組込み MCU は フラッシュ / RAM / レジスタ といった異なるメモリ空間を持ち、ポインタで正確にアドレス指定しなければ動作しません。
volatile を付与することで、コンパイラの最適化が読み書きを除外しないよう保証できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#define UART_BASE 0x40011000UL typedef struct { volatile uint32_t SR; volatile uint32_t DR; volatile uint32_t BRR; volatile uint32_t CR1; } UART_TypeDef; static UART_TypeDef * const UART1 = (UART_TypeDef *)UART_BASE; /* 文字送信 */ void uart_putc(char c) { while (!(UART1->SR & (1U << 7))) {} // TXE 待ち UART1->DR = (uint32_t)c; } |
4. レジスタマッピングと割り込みハンドラ
- 構造体でレジスタをマップすることで、ビット単位の操作が C の構文だけで記述可能になります。
- 割り込み関数はコンパイラ固有属性(例:
__attribute__((interrupt)))で宣言し、ベクタテーブルに正しく登録します。
|
1 2 3 4 5 6 |
/* SysTick 割り込みハンドラ (Cortex‑M4) */ void SysTick_Handler(void) __attribute__((interrupt)); void SysTick_Handler(void) { tick_counter++; // 1 ms カウント更新 } |
最新開発環境の構築手順
以下は Windows マシン上で WSL2 + Ubuntu 22.04 をベースにした、2026 年時点で推奨される構成例です。
| 項目 | 推奨ツール・バージョン | 主な役割 |
|---|---|---|
| Linux 環境 | WSL2 + Ubuntu 22.04 (Jammy) | フルカーネルで ARM クロスコンパイラや OpenOCD がそのまま動作 |
| エディタ | Visual Studio Code | 拡張性が高く、PlatformIO との相性抜群 |
| ビルドシステム | GNU Make, CMake (任意) | 手動ビルドフローを柔軟に構築 |
| パッケージマネジメント | apt (Ubuntu 標準) |
必要ツールのインストールに利用 |
| クロスコンパイラ | gcc-arm-none-eabi (公式リポジトリ最新) | ARM Cortex‑M 系列向けのフリーコンパイラ |
| 統合開発環境 | PlatformIO IDE 拡張 | GUI でビルド・書き込み・デバッグが可能 |
| ツールチェーン(手動) | GNU Arm Embedded Toolchain 13.2 (公式サイト配布) | Makefile ベースでも利用できる最新コンパイラ |
注意
Ubuntu のaptで提供されるgcc-arm-none-eabiはリポジトリ更新のタイミングに依存します。最新版が必要な場合は ARM 公式サイトから直接ダウンロードしてください。
手順 1️⃣:WSL2 と Ubuntu のインストール
|
1 2 3 |
# PowerShell(管理者)で実行 wsl --install -d Ubuntu-22.04 # Ubuntu 22.04 LTS を取得 |
起動後、基本的なパッケージを更新します。
|
1 2 3 |
sudo apt update && sudo apt upgrade -y sudo apt install build-essential git cmake python3-pip -y |
手順 2️⃣:クロスコンパイラと Make の導入
|
1 2 3 4 5 6 7 |
# Ubuntu リポジトリから取得(2026 年 4 月時点での最新版) sudo apt install gcc-arm-none-eabi make -y # バージョン確認 arm-none-eabi-gcc --version # → 13.2.x 系列が表示されれば OK make --version # → GNU Make 4.3 以上推奨 |
補足:公式サイトから
gcc-arm-none-eabi-13.2.1-x86_64-linux.tar.bz2をダウンロードし、$HOME/opt配下に展開して PATH に追加すると、常に最新版が使えます。
手順 3️⃣:VS Code と PlatformIO のセットアップ
|
1 2 3 4 5 6 |
# Windows 側で VS Code をインストール(winget が利用可能な場合) winget install Microsoft.VisualStudioCode # Ubuntu 側から拡張を自動導入(VS Code 起動後に実行) code --install-extension platformio.platformio-ide |
PlatformIO は platformio.ini にターゲットボードとフレームワークだけを書けば、内部で必要なツールチェーンやライブラリを取得してくれます。
手順 4️⃣:GNU Arm Embedded Toolchain(手動版)のインストール例
|
1 2 3 4 5 6 7 8 9 |
cd $HOME/opt wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/13.2-2023q4/gcc-arm-none-eabi-13.2.1-x86_64-linux.tar.bz2 tar -xjf gcc-arm-none-eabi-13.2.1-x86_64-linux.tar.bz2 echo 'export PATH=$HOME/opt/gcc-arm-none-eabi-13.2.1/bin:$PATH' >> ~/.bashrc source ~/.bashrc # 動作確認 arm-none-eabi-gcc --version # → 13.2.1 が表示されれば完了 |
クロスコンパイルと書き込みの実践例
STM32F4(Cortex‑M4)向け Makefile ビルド
|
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 |
# === Makefile (STM32F4 用) ========================== TARGET := main CPU := cortex-m4 FPU := fpv4-sp-d16 FLOAT_ABI:= hard CC := arm-none-eabi-gcc OBJCOPY := arm-none-eabi-objcopy CFLAGS := -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FLOAT_ABI) \ -O2 -g -Wall -TSTM32F429ZI.ld SRC := $(wildcard src/*.c) OBJ := $(SRC:.c=.o) all: $(TARGET).elf $(TARGET).hex $(TARGET).elf: $(OBJ) $(CC) $(CFLAGS) $^ -o $@ $(TARGET).hex: $(TARGET).elf $(OBJCOPY) -O ihex $< $@ clean: rm -f $(OBJ) $(TARGET).elf $(TARGET).hex # =================================================== |
STM32F429ZI.ldは ST が提供するリンカスクリプト(スタートアップコードと組み合わせて使用)。- ビルドは
make、生成物は.hexファイル。これを OpenOCD 経由で書き込みます。
ESP32(Arduino フレームワーク)向け PlatformIO 設定
|
1 2 3 4 5 6 7 8 9 10 11 |
# === platformio.ini ================================ [env:esp32dev] platform = espressif32 @ 6.5.0 ; 2026 年最新版 board = esp32dev framework= arduino monitor_speed = 115200 build_flags = -D LED_BUILTIN=2 ; ビルトインLED ピン設定 # ================================================== |
pio run -t upload→ コンパイル+フラッシュpio device monitor→ シリアルモニタ起動
書き込みコマンド例(OpenOCD)
|
1 2 3 4 5 6 |
# STM32F4 (ST-Link/V2) openocd -f interface/stlink.cfg -f target/stm32f4x.cfg # ESP32 (FTDI/ESP‑USB アダプタ) openocd -f interface/ftdi/esp32_devkit.cfg -f target/esp32.cfg |
デバッグ環境(OpenOCD + GDB)
| 機能 | コマンド例 | 説明 |
|---|---|---|
| 接続開始 | openocd -f … |
JTAG/SWD アダプタとターゲットを接続 |
| デバッグ起動 | arm-none-eabi-gdb build/main.elf |
ELF をロードし GDB セッション開始 |
| ターゲット接続 | (gdb) target remote :3333 |
OpenOCD がリスンするポートへ接続 |
| リセット & 停止 | (gdb) monitor reset halt |
デバイスをリセットしてブレークポイント待ち状態に |
| プログラム書き込み | (gdb) load |
ビルドした ELF をフラッシュ |
| ブレークポイント設定 | (gdb) break main |
main 関数開始で停止 |
| 実行再開 | (gdb) continue |
デバッグ実行を続行 |
Tip
GDB のmonitor reg系コマンドでリアルタイムにレジスタ内容を確認できるため、割り込みハンドラの動作検証が楽になります。
ハンズオン:UART コンソール & LED ブリンク
1. UART に文字列出力(STM32F4)
|
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 31 32 |
#include "stm32f4xx.h" #include <stdio.h> /* newlib 用 _write 実装 */ int _write(int file, char *ptr, int len) { for (int i = 0; i < len; ++i) { while (!(USART2->SR & (1U << 7))) {} // TXE 待ち USART2->DR = ptr[i]; } return len; } static void usart2_init(void) { /* クロック有効化 */ RCC->AHB1ENR |= (1U << 0); // GPIOA RCC->APB1ENR |= (1U << 17); // USART2 /* PA2(TX)/PA3(RX) を AF7 に設定 */ GPIOA->MODER &= ~((3U<<4)|(3U<<6)); GPIOA->MODER |= ((2U<<4)|(2U<<6)); // Alternate function GPIOA->AFR[0] |= (7U<<8) | (7U<<12); USART2->BRR = 0x0683; // 115200 @16MHz USART2->CR1 = (1U<<3)|(1U<<2)|(1U<<13); // RE, TE, UE } int main(void) { usart2_init(); printf("Hello, World! from STM32F4\r\n"); while (1) {} } |
_writeを実装すればprintf系関数が UART にシームレスに流れます。- コードは Zenn の無料電子書籍 でも同様のサンプルとして紹介されています(出典:著者公開資料)。
2. GPIO 制御で LED を点滅(STM32F4, PD12)
|
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 |
#include "stm32f4xx.h" static void systick_delay(uint32_t ms) { for (uint32_t i = 0; i < ms; ++i) { SysTick->LOAD = 16000 - 1; // 16 MHz / 1 kHz SysTick->VAL = 0; SysTick->CTRL = 5; // ENABLE + CLKSOURCE while (!(SysTick->CTRL & (1U << 16))) {} } } int main(void) { /* GPIOD クロック有効化 */ RCC->AHB1ENR |= (1U << 3); /* PD12 を汎用出力に設定 */ GPIOD->MODER &= ~(3U << (12 * 2)); GPIOD->MODER |= (1U << (12 * 2)); while (1) { GPIOD->ODR ^= (1U << 12); // トグル systick_delay(500); } } |
SysTickを利用したウェイトは OS に依存しないため、リアルタイム性が保てます。- 同様の実装例は GitHub のサンプルリポジトリ(公開されているもの)でも確認できます。
学習リソースと次のステップ
| カテゴリ | 推奨資料・リンク | 内容 |
|---|---|---|
| 書籍・電子書籍 | Zenn 無料電子書籍 (著者: naoyoshinori) |
基礎文法 → メモリモデル → 組込み概念まで体系的に学べる。章末の演習問題で理解度チェックが可能。 |
| 記事・図解 | Qiita – C言語基礎文法完全ガイド (hhirakawa0328) |
ビジュアル中心でコード例とフローを説明。初心者向けに「ポイント」ごとにまとめられている。 |
| ツールチェーン公式 | GNU Arm Embedded Toolchain https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm |
コンパイラ・リンカ・GDB の最新版ダウンロードとインストール手順。 |
| デバッグ | OpenOCD 公式マニュアル (2026 年版) https://openocd.org/doc/pdf/OpenOCD-0.12.pdf |
JTAG/SWD 設定例、各 MCU ファミリ向け設定ファイルの入手先を網羅。 |
| 実践サンプル | GitHub – embedded-c-guide/sample https://github.com/embedded-c-guide/sample |
UART, LED, PWM など多様なデモが格納。README にビルド・書き込み手順が明記。 |
次に挑戦すべきこと
- リポジトリをクローンし、自分のボードに合わせて
platformio.ini/Makefile を調整
bash
git clone https://github.com/embedded-c-guide/sample.git
cd sample - ビルド → フラッシュ → デバッグ のフローを 3 回以上繰り返し、エラーの原因追求に慣れる。
- 応用課題(例)
- PWM を使ったモータ制御
- ADC で取得したセンサデータをリアルタイムで UART に送信
- FreeRTOS のタスク化でマルチスレッド構成に挑戦
学習のコツ:コードは「動く」ことが最優先。まずはコンパイルエラー・リンクエラーを自力で解決する経験が、組込み開発者としての基盤になります。
まとめ
| 項目 | 要点 |
|---|---|
| C 言語の核 | 固定幅整数・ビット演算子・volatile ポインタ・レジスタマッピングを正しく理解すれば、ハードウェア制御が安全にできる。 |
| 開発環境 | WSL2 + Ubuntu 22.04 に gcc-arm-none-eabi、Make、VS Code+PlatformIO、GNU Arm Toolchain を揃えると、一貫したフローが実現できる。 |
| ビルド・書き込み | STM32 は Makefile、ESP32 は PlatformIO が主流。どちらも openocd と組み合わせれば汎用的なデバッグが可能。 |
| ハンズオン | UART コンソールと LED ブリンクは「動く」ことを確認する最小構成であり、実機テストの入り口になる。 |
| 次へのステップ | 公式サンプルや書籍・記事を活用し、PWM、ADC、RTOS といった上位テーマへ拡張していく。 |
このガイドに沿って環境構築とハンズオンを完了すれば、C 言語初心者でも 組込み開発の土台 が確実に身につきます。あとは 「やってみる」 ことが最も大切です。Happy Embedded Programming!