Skip to content

필사 모드: 組み込みシステム・IoT完全ガイド: MCUからエッジAIまで

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

1. 組み込みシステムの概要

組み込みシステム(Embedded System)とは、特定の機能を実行するためにハードウェアとソフトウェアが統合された専用コンピューティングシステムです。洗濯機、自動車のエンジン制御ユニット(ECU)、スマートサーモスタット、医療機器など、私たちの身の回りにある数多くの製品に内蔵されています。

マイクロコントローラ(MCU)vs マイクロプロセッサ(MPU)

| 項目 | MCU | MPU |

| -------- | -------------------- | ------------------- |

| CPU | シンプル・低消費電力 | 高性能・複雑 |

| メモリ | 内蔵Flash/RAM | 外付けDRAMが必要 |

| OS | なし or RTOS | Linux, Android等 |

| 消費電力 | 数mW | 数W |

| 例 | STM32, AVR, ESP32 | Raspberry Pi, i.MX8 |

主要MCUプラットフォーム

- **STM32(STマイクロエレクトロニクス)**: ARM Cortex-Mベース、産業用途に広く採用。HALライブラリとCubeMX GUIツールを提供。

- **AVR(Microchip/Atmel)**: Arduino UNOの基盤MCU。入門者に親しみやすいプラットフォーム。

- **ESP32(Espressif)**: デュアルコアXtensa LX6にWiFiとBLEを内蔵。IoTプロジェクトに最適。

- **RP2040(Raspberry Pi)**: デュアルコアARM Cortex-M0+に独自のPIO(プログラマブルI/O)サブシステムを搭載。

- **PIC(Microchip)**: 産業現場で長い実績を持つMCUファミリー。

開発環境

- **IDE**: STM32CubeIDE, MPLAB X, Arduino IDE, PlatformIO

- **コンパイラ**: GCC(arm-none-eabi-gcc), LLVM/Clang

- **デバッガ**: JTAG, SWD(Serial Wire Debug), OpenOCD, J-Link, ST-Link

2. Cによるハードウェア制御

組み込みCプログラミングの核心は、ハードウェアレジスタを直接操作するか、メーカー提供のHAL(ハードウェア抽象化レイヤ)ライブラリを活用することです。

GPIO制御

GPIO(General Purpose Input/Output)はデジタル入出力を制御する最も基本的なインタフェースです。

// STM32 HALライブラリを使ったGPIO制御

#include "stm32f4xx_hal.h"

// LED トグル(ピン PA5)

HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

HAL_Delay(500);

// ボタン読み取り(ピン PC13、アクティブLOW)

if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET) {

// ボタン押下時の処理

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

}

レジスタ直接操作

HALを使わずにレジスタを直接操作すると、より高速でコードサイズの小さな実装が可能です。

// レジスタ直接操作(STM32F4)

// GPIOAクロック有効化

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

// PA5を出力に設定(MODERレジスタ)

GPIOA->MODER &= ~(0x3 << (5 * 2)); // ビットクリア

GPIOA->MODER |= (0x1 << (5 * 2)); // 出力モード設定

// PA5 HIGH出力

GPIOA->BSRR = (1 << 5);

// PA5 LOW出力

GPIOA->BSRR = (1 << (5 + 16));

volatileキーワードの重要性

コンパイラの最適化により、ハードウェアレジスタへのアクセスが省略される場合があります。`volatile`修飾子でこれを防ぎます。

// 誤り: コンパイラが最適化で除去する可能性あり

uint32_t *reg = (uint32_t *)0x40020000;

*reg = 0x01;

// 正解: volatileを使用

volatile uint32_t *reg = (volatile uint32_t *)0x40020000;

*reg = 0x01;

// ISRで変更されるグローバル変数もvolatileが必要

volatile uint8_t button_pressed = 0;

3. 割り込みとタイマー

割り込みサービスルーチン(ISR)

割り込みとは、ハードウェアイベント(ボタン入力、タイマーオーバーフロー、データ受信など)が発生した際に、CPUが現在の処理を中断してISRを実行するメカニズムです。

// EXTI割り込みコールバック(HAL方式)

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {

if (GPIO_Pin == GPIO_PIN_13) {

button_pressed = 1;

// ISR内では最小限の処理のみ

// HAL_Delay()などのブロッキング関数は使用禁止

}

}

// タイマー割り込みコールバック(1msごとに呼び出し)

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {

if (htim->Instance == TIM2) {

system_tick++;

}

}

PWM出力

タイマーのPWM(パルス幅変調)機能で、サーボモータ制御、LED輝度調節、DCモータ速度制御を実現します。

// PWM開始(TIM3チャンネル1)

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

// デューティ比50%設定(ARR=999のとき CCR=500)

__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 500);

// サーボモータ角度制御(0〜180度)

void servo_set_angle(uint8_t angle) {

// 1ms〜2msのパルス幅をタイマーカウンタ値に変換

uint32_t pulse = 500 + (angle * 1000 / 180);

__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pulse);

}

4. シリアル通信プロトコル

UART/USART

非同期シリアル通信。デバッグ出力、GPSモジュール、Bluetoothモジュールとの接続に主に使われます。

// UART文字列送信

char msg[] = "Hello, UART!\r\n";

HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);

// UART受信(割り込み方式)

uint8_t rx_byte;

HAL_UART_Receive_IT(&huart2, &rx_byte, 1);

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {

if (huart->Instance == USART2) {

rx_buffer[rx_index++] = rx_byte;

HAL_UART_Receive_IT(&huart2, &rx_byte, 1);

}

}

SPI通信

マスタ・スレーブ同期通信。ディスプレイ、SDカード、ADCなど高速データ転送が必要な用途に使います。

// SPI送受信(Flash ID読み取り)

uint8_t tx_data[] = {0x9F, 0x00};

uint8_t rx_data[2];

HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); // CS LOW

HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, 2, 100);

HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); // CS HIGH

I2C通信

2線式(SDA/SCL)バス通信。同一バスに複数デバイスを接続可能(アドレスで識別)。センサー類に標準的に使われます。

// I2CでMPU6050加速度センサー読み取り

#define MPU6050_ADDR 0xD0 // 7ビットアドレス0x68、書き込み0xD0

#define ACCEL_XOUT_H 0x3B

uint8_t data[6];

HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, ACCEL_XOUT_H,

I2C_MEMADD_SIZE_8BIT, data, 6, 100);

int16_t accel_x = (data[0] << 8) | data[1];

int16_t accel_y = (data[2] << 8) | data[3];

int16_t accel_z = (data[4] << 8) | data[5];

// 実際の加速度(g単位)= raw / 16384.0(±2g設定時)

float ax = accel_x / 16384.0f;

CANバス

自動車・産業機器で使われる堅牢な差動シリアル通信プロトコルです。

// CANメッセージ送信(STM32 HAL)

CAN_TxHeaderTypeDef tx_header;

uint8_t tx_data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};

uint32_t tx_mailbox;

tx_header.StdId = 0x123;

tx_header.IDE = CAN_ID_STD;

tx_header.RTR = CAN_RTR_DATA;

tx_header.DLC = 8;

HAL_CAN_AddTxMessage(&hcan1, &tx_header, tx_data, &tx_mailbox);

5. RTOS(リアルタイムオペレーティングシステム)

RTOSは決定論的なタイミングを保証するOSです。複数のタスクを優先度に従ってスケジューリングし、リアルタイム応答が求められるシステムに不可欠です。

FreeRTOSの基礎

FreeRTOSは世界で最も広く使われているオープンソースRTOSです。Amazonが管理し、STM32、ESP32、Arduinoなど多くのプラットフォームをサポートします。

#include "FreeRTOS.h"

#include "task.h"

#include "semphr.h"

#include "queue.h"

// LEDブリンクタスク

void vTaskLED(void *pvParameters) {

while(1) {

HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);

vTaskDelay(pdMS_TO_TICKS(500)); // 500ms待機(CPU譲渡)

}

}

// センサー読み取りタスク

void vTaskSensor(void *pvParameters) {

QueueHandle_t xQueue = (QueueHandle_t)pvParameters;

float temperature;

while(1) {

temperature = read_temperature_sensor();

xQueueSend(xQueue, &temperature, portMAX_DELAY);

vTaskDelay(pdMS_TO_TICKS(1000));

}

}

int main(void) {

HAL_Init();

SystemClock_Config();

QueueHandle_t xTempQueue = xQueueCreate(10, sizeof(float));

// タスク生成(関数名, タスク名, スタックサイズ, パラメータ, 優先度, ハンドル)

xTaskCreate(vTaskLED, "LED", 128, NULL, 1, NULL);

xTaskCreate(vTaskSensor, "Sensor", 256, xTempQueue, 2, NULL);

vTaskStartScheduler(); // RTOSスケジューラ起動(ここから戻らない)

while(1);

}

セマフォとミューテックス

SemaphoreHandle_t xMutex;

SemaphoreHandle_t xSemaphore;

// ミューテックスで共有リソースを保護

xMutex = xSemaphoreCreateMutex();

void vTaskA(void *pvParameters) {

while(1) {

if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {

// クリティカルセクション

shared_data++;

xSemaphoreGive(xMutex);

}

}

}

// バイナリセマフォでISR-タスク同期

xSemaphore = xSemaphoreCreateBinary();

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);

portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}

6. Arduinoエコシステム

Arduinoは組み込み入門のハードルを下げるために設計されたオープンソースプラットフォームです。シンプルなAPIと膨大なライブラリエコシステムが特徴です。

Arduinoボード比較

| ボード | MCU | クロック | Flash | RAM | 特徴 |

| --------- | ---------- | -------- | ----- | ---- | -------------------- |

| UNO R3 | ATmega328P | 16MHz | 32KB | 2KB | 定番入門用 |

| Nano | ATmega328P | 16MHz | 32KB | 2KB | 小型フォームファクタ |

| Mega 2560 | ATmega2560 | 16MHz | 256KB | 8KB | 多数のI/Oピン |

| Due | SAM3X8E | 84MHz | 512KB | 96KB | 32ビットARM |

| UNO R4 | RA4M1 | 48MHz | 256KB | 32KB | 最新世代 |

DHT22 + I2C LCD実例

#include <DHT.h>

#include <LiquidCrystal_I2C.h>

#define DHTPIN 2

#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {

Serial.begin(9600);

dht.begin();

lcd.init();

lcd.backlight();

lcd.print("IoT Weather Box");

delay(2000);

lcd.clear();

}

void loop() {

float temp = dht.readTemperature();

float hum = dht.readHumidity();

if (isnan(temp) || isnan(hum)) {

Serial.println("DHT read error!");

return;

}

lcd.setCursor(0, 0);

lcd.print("Temp: ");

lcd.print(temp, 1);

lcd.print(" C ");

lcd.setCursor(0, 1);

lcd.print("Hum: ");

lcd.print(hum, 1);

lcd.print(" % ");

Serial.print("T="); Serial.print(temp);

Serial.print(" H="); Serial.println(hum);

delay(2000);

}

7. ESP32 & WiFi/BLE IoT

ESP32はEspressif製の強力なIoT MCUです。デュアルコア240MHz、WiFi 802.11 b/g/n、BLE 4.2/5.0を内蔵し、コストパフォーマンスに優れています。

MicroPythonでMQTT IoTを実装

MicroPython ESP32 -- MQTTでセンサーデータを送信

from umqtt.simple import MQTTClient

from machine import Pin, ADC

def connect_wifi(ssid, password):

wlan = network.WLAN(network.STA_IF)

wlan.active(True)

if not wlan.isconnected():

wlan.connect(ssid, password)

while not wlan.isconnected():

time.sleep(0.5)

print('WiFi接続:', wlan.ifconfig())

def on_message(topic, msg):

print('Topic:', topic, 'Message:', msg)

connect_wifi('MySSID', 'MyPassword')

adc = ADC(Pin(34))

adc.atten(ADC.ATTN_11DB)

client = MQTTClient('esp32_sensor', 'broker.hivemq.com', port=1883)

client.set_callback(on_message)

client.connect()

client.subscribe(b'device/control')

while True:

raw = adc.read()

voltage = raw * 3.3 / 4095

temp_approx = (voltage - 0.5) * 100

payload = '{:.1f}'.format(temp_approx)

client.publish(b'sensor/temperature', payload.encode())

client.check_msg()

time.sleep(5)

ESP-IDF WiFi(C/C++)

// ESP-IDF WiFiステーション初期化

#include "esp_wifi.h"

#include "esp_event.h"

#include "nvs_flash.h"

#define WIFI_SSID "MyNetwork"

#define WIFI_PASS "MyPassword"

static void wifi_event_handler(void *arg, esp_event_base_t event_base,

int32_t event_id, void *event_data) {

if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {

esp_wifi_connect();

} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {

ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;

ESP_LOGI("WiFi", "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));

}

}

void wifi_init_sta(void) {

nvs_flash_init();

esp_netif_init();

esp_event_loop_create_default();

esp_netif_create_default_wifi_sta();

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

esp_wifi_init(&cfg);

esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL);

esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL);

wifi_config_t wifi_config = {

.sta = { .ssid = WIFI_SSID, .password = WIFI_PASS },

};

esp_wifi_set_mode(WIFI_MODE_STA);

esp_wifi_set_config(WIFI_IF_STA, &wifi_config);

esp_wifi_start();

}

8. Raspberry Pi & Linux組み込み

Raspberry Piは完全なLinuxオペレーティングシステムを実行するシングルボードコンピュータ(SBC)です。組み込み開発と汎用コンピューティングの境界に位置する強力なプラットフォームです。

Raspberry Piモデル比較

| モデル | CPU | RAM | 特徴 |

| ------------ | -------------------------- | ------ | -------------------- |

| Pi Zero 2W | ARM Cortex-A53 quad 1GHz | 512MB | 超小型・WiFi/BLE搭載 |

| Pi 4 Model B | ARM Cortex-A72 quad 1.8GHz | 1〜8GB | 汎用高性能 |

| Pi 5 | ARM Cortex-A76 quad 2.4GHz | 4〜8GB | 最新世代 |

| Pi Pico 2 | RP2350 dual Cortex-M33 | 520KB | マイクロコントローラ |

GPIO制御とサーボモータ

GPIO.setmode(GPIO.BCM)

GPIO.setup(18, GPIO.OUT)

50Hz PWMでサーボモータ制御

pwm = GPIO.PWM(18, 50)

pwm.start(7.5) # ニュートラル位置(90度)

def set_servo_angle(angle):

"""サーボの角度を0〜180度で設定"""

duty = 2.5 + (angle / 180.0) * 10.0

pwm.ChangeDutyCycle(duty)

time.sleep(0.3)

try:

for angle in [0, 45, 90, 135, 180]:

set_servo_angle(angle)

print(f"角度: {angle}度")

time.sleep(1)

finally:

pwm.stop()

GPIO.cleanup()

gpiozeroライブラリ

from gpiozero import LED, Button, DistanceSensor

led = LED(17)

button = Button(4)

button.when_pressed = led.on

button.when_released = led.off

HC-SR04超音波距離センサー

sensor = DistanceSensor(echo=24, trigger=23)

while True:

dist = sensor.distance * 100 # cm単位

print(f"距離: {dist:.1f} cm")

if dist < 20:

led.blink(on_time=0.1, off_time=0.1)

time.sleep(0.5)

Dockerコンテナで運用

Raspberry Pi向けPython IoTアプリ Dockerfile

FROM python:3.11-slim-bullseye

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "sensor_server.py"]

docker-compose.yml -- フルIoTスタック

version: '3'

services:

sensor-app:

build: .

privileged: true # GPIO接続に必要

volumes:

- /dev:/dev

restart: unless-stopped

influxdb:

image: influxdb:2.7

ports:

- '8086:8086'

volumes:

- influx_data:/var/lib/influxdb2

grafana:

image: grafana/grafana:latest

ports:

- '3000:3000'

volumes:

- grafana_data:/var/lib/grafana

volumes:

influx_data:

grafana_data:

9. エッジAI(Edge AI)

エッジAIとは、クラウドではなくローカルデバイスでAI推論を実行する技術です。超低遅延、オフライン動作、プライバシー保護、帯域幅削減が主なメリットです。

TensorFlow Lite(TFLite)

TFLiteはモバイルおよび組み込みデバイス向けに最適化された軽量MLフレームワークです。

TFLite画像分類推論(Raspberry Pi)

from PIL import Image

インタプリタのロードと初期化

interpreter = tflite.Interpreter(

model_path='mobilenet_v2_1.0_224_quant.tflite',

num_threads=4

)

interpreter.allocate_tensors()

input_details = interpreter.get_input_details()

output_details = interpreter.get_output_details()

print("入力形状:", input_details[0]['shape']) # [1, 224, 224, 3]

print("入力型:", input_details[0]['dtype']) # uint8(量子化モデル)

def classify_image(image_path, labels):

img = Image.open(image_path).convert('RGB').resize((224, 224))

input_data = np.expand_dims(np.array(img), axis=0)

interpreter.set_tensor(input_details[0]['index'], input_data)

start = time.time()

interpreter.invoke()

elapsed = (time.time() - start) * 1000

output = interpreter.get_tensor(output_details[0]['index'])

top_idx = np.argmax(output[0])

print(f"ラベル: {labels[top_idx]}, スコア: {output[0][top_idx]}")

print(f"推論時間: {elapsed:.1f}ms")

with open('labels.txt') as f:

labels = [line.strip() for line in f.readlines()]

classify_image('test.jpg', labels)

ONNX Runtime

ONNX Runtimeでカスタムモデルを実行

from PIL import Image

session = ort.InferenceSession(

'model.onnx',

providers=['CPUExecutionProvider']

)

input_name = session.get_inputs()[0].name

output_name = session.get_outputs()[0].name

input_shape = session.get_inputs()[0].shape

print(f"入力: {input_name}, 形状: {input_shape}")

画像前処理

img = Image.open('test.jpg').resize((224, 224))

img_array = np.array(img).astype(np.float32) / 255.0

img_array = np.transpose(img_array, (2, 0, 1)) # HWC to CHW

img_array = np.expand_dims(img_array, axis=0) # バッチ次元追加

result = session.run([output_name], {input_name: img_array})

print("出力形状:", result[0].shape)

エッジAIプラットフォーム比較

| プラットフォーム | ベンダー | AI性能 | 消費電力 | 特徴 |

| ---------------- | -------------- | ---------- | -------- | ------------------ |

| Jetson Orin Nano | NVIDIA | 40 TOPS | 7〜15W | CUDAオンチップGPU |

| Coral Dev Board | Google | 4 TOPS | 約2W | 専用Edge TPU |

| RK3588ボード | Rockchip | 6 TOPS NPU | 約8W | コスパ優秀 |

| Hailo-8 M.2 | Hailo | 26 TOPS | 2.5W | PCIe拡張モジュール |

| Pi 5 + AI HAT+ | RPi Foundation | 26 TOPS | 約5W | Piエコシステム対応 |

10. IoT通信プロトコルとクラウド

MQTT

MQTT(Message Queuing Telemetry Transport)はIoT向けに最適化された軽量のpub/subプロトコルです。ブローカーが発行者と購読者を分離し、スケーラブルで効率的なメッセージングを実現します。

Python Paho-MQTTクライアント

BROKER = "broker.hivemq.com"

PORT = 1883

TOPIC_PUB = "home/sensor/living_room"

TOPIC_SUB = "home/control/#"

def on_connect(client, userdata, flags, rc):

print(f"接続コード: {rc}")

client.subscribe(TOPIC_SUB)

def on_message(client, userdata, msg):

payload = json.loads(msg.payload.decode())

print(f"Topic: {msg.topic}, Payload: {payload}")

client = mqtt.Client("python_sensor_01")

client.on_connect = on_connect

client.on_message = on_message

client.connect(BROKER, PORT, keepalive=60)

client.loop_start()

while True:

data = {

"temperature": 23.5,

"humidity": 60.2,

"timestamp": int(time.time())

}

client.publish(TOPIC_PUB, json.dumps(data))

time.sleep(10)

InfluxDB + Grafanaデータ可視化

InfluxDB 2.xにセンサーデータを書き込む

from influxdb_client import InfluxDBClient, Point

from influxdb_client.client.write_api import SYNCHRONOUS

INFLUX_URL = "http://localhost:8086"

INFLUX_TOKEN = "your_token_here"

INFLUX_ORG = "myorg"

INFLUX_BUCKET = "iot_sensors"

client = InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG)

write_api = client.write_api(write_options=SYNCHRONOUS)

point = (

Point("environment")

.tag("location", "living_room")

.tag("device", "esp32_01")

.field("temperature", 23.5)

.field("humidity", 60.2)

.field("co2_ppm", 650)

)

write_api.write(bucket=INFLUX_BUCKET, record=point)

クラウドIoTサービス

- **AWS IoT Core**: 完全マネージド型、数十億台のデバイスをサポート。X.509証明書ベースのmTLSで安全な接続を実現。Lambda、DynamoDB、S3と統合。

- **Azure IoT Hub**: エンタープライズ向けデバイス管理。デバイスツインやダイレクトメソッドが利用可能。

- **Google Cloud IoT**: Pub/Sub、BigQuery、Vertex AIとの統合でエンドツーエンドのMLパイプラインを構築。

11. 組み込みセキュリティ

OTA(Over-the-Air)ファームウェア更新

セキュアOTAの核心は署名検証です。署名されていないファームウェアを拒否し、悪意あるコードのインストールを防止します。

// ESP-IDF HTTPS OTAアップデート

#include "esp_ota_ops.h"

#include "esp_https_ota.h"

void ota_task(void *pvParameter) {

esp_https_ota_config_t ota_config = {

.http_config = &(esp_http_client_config_t){

.url = "https://myserver.com/firmware.bin",

.cert_pem = server_cert_pem, // サーバー証明書検証

},

};

esp_err_t ret = esp_https_ota(&ota_config);

if (ret == ESP_OK) {

esp_restart();

} else {

ESP_LOGE("OTA", "Update failed: %s", esp_err_to_name(ret));

}

vTaskDelete(NULL);

}

MCUでのAES暗号化

// mbedTLS AES-128 CBC暗号化(STM32/ESP32)

#include "mbedtls/aes.h"

void aes_encrypt_data(uint8_t *plaintext, uint8_t *ciphertext,

uint8_t *key, uint8_t *iv, size_t len) {

mbedtls_aes_context ctx;

mbedtls_aes_init(&ctx);

mbedtls_aes_setkey_enc(&ctx, key, 128); // 128ビット鍵

uint8_t iv_copy[16];

memcpy(iv_copy, iv, 16); // IVは暗号化中に変化

mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, len,

iv_copy, plaintext, ciphertext);

mbedtls_aes_free(&ctx);

}

セキュリティ設計原則

1. **最小権限の原則**: 必要な機能のみ有効化、未使用インタフェースは無効化

2. **セキュアブート(Secure Boot)**: 起動時にファームウェア署名を検証

3. **フラッシュ暗号化**: フラッシュメモリに保存されたコード・データを暗号化

4. **読み出し保護(RDP)**: JTAG/SWDによるファームウェアダンプを防止

5. **ハードウェアRNG(TRNG)**: 暗号化鍵生成にオンチップ真性乱数生成器を使用

6. **ウォッチドッグタイマー**: 無応答状態を自動復旧

12. 確認クイズ

**正解**: MCU(マイクロコントローラ)はCPU、メモリ(FlashとRAM)、周辺機器(UART、SPI、I2C、ADC等)が1チップに統合されています。一方、MPU(マイクロプロセッサ)はCPUコアに特化し、外付けメモリや周辺チップが別途必要です。

**解説**: MCUは低消費電力・小型・低コストが求められる組み込みアプリケーションに適しています。MPUはLinuxのような複雑なOSを動かす必要があるゲートウェイ、HMIパネル、メディアデバイスに適しています。

**正解**: ミューテックスには**所有権(Ownership)**があり、ロックしたタスクだけがアンロックできます。また優先順位逆転を防ぐ優先順位継承機能を備えています。バイナリセマフォには所有権がなく、別のタスクやISRでもシグナルを送れます。

**解説**: ミューテックスは共有リソースの相互排他(Mutual Exclusion)に使います。バイナリセマフォはタスク間のイベント同期、特にISRからタスクへの通知に使います。ISR内でミューテックスを使うのは誤りであり、デッドロックの原因になります。

**正解**:

- **I2Cの利点**: 2線(SDA+SCL)のみ、同一バスに複数機器を接続可能(7ビットアドレスで識別)、配線がシンプル

- **I2Cの欠点**: SPIより低速(最大約3.4Mbps)、プルアップ抵抗が必要、オープンドレイン方式

- **SPIの利点**: 非常に高速(数十Mbps)、全二重通信、電気的にシンプル

- **SPIの欠点**: 機器ごとにCS(チップセレクト)ピンが必要でピン数が増える、アドレス概念なし

**解説**: 低速センサー(MPU6050、BMP280等)には配線の簡便さからI2Cを、TFTディスプレイ、SDカード、SPIフラッシュなど高速転送が必要な機器にはSPIを使います。

**正解**: コンパイラは変数の値がプログラムの通常の実行パスでしか変化しないと仮定します。そのため値をレジスタにキャッシュして、メモリからの再読み込みを省略することがあります。しかしハードウェアレジスタ、ISRで更新される変数、DMAバッファはプログラムフロー外部から値が変わります。`volatile`修飾子はコンパイラにこれらの変数を最適化しないよう指示します。

**解説**: `volatile`なしでISR内でフラグを立てても、メインループがレジスタにキャッシュされた値を読み続け、変更を認識しないバグが発生します。これは組み込みシステム開発における典型的で発見が難しいバグの一つです。

**正解**: 量子化はモデルの重みと活性化値を32ビット浮動小数点(FP32)から8ビット整数(INT8)に変換する手法です。これによりモデルサイズが約4分の1になり、推論速度が2〜4倍向上し、メモリ使用量と消費電力を大幅に削減できます。

**解説**: 組み込みデバイスはメモリ(数MB)と演算リソースが極めて限られています。TFLiteのINT8量子化モデルであれば、Raspberry PiやCortex-M MCUといった低スペック機器でもリアルタイム推論が可能です。精度の低下は一般的にFP32モデルと比較して1〜2%以内に収まり、多くの実用用途では許容範囲内です。

参考資料

- [FreeRTOS公式ドキュメント](https://www.freertos.org/Documentation/RTOS_book.html)

- [STM32 HALドライバユーザーマニュアル(UM1725)](https://www.st.com/resource/en/user_manual/um1725-description-of-stm32f4-hal-and-lowlayer-drivers-stmicroelectronics.pdf)

- [ESP-IDFプログラミングガイド](https://docs.espressif.com/projects/esp-idf/en/latest/)

- [TensorFlow Lite マイクロコントローラ向け](https://www.tensorflow.org/lite/microcontrollers)

- [Raspberry Pi Foundation公式ドキュメント](https://www.raspberrypi.com/documentation/)

- [Arduino言語リファレンス](https://www.arduino.cc/reference/en/)

- [MQTT プロトコル仕様(OASIS)](https://mqtt.org/mqtt-specification/)

현재 단락 (1/467)

組み込みシステム(Embedded System)とは、特定の機能を実行するためにハードウェアとソフトウェアが統合された専用コンピューティングシステムです。洗濯機、自動車のエンジン制御ユニット(ECU...

작성 글자: 0원문 글자: 17,096작성 단락: 0/467