この記事では、自動車や医療機器などの高信頼性が求められる組み込みシステムを想定し、MISRA C:2012 および最新の MISRA C:2023 規約を厳格に遵守した振動モータ(PWM制御)の実装方法を解説します。
また、AIを活用しながら規約を遵守する「バイブコーディング(Vibe Coding)」のベストプラクティスについても触れます。
1. MISRA C:2023 の重要ポイントと変更点
MISRA C:2023は、2012年版に Amendment 2〜4 を統合した最新のガイドラインです。
- C11/C18の正式サポート: マルチスレッド(<threads.h>)やアトミック操作(<stdatomic.h>)に関するルールが追加されました。
- 型安全の強化: 暗黙の型変換に対するチェックがより厳格になりました。
- 未定義動作の排除: 開発者の意図しない動作(ポインタ演算の誤用、未初期化アクセスなど)を「Mandatory(必須)」ルールで禁止しています。
2. サンプルコード:MISRA準拠のバイブ制御
以下に、一般的なマイコン(STM32, RL78等)を想定した、PWMによる振動強度制御のサンプルを示します。
/*============================================================================
* ファイル名 : vibra_control.c
* 規約遵守 : MISRA C:2012 / MISRA C:2023 準拠
*============================================================================*/
#include <stdint.h>
#include <stdbool.h>
#include "reg_timer.h" /* ハードウェア依存のレジスタ定義 */
/* 定数定義(Rule 5.1-5.4: マジックナンバー禁止) */
#define VIBRA_PWM_FREQ_HZ (250u)
#define VIBRA_DUTY_MAX (1000u)
#define VIBRA_DUTY_MIN (0u)
#define VIBRA_DUTY_DEFAULT (300u)
/* 状態管理(Rule 10.1: 列挙型の型安全) */
typedef enum
{
VIBRA_STATE_STOPPED = 0,
VIBRA_STATE_RUNNING = 1
} vibra_state_t;
/* グローバル変数(Rule 8.4: static制限, Rule 18.x: volatileの使用) */
static volatile uint16_t vibra_duty_cycle = VIBRA_DUTY_DEFAULT;
static vibra_state_t vibra_state = VIBRA_STATE_STOPPED;
/* プロトタイプ宣言(Rule 8.2: パラメータ名明示) */
void Vibra_Init(void);
void Vibra_SetIntensity(uint16_t intensity);
void Vibra_Stop(void);
/*----------------------------------------------------------------------------
* 関数: Vibra_SetIntensity
* 概要: 振動強度を設定(0-1000)
*----------------------------------------------------------------------------*/
void Vibra_SetIntensity(uint16_t intensity)
{
uint16_t clamped_duty = intensity;
/* 防御的プログラミング(Rule 14.3: 条件式の明確化) */
if (intensity > VIBRA_DUTY_MAX)
{
clamped_duty = VIBRA_DUTY_MAX;
}
else
{
/* 適切なパスの維持 */
}
if (clamped_duty == VIBRA_DUTY_MIN)
{
Vibra_Stop();
}
else
{
vibra_duty_cycle = clamped_duty;
/* 型変換の明示(Rule 10.3) */
const uint32_t period = (uint32_t)TIMER_PERIOD_REG;
TIMER_COMPARE_REG = (uint16_t)((period * (uint32_t)vibra_duty_cycle) / VIBRA_DUTY_MAX);
if (vibra_state == VIBRA_STATE_STOPPED)
{
TIMER_CONTROL_REG |= TIMER_CONTROL_START_BIT;
vibra_state = VIBRA_STATE_RUNNING;
}
}
}
void Vibra_Stop(void)
{
TIMER_CONTROL_REG &= (uint16_t)(~TIMER_CONTROL_START_BIT);
TIMER_COMPARE_REG = 0u;
vibra_state = VIBRA_STATE_STOPPED;
vibra_duty_cycle = VIBRA_DUTY_MIN;
}
