顯示包含「N9H31」標籤的文章。顯示所有文章
顯示包含「N9H31」標籤的文章。顯示所有文章

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月14日星期二

NK-N9H31A2 開發板:GPIO input

NK-N9H31A2 開發板:GPIO output 中,已經可以控制 LED 亮滅,接下來偵測按鈕並控制 LED 亮滅,關於 GPIO input 的知識可以參考韌體工程師需要懂一點硬體:GPIO 輸入輸出模式與實務應用整理

實驗目的

使用提供的函式偵測板子上的按鈕,按下後 LED 亮,反之則滅掉

使用範例

在官方的 SampleCode 中,找到 GPIO,匯入方式就不再贅述,可以參考上一篇

電路說明
        由於下載下來的範例程式中,對應的腳位不一樣,所以要依照板子上的電路圖稍作調整將程式碼中的按鍵腳位設定改為 PI9 及 PH1
        由於按鍵電路使用外部 pull-up 電阻,未按下時 GPIO 讀到為 1,按下時接地,GPIO 讀到為 0,因此按鍵為 Active Low 設計。
        按鍵狀態最終會反映在 GPIO 的輸入數值中,透過函式讀取即可判斷目前按鍵狀態。
       

程式碼

        以下的程式碼可以直接複製貼上,此篇文章中主要學會使用函式偵測按鍵是否按下的數值,並控制對應的 LED 亮滅,所以將原本官方的程式進行修改,僅保留偵測按鍵及控制 LED 的部分
int main(void)
{
    int32_t i32Err;

    sysDisableCache();
    sysFlushCache(I_D_CACHE);
    sysEnableCache(CACHE_WRITE_BACK);
    sysInitializeUART();

    sysprintf("+-------------------------------------------------+\n");
    sysprintf("|                 GPIO Sample Code                |\n");
    sysprintf("+-------------------------------------------------+\n\n");

    /* Configure Port F10 to output mode and pull-up, LED_1 */
	GPIO_OpenBit(GPIOF, BIT10, DIR_OUTPUT, PULL_UP);
    /* Configure Port I10 to output mode and pull-up, LED_2 */
	GPIO_OpenBit(GPIOI, BIT10, DIR_OUTPUT, PULL_UP);
    
    /* Configure Port I10 to input mode and pull-up, KEY_2 */
	GPIO_OpenBit(GPIOH, BIT1, DIR_INPUT, PULL_UP);
    /* Configure Port I9 to input mode and pull-up, KEY_1 */
	GPIO_OpenBit(GPIOI, BIT9, DIR_INPUT, PULL_UP);

    while (1)
    {
        /* use KEY_1 control LED_1 */
        if (GPIO_ReadBit(GPIOI, BIT9) == 0) /* KEY_1 is push down */
        {
        	GPIO_SetBit(GPIOF, BIT10); /* LED_1 OFF */
        }
        else
        {
            GPIO_ClrBit(GPIOF, BIT10); /* LED_1 ON */
        }
        
        /* use KEY_2 control LED_2 */
        if (GPIO_ReadBit(GPIOH, BIT1) == 0) /* KEY_2 is push down */
        {
        	GPIO_SetBit(GPIOI, BIT10); /* LED_2 OFF */
        }
        else
        {
        	GPIO_ClrBit(GPIOI, BIT10); /* LED_2 ON */
        }
    }
    
//    GPIO_CloseBit(GPIOF, BIT10);
//    GPIO_CloseBit(GPIOI, BIT10);
//    GPIO_CloseBit(GPIOH, BIT1);
//    GPIO_CloseBit(GPIOI, BIT9);

    while(1);
}

函式說明

這裡只針對上面程式使用到的 GPIO 函式說明,更多說明可以參考 gpio.h gpio.c
  • GPIO_OpenBit 
    • 設定單一 GPIO 腳位的模式(port, bit, direction, pull)
  • GPIO_SetBit 
    • 將指定 port 的 bit 驅動為高電位(1)
  • GPIO_ClrBit 
    • 將指定 port 的 bit 驅動為低電位(0)
  • GPIO_CloseBit 
    • 將單一 bit 恢復為預設/關閉狀態
  • GPIO_ReadBit  
    • 讀取偵測到的 GOIO 狀態,高電位(1)低電位(0)

實際效果



程式參考

        Nuvoton 官方 github https://github.com/OpenNuvoton/N9H31_NonOS

延伸閱讀

         

2026年4月13日星期一

NK-N9H31A2 開發板:GPIO output

開發環境建立好之後,當然就是要開始寫程式,那怎麼知道寫的程式碼動作正確運行,就是使用GPIO 控制 LED 燈閃爍啦,這篇文章僅說明腳位輸出控制,不包含中斷,未來會在別的章節進行說明,GPIO 的一些知識可以參考"GPIO 輸入輸出模式與實務應用整理"

實驗目的

透過程式控制板子上的 LED 燈亮面,使用提供的函式

使用範例

在官方的 SampleCode 中,找到 GPIO,匯入方式就不再贅述,可以參考此篇

電路說明

        由於下載下來的範例程式中,對應的腳位不一樣,所以要依照板子上的電路圖稍作調整將程式碼中的腳位設定改為 PI10 及 PF10
        在 N9H31 中,GPIO 控制 LED 的本質是透過設定對應的暫存器位元,而 LED 是否亮起,取決於外部電路的接法(開發板 Active Low)。
N9H31 開發板上的 LED

程式碼

        以下的程式碼可以直接複製貼上,此篇文章中主要學會使用函式控制 LED 亮滅,所以將原本官方的程式進行修改,僅保留控制 LED 的部分
void delay(uint32_t count)
{
	while(count--);
}

int main(void)
{
   sysDisableCache();
   sysFlushCache(I_D_CACHE);
   sysEnableCache(CACHE_WRITE_BACK);
   sysInitializeUART();
   sysprintf("+-------------------------------------------------+\n");
   sysprintf("|                 GPIO Sample Code                |\n");
   sysprintf("+-------------------------------------------------+\n\n");
   /* Configure Port F10 to output mode and pull-up, LED_2 */
	GPIO_OpenBit(GPIOF, BIT10, DIR_OUTPUT, PULL_UP);
   /* Configure Port I10 to output mode and pull-up, LED_1 */
	GPIO_OpenBit(GPIOI, BIT10, DIR_OUTPUT, PULL_UP);
   /* Blink LEDs */
   for (int i = 0; i &lt 10; i++)
   {
       GPIO_SetBit(GPIOF, BIT10);
       GPIO_SetBit(GPIOI, BIT10);
       delay(0xFFFFFF);
       GPIO_ClrBit(GPIOF, BIT10);
       GPIO_ClrBit(GPIOI, BIT10);
       delay(0xFFFFFF);
   }
   GPIO_CloseBit(GPIOF, BIT10);
   GPIO_CloseBit(GPIOI, BIT10);
   sysprintf("  [OK].\n");
   while(1);
}

函式說明

這裡只針對上面程式使用到的 GPIO 函式說明,更多說明可以參考 gpio.h gpio.c
  • GPIO_OpenBit 
    • 設定單一 GPIO 腳位的模式(port, bit, direction, pull)
  • GPIO_SetBit 
    • 將指定 port 的 bit 驅動為高電位(1)
  • GPIO_ClrBit 
    • 將指定 port 的 bit 驅動為低電位(0)
  • GPIO_CloseBit 
    • 將單一 bit 恢復為預設/關閉狀態

實際效果


程式參考

    Nuvoton 官方 github https://github.com/OpenNuvoton/N9H31_NonOS

延伸閱讀






2026年2月27日星期五

NK-N9H31A2 開發板:開發環境建置 (四) NuWriter 下載與 UART 執行驗證

 在上一篇文章中,我們已成功完成 hello 範例的 GCC 編譯。本篇將透過 Nuvoton 官方工具 NuWriter 將程式下載至開發板,並透過 UART 確認程式是否正常執行。

NuWriter

NuWriter 是 Nuvoton 提供的下載工具,支援 DDR、SPI、NAND、eMMC 等模式,可用於將映像檔暫時下載至 DDR 執行,或寫入各類儲存裝置,NuWriter 專案中包含 Driver、Firmware 及 PC Tool 原始碼,本篇僅使用已編譯完成之 PC Tool(Release 版本)。本篇僅使用 DDR/SPRAM 模式進行開發階段的功能驗證。
NuWriter 為 Nuvoton ARM9 MPU 系列(包含 NUC970 / N9H30 / N9H31)共用下載工具,可於官方 GitHub 專案取得:https://github.com/OpenNuvoton/NUC970_NuWriter/tree/master

準備下載檔案

本次使用 hello.bin 進行下載測試。

NuWriter 燒錄步驟

1. 啟動軟體
    下載並解壓縮 NuWriter 原始碼後,在以下路徑找到執行檔
     NUC970_NuWriter-master\NuWriter\NuWriter\Release\NuWriter.exe 

    選擇 N9H31 series 及 N9H31K51FC.ini
2. 設定參數及下載
    選擇DDR/SRAM, address 要設定 0x0,Execute address 使用範例專案預設值(0x0),若使用其他專案請依 linker script 設定為準。
    點擊 Re-Connect, 確認有顯示 Device Connected
    Download and run 點擊 Download

3. 燒錄完成畫面

4. 確認功能 
    這裡使用 Arduino 軟體的 comport 進行確認,可以看到有顯示程式碼的資訊
    UART 設定為 115200, 8N1。

    提醒: 當發生 Disconnect 時,記得重新按一下板子上的重置按鈕或重新上電

為什麼使用 DDR/SPRAM 模式?

DDR/SPRAM 模式會將程式暫時下載至 DDR 記憶體執行,不會寫入 SPI Flash,適合開發階段驗證使用,斷電後程式不會保留。

2026年2月22日星期日

NK-N9H31A2 開發板:開發環境建置 (三) 範例專案導入與編譯測試

完成編譯環境設定後,接下來實際導入 Nuvoton 提供的範例專案進行建置測試。本次以 hello 範例為例,驗證 ARM GNU Toolchain 與 xPack Build Tools 是否能正常運作。

下載範例專案

到官方提供的連結下載範例專案 (此為 Nuvoton 官方 Non-OS 範例專案庫) 
下載到 C 槽並解壓縮,本次以 hello 範例專案作為編譯示範,如下圖。

圖片說明:解壓縮之後


圖片說明:範例專案

匯入專案

1. 在 Eclipse 中選擇 File → Open Projects from File System

2. 選擇 Directory

3. 選擇 sample code 資料夾內的 GCC
    範例專案同時提供 Keil 與 GCC 版本,本篇使用 GCC 版本進行測試。
    詳細路徑 C:\N9H31_NonOS-master\SampleCode\hello\GCC


    畫面會變成下方,點擊 Finish 即可


    專案導入完成後會顯示在左側,將 main.c 展開,點擊工具列的 Build 按鈕進行編譯。


    編譯完成後,Console 視窗應顯示下列訊息
    Build Finished. 0 errors, 0 warnings. 
    同時可在專案的 Release 資料夾中看到 hello.elf 檔案,這代表編譯環境設定正確,GCC 工具鏈與 make 工具運作正常。


    若出現 'arm-none-eabi-gcc: command not found',通常代表 Toolchain 或 xPack 路徑設定錯誤,請重新確認前述的 gcc-arm 或 xPack 路徑有沒有跑掉。

至此,N9H31 的 GCC 編譯環境驗證完成,下一篇將介紹如何將程式下載至開發板並實際執行範例。

NK-N9H31A2 開發板:開發環境建置 (二) ARM GNU Toolchain 與 xPack 設定

上一篇文章中,我們完成了 Eclipse IDE 的安裝與 Workspace 初始化。本篇將設定 Arm GNU Toolchain(arm-none-eabi)與 xPack Windows Build Tools 的路徑,使 Eclipse 能正確呼叫編譯器與 make 工具,完成 N9H31(ARM926EJ-S)專案的建置流程。

資料夾建立

在正式進入設定前,先於 C 槽建立 n9h_tools 資料夾,並在其中建立 gcc-arm 與 build-tools 兩個子資料夾,分別用來存放 Arm GNU Toolchain 與 xPack Windows Build Tools。


ARM GNU Toolchain 安裝與配置

1.下載 Arm GNU Toolchain(arm-none-eabi)
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
因使用 Windows 10 環境,所以選擇 Windows (mingw-w64-i686) zip 版本,如下圖。
下載完成後,將壓縮檔解壓縮至 C:\n9h_tools\gcc-arm 資料夾。

圖片來源:Arm Developer 官方下載頁面

2. 設定 Arm Toolchain 路徑
開啟 Window → Preferences

找到 MCU 的項目,選擇 Global Arm Toolchains Paths 將 Toolchain folder 指向解壓縮後的 Arm GNU Toolchain bin 目錄(該目錄內應包含 arm-none-eabi-gcc.exe)。
詳細路徑 C:\n9h_tools\gcc-arm\arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi\bin
(這部分可以依照個人習慣進行替換)
設定完成後,點選 Apply and Close 套用設定。

xPack Windows Build Tools 安裝與配置

1.下載 xPack
xPack Windows Build Tools 主要提供 make、sh 等 GNU 建置工具,使 Windows 環境能正常執行 Makefile 編譯流程。
找到下圖並選擇 zip ,下載完成後,將壓縮檔解壓縮至 C:\n9h_tools\build-tools 資料夾。

圖片來源:xPack GitHub Releases 頁面
 

2. 設定 xPack Build Tools 路徑
找到 MCU 的項目,選擇 Global Build Tools Path 將 Build tools folder 指向 xPack 的 bin 目錄,Build tools folder 請指定到 xPack 的 bin 目錄(該目錄內應包含 make.exe)。
詳細路徑 C:\n9h_tools\build-tools\xpack-windows-build-tools-4.4.1-3\bin 
修改完之後記得按下 Apply and Close


完成以上兩項設定後,Eclipse 即可正確呼叫 ARM 編譯器與 make 工具,下一篇將示範如何導入範例專案並實際進行編譯測試。

2026年2月20日星期五

NK-N9H31A2 開發板:開發環境建置 (一) Eclipse 安裝

完成驅動程式安裝後,接下來正式進入開發環境建置階段,本篇使用作業系統為 Windows 10。
本系列將說明如何建立適用於 N9H31 (ARM926EJ-S 架構) 的開發環境,包含:
  1. Eclipse IDE 安裝(本篇)
  2. ARM GNU Toolchain 安裝與配置(下一篇)
  3. xPack Windows Build Tools 設定(下一篇)
  4. 範例專案導入與編譯測試(下下一篇)
為什麼選擇 Eclipse?
在 ARM9 架構下,其實工具選擇不像 Cortex-M 那麼多,這次選擇 Eclipse,原因如下:
1. 開源工具鏈完整
Eclipse 為開源 IDE,可搭配 GNU Toolchain,對於裸機或嵌入式 Linux 開發都適用。 

2. Keil MDK 對 ARM9 並非主流支援架構
N9H31 採用 ARM926EJ-S(ARM9 / ARMv5TE)核心。雖然 Nuvoton 提供 Keil 範例專案,但該專案使用的是早期 ARM-ADS 工具鏈(屬於舊版 ARM9 開發環境)。目前 Keil MDK 官方產品定位主要聚焦於 Cortex-M / Cortex-R 架構,並以 Arm Compiler 6 為主流編譯器。ARM9 屬於較舊架構,需搭配舊版工具鏈使用,因此本次環境建置改採 GNU Toolchain + Eclipse。

3. 官方已提供 Eclipse 專案範例
Nuvoton Technology Corporation 官方已提供 Eclipse 範例專案,可直接導入。減少手動建立 linker script、已配置好 startup code、Makefile / build 設定完整,可直接編譯測試。ARM9 與 Cortex-M 不同,需要自行處理 DDR 初始化、MMU 設定、Cache 控制、向量表重定位,若從零開始配置會耗費大量時間。

下載連結
先把所有會用到的連結放在這裡

Eclipse 安裝說明

接下來會逐步引導安裝過程

1.點擊 Eclipse 連結後,進入官方頁面,我們要找到下圖,這裡要強調是 Embedded C/C++ ,並選擇x86

2. 下載之後建議直接在 C 槽解壓縮,避免發生解壓縮失敗

解壓縮之後的樣子,為了讓路徑更單純,將資料夾整包提取直接放到 C 槽路徑底下,如下圖

3. 第一次開啟的樣子
要點這個圖示進行開啟
在這裡我們在 C 槽建立一個給 N9H31 專用的 workspace
過程中如果遇到下圖,點擊允許,主要避免 windows 一直掃描,降低編譯時間

開啟之後的樣子






2026年1月25日星期日

NK-N9H31A2 開發板:驅動程式

有硬體之後就是要準備開發軟體環境,但在正式開始開發前需要先將需要的軟體驅動安裝完備,這篇會說明必要驅動安裝,由於都是一路點擊下一步,這裡提供驅動的網址,就不逐步說明。


開發環境

本文使用系統為 windows 11,不同作業系統可能略有差異

驅動程式

下面三個為主要安裝的驅動連結
CDC driver 功用
Communications Device Class 是 USB 協會制定的一種跨裝置類別,定義 USB 裝置如何模擬成傳統的通訊裝置,有以下三個主要特色。
    1. 通訊協定標準化 規定 USB 傳輸線中,哪些裝置用於傳輸資料,哪些用於傳輸控制訊號
    2. 跨平台相容 因為是標準化規範,現今的作業系統,windows  Linux, macOS 通常有內建此類的驅動,可以直接插上電腦的 USB 孔,就可以偵測到裝置
    3. 硬體抽象化
      對於 MCU 使用者來說,只需要在韌體中實作功能,不用寫複雜的 use 通訊協定 (這功能我也蠻想嘗試看看的,未來在設計板子時就可以省略掉一顆 Usb 轉換 IC 而且通訊傳輸速度更快)
Virtual COM driver 功用
主要功能就是在電腦作業系統中,模擬出一個傳統的序列埠,有些晶片商,在自己的燒錄器上也會有這功能,像是你插上去之後就會有兩個裝置出現,但這功能的好處有以下兩點
    1. 模擬傳統介面(像是 RS232 或是 RS485 等)
    2. 簡化軟體開發,在還沒有準備好完整硬體的時候,可以先模擬指令開發
Nu-Link driver 功用
讓電腦可以支援 keil MDK 或是 IAR 的開發軟體,包含 NuMicro 系列的晶片

安裝完成結果


在電腦裝置管理員中可以看到 NuVCOMDeviceClass 及 COM5(這個可能每個人的不一樣)

Note: 若沒有看到 NuVCOMDeviceClass 檢查板子上的 SW1 開關 PA0 PA1 有沒有調整到 ON


參考資料

https://www.nuvoton.com.cn/export/resource-files/en-us--UM_NuMaker_HMI_N9H31_A1_A2_EN_Rev1.00.pdf

https://www.nuvoton.com/export/resource-files/en-us--RH_Nu-Link_Driver_for_Keil_MDK_EN_V3.21.pdf

https://www.nuvoton.com/tool-and-software/ide-and-compiler/





打賞按讚