2026年8月2日星期日

AES 加密演算法介紹(一):基本概念、規格與常見模式

 AES (Advanced Encryption Standard)

一、AES 是什麼

  • 對稱式加密
  • 區塊加密
  • 加密與解密使用同一把 Key
  • AES 本身不是 Hash,也不是 MAC
  • AES 本身只提供區塊加密能力,實際應用還需要搭配運作模式

     AES 是一種對稱式區塊加密演算法,主要用途是將可以直接閱讀的明文(Plaintext)轉換成無法直接理解的密文(Ciphertext)。持有正確金鑰的一方,才能再將密文解密回原始明文。

二、基本規格

  •     主要有以下三種,差異為金鑰長度及計算幾輪

AES 類型
Key 長度
Key 大小
Round 數
AES-128
128 bits
16 bytes
10
AES-192
192 bits
24 bytes
12
AES-256
256 bits
32 bytes
14

    •     無論使用 AES-128、AES-192 或 AES-256,AES 的區塊大小(Block Size)都固定為 128 bits,也就是 16 bytes。
    • AES-128、AES-192 與 AES-256 中的數字代表的是 Key Size,不是 Block Size。

    三、AES 核心輸入與輸出介面

    加密 AES_Encrypt(Key, PlaintextBlock) → CiphertextBlock

    解密 AES_Decrypt(Key, CiphertextBlock) → PlaintextBlock

    PlaintextBlock:16 bytes
    CiphertextBlock:16 bytes
    Key:16、24 或 32 bytes

     

    為什麼需要運作模式

    當資料長度為 100 bytes 時,AES Core 一次只能處理 16 bytes,所以需要規則決定

      • 如何分割資料
      • Block 之間如何連接
      • 是否需要 Padding
      • 是否需要 IV 或 Nonce
      • 是否驗證資料完整性
    五、AES 的五種常見模式

    模式
      完整性/認證   IV/Nonce/Counter    明文 Padding
    ECB
    否               不需要通常需要 
    CBC
    否               IV通常需要 
    CTR
    否               Counter Block不需要   
    GCM
      是,使用 Tag       IV/Nonce不需要   
    CCM
    是,使用 Tag       Nonce不需要   

        補充:Counter Block 通常由 Nonce 與遞增的 Counter 組成,詳細結構將於第五篇介紹。

    AES 的常見用途

    • HTTPS/TLS
    • VPN
    • Wi-Fi
    • 硬碟加密
    • 加密韌體映像
    • 安全韌體更新
    • 嵌入式系統
    • PSA Crypto
    • 金鑰儲存與資料保護
    七、小結

    AES 是一種對稱式區塊加密演算法,每次固定處理一個 128-bit,也就是 16-byte 的資料區塊。AES 支援 128、192 與 256-bit 三種金鑰長度,分別執行 10、12 與 14 輪核心運算。由於 AES Core 本身一次只能處理一個 Block,因此實際處理多個資料區塊或任意長度資料時,還需要搭配 ECB、CBC、CTR、GCM 或 CCM 等運作模式。下一篇將進一步介紹 AES Core 內部的主要運算流程。





    2026年5月4日星期一

    NK-N9H31A2 開發板:ETIMER

    在 Timer 這篇中已介紹相關基本觀念,本篇將配合實際範例進行操作,使用 N9H31 的 ETIMER 控制 LED 定時閃爍,並透過 UART 輸出訊息。
    本範例以官方提供的 ETIMER_Periodic 為基礎進行修改。原始範例僅透過 UART 輸出計數秒數,未對應到開發板上的 LED,因此本篇額外加入 GPIO 控制,使 LED 能夠呈現固定週期的亮滅。
    同時,透過 serial port tool(例如 Arduino Serial Monitor)觀察 UART 訊息時間戳記,可進一步驗證 Timer 的實際運作頻率。

    實驗目的

    透過 Timer 定時觸發中斷:
    • 控制 LED 週期性亮滅
    • 透過 UART 輸出訊號,觀察時間間隔

    使用範例

    官方範例 ETIMER_Periodic

    程式碼

    核心概念:Timer 週期性產生中斷 → CPU 進入 ISR → 在 ISR 中控制 LED 並輸出 UART 訊息。

    範例是基於 Nuvoton 官方 Sample Code(ETIMER_Periodic)進行修改,
    僅作為學習與教學用途,以下為修改後的範例程式:
    
    static int state = 0;
    
    /**
     * ETIMER0 interrupt handler. Toggle LED state and print message every time timer timeout.
     */
    void ETMR0_IRQHandler(void)
    {
    	ETIMER_ClearIntFlag(0);
    
    	if (state)
    	{
    		/* LED ON */
    		outpw(REG_GPIOF_DATAOUT, inpw(REG_GPIOF_DATAOUT) & ~BIT10);
    		outpw(REG_GPIOI_DATAOUT, inpw(REG_GPIOI_DATAOUT) & ~BIT10);
    		state = 0;
    		sysprintf("H\n");
    	}
    	else
    	{
    		/* LED OFF */
    		outpw(REG_GPIOF_DATAOUT, inpw(REG_GPIOF_DATAOUT) | BIT10);
    		outpw(REG_GPIOI_DATAOUT, inpw(REG_GPIOI_DATAOUT) | BIT10);
    		state = 1;
    		sysprintf("L\n");
    	}
    }
    
    /*-----------------------------------------------------------------------------*/
    int main(void)
    {
    	sysDisableCache();
    	sysFlushCache(I_D_CACHE);
    	sysEnableCache(CACHE_WRITE_BACK);
    	sysInitializeUART();
    
    	sysprintf("\nETIMER0 periodic + LED toggle test\n");
    
    	/* Enable ETIMER0 clock */
    	outpw(REG_CLK_PCLKEN0, inpw(REG_CLK_PCLKEN0) | (1 << 4));
    
    	/* Enable GPIO clock */
    	outpw(REG_CLK_PCLKEN0, inpw(REG_CLK_PCLKEN0) | (1 << 3));
    
    	/* PF10 PI10 set as GPIO function */
    	outpw(REG_SYS_GPF_MFPH, inpw(REG_SYS_GPF_MFPH) & ~(0xF << 8));
    	outpw(REG_SYS_GPI_MFPH, inpw(REG_SYS_GPI_MFPH) & ~(0xF << 8));
    
    	/* PF10 PI10 set as output */
    	outpw(REG_GPIOF_DIR, inpw(REG_GPIOF_DIR) | BIT10);
    	outpw(REG_GPIOI_DIR, inpw(REG_GPIOI_DIR) | BIT10);
    
    	/* PF10 PI10 initial low */
    	outpw(REG_GPIOF_DATAOUT, inpw(REG_GPIOF_DATAOUT) & ~BIT10);
    	outpw(REG_GPIOI_DATAOUT, inpw(REG_GPIOI_DATAOUT) & ~BIT10);
    
    	/* Set timer frequency to 1Hz */
    	ETIMER_Open(0, ETIMER_TOGGLE_MODE, 1);
    
    	/* Enable timer interrupt */
    	ETIMER_EnableInt(0);
    	sysInstallISR(HIGH_LEVEL_SENSITIVE | IRQ_LEVEL_1, ETMR0_IRQn, (PVOID)ETMR0_IRQHandler);
    	sysSetLocalInterrupt(ENABLE_IRQ);
    	sysEnableInterrupt(ETMR0_IRQn);
    
    	/* Start Timer 0 */
    	ETIMER_Start(0);
    
    	while (1)
    		;
    }
    
    補充說明:本範例同時控制 PF10 與 PI10,因為開發板上分別對應兩顆 LED。透過 Timer 中斷同時切換兩個 GPIO,可快速驗證 Timer 與中斷機制是否正常運作。

    函式說明

    ETIMER_Open(timerNo, mode, freq)
    • 設定 Timer 的運作模式與目標頻率。
    • 設定 Timer mode(One-shot / Periodic / Continuous / Toggle)
    • 自動計算 prescaler 與 compare value
    • 回傳實際可達到的頻率(可能略有誤差)
    注意:此函式不會啟動 Timer,需搭配 ETIMER_Start()


    ETIMER_EnableInt(timerNo)
        啟用 Timer 中斷功能。

    sysInstallISR(level, irq, handler)
        註冊中斷服務函式(ISR)
     將 interrupt source 對應到 handler

    sysSetLocalInterrupt(ENABLE_IRQ)
    啟用 CPU 層級中斷(全域開關)

    sysEnableInterrupt(irq)
    啟用中斷控制器(AIC)中的指定 IRQ

    ETIMER_Start(timerNo)
    啟動 Timer 計數


    ETIMER_ClearIntFlag(timerNo)
    清除 Timer 中斷旗標

    ETMR0_IRQHandler()
    • Timer 中斷服務函式(ISR)
    • 要處理的事情
    目前流程:清除中斷旗標 -> 執行應用邏輯(toggle LED + UART 輸出)
    原則:保持簡短 避免阻塞

    Timer 中斷的觸發需要同時啟用:
    1. Timer 中斷功能(ETIMER_EnableInt)
    2. 中斷控制器(sysEnableInterrupt)
    3. CPU 中斷(sysSetLocalInterrupt)

    三者缺一不可。

    實驗結果


    2026年4月26日星期日

    韌體工程師需要懂一點硬體:Timer 計時器概念與實務應用

    在嵌入式系統中,有一個幾乎無所不在、卻常常被低估的重要模組,就是 Timer(計時器)。無論是最基本的 LED 閃爍、系統運行時間統計,還是進階的 PWM 控制與週期性任務排程,都離不開 Timer 的運作。很多時候,我們在撰寫韌體時,只是「把 Timer 設起來讓它動」,但當遇到計時不準、頻率錯誤,或是系統行為異常時,才發現問題往往不是出在程式邏輯,而是對底層硬體運作理解不夠深入。

    其實,Timer 的本質並不複雜,可以把它想像成一個搭配時脈(Clock)運作的計數器,就像日常生活中的碼表或鬧鐘一樣:時脈提供節奏,計數器負責累積,當達到某個條件時觸發對應的行為。

    本篇文章將從硬體角度出發,說明 Timer 的基本運作原理、時脈來源與計時概念,並整理實務上常見的計時誤差原因,幫助韌體工程師建立更扎實的底層觀念,為後續實際應用(如 MCU Timer 設定與範例)打下基礎。



    一、計時器使用概念

    計時器的運作方式主要可以分為幾種基本模式:
    • 上數(Up Counter):從 0 開始累加,直到達到設定值
    • 下數(Down Counter):從設定值開始往下遞減至 0
    當計數器達到指定條件時,通常會觸發事件(例如中斷或輸出變化),並依設定進行:
    • 自動重載(Auto-reload):計數器自動回到初始值,持續週期性運作
    • 單次模式(One-shot):計數完成後停止

    二、時間誤差觀念

    Timer 的精準度取決於其時脈來源(Clock Source),而這些時脈通常來自實體振盪器(如晶振或內部 RC 振盪器),本質上仍會存在微小誤差,這些誤差在短時間內幾乎難以察覺,但隨著時間累積,可能會逐漸放大。例如:每秒僅有極小誤差,長時間運行後,可能累積成數秒甚至數分鐘的偏差。


        Timer 的誤差主要來自於「時脈穩定性」,而時脈又會受到晶振品質、溫度與電壓變動影響。
        常見誤差來源
    1. 晶振誤差(Frequency tolerance)
    2. 溫度影響(Temperature drift)
    3. 電壓變動(Voltage variation)

    小故事

    小時候,不論是指針式還是數位手錶,為了能夠準確掌握下課鐘聲,總會特別把時間對準。當鐘聲響起的那一刻,按下調整鍵,讓手錶與鐘聲同步,開始下一堂課休息的倒數。

    而現在的手錶,多半支援 Wi-Fi 或藍牙,可以自動與網路時間同步,不需要再手動校正,也大幅降低了時間誤差累積的問題。



    三、如何減少誤差

    在這個部分首先要釐清問題的種類,因為 Timer 的誤差並不是單一原因造成,也沒有一種方法可以套用在所有情境。在實務上,應先判斷應用需求,再選擇合適的改善方式。以下常見分為三類

        案例一、低精度週期應用

        這類應用通常不需要高精度時間,只要大致週期正確即可 ex. LED / Timeout / 簡單週期 。

        常見問題:
    • Timer 設定錯誤(clock / prescaler)
    • ISR 執行時間過長
        建議作法:
    • 確認 clock source 與分頻設定正確
    • ISR 僅執行必要操作
    • 避免使用 printf 或大量運算
        誤差在可接受範圍內即可,不需過度設計

        案例二、長時間計時(RTC / System Time)

        這類的應用主要是時間的長時間累積而導致的誤差

        建議作法:
    • 使用精度較高的晶振(Crystal / TCXO)
    • 避免極端溫度與電壓變化
    • 長時間運作時,定期校正時間
    • 使用時間校正機制(如 RTC、NTP)
        問題不在短時間,而是在「累積」

        案例三、高穩定波形輸出(PWM)

        PWM 的問題通常不是「慢慢偏掉」,而是「瞬間不穩定」,特別是在使用 Software PWM(透過 Timer interrupt 控制)時:
        常見問題:
    • ISR 執行時間不固定
    • 中斷延遲(latency)
    • Duty cycle 抖動(jitter)
        建議作法:
    • 優先使用硬體 PWM 模組
    • 減少 ISR 執行時間
    • 避免在 ISR 中做複雜運算
    • 使用示波器確認實際波形
    • 確認操作 PWM 硬體的流程
        PWM 不準通常是「抖動問題」,不是 ppm 誤差


    結語

    Timer 看似只是簡單的計數器,但其準確度與穩定性,實際上取決於時脈來源、硬體設計與韌體使用方式,在不同應用情境下,應選擇合適的設計策略,才能在精度與系統負擔之間取得平衡。

    打賞按讚