Saturday, July 30, 2016

Using SWO on nRF52

在 Nordic Semiconductor 的產品討論區上,看到有使用者詢問如何使用 SWO 來輸出資訊。在花了一點時間嘗試後,將使用方式記載如下:(原文網址

The following steps showing how to configure the SWO
  1. add the additional define "ENABLE_SWO" to the project setting, which will set the nRF52 P0.18 as SWO instead of been a common GPIO
  2. set the TRACECONFIG register for trace port debug interface; the detail can be found in here. If you are using JLink-OB on the PCA10040, the maximum SWO sampling frequencey is 7.5MHz, so it is needed to configure the TRACEPORTSPEED to 4MHz.
  3. Set the trace enable register and trace control register which in the "Instrumentation Trace Macrocell" to turn on the ITM stimulus
  4. call the ITM_SendChar(uint32_t ch) to transmit the character via ITM channel 0, the detail can be found in the /components/toolchain/CMSIS/Include/core_cm4.h
Sample code:


 #include <stdint.h>  
 #include "nrf.h"  
 int main(void)  
 {  
   // step 2  
   NRF_CLOCK->TRACECONFIG = (NRF_CLOCK->TRACECONFIG & ~CLOCK_TRACECONFIG_TRACEPORTSPEED_Msk) |  
     (CLOCK_TRACECONFIG_TRACEPORTSPEED_4MHz << CLOCK_TRACECONFIG_TRACEPORTSPEED_Pos);  
   // step 3  
   ITM->TCR |= 1;  
   ITM->TER |= 1;  
   uint8_t c = 65;  
   while (true)  
   {  
     // step 4    
     ITM_SendChar(c);  
     if( c >= 90){  
       c = 65;  
     }else{  
       c++;  
     }  
   }  
 }  

After flash the code, execute the JLinkExe and set the SWO speed to 4MHz, then you will see the result on the screen:

 ~$ JLinkExe -if swd -device nrf52 -speed auto  
 JLink>connect  
 JLink>swoview 4000000  
 Receiving SWO data @ 4000 kHz  
 Data from stimulus port 0:  
 --------------------------------------------------------  
 ABCD...  

Using the app_trace module for debug log output in nRF5x SDK

前段時間在 facebook 上看到有人討論 nRF52 的使用以及 SDK 的 debug message log 功能,因此自己寫了一份說明解釋如下:(先簡短記載,再找時間修篇幅)

如果要從UART輸出log的話,以nRF5_SDK_11的gcc的template為例,必須完成以下步驟:
1. 在Makefile確認以下參數
CFLAGS += -DENABLE_DEBUG_LOG_SUPPORT

CFLAGS += -DNRF_LOG_USES_UART=1
ASMFLAGS += -DNRF_LOG_USES_UART=1
(上面兩個通常預設是-DNRF_LOG_USES_RTT=1)

2. 在main.c中有引入app_trace.h,並且有加入app_trace_init()

3. 預設UART輸出log的設定是有流量控制的,可以修改
nRF5_SDK_11/components/libraries/util/nrf_log.c
中的log_uart_init(), 將流量設定改成APP_UART_FLOW_CONTROL_DISABLED

4. 如果發現app_trace_log()只會印出第一個字,需要修正Makefile
(1.)在C_SOURCE_FILES中,移除
../../../../../../components/libraries/uart/app_uart.c \
加入
../../../../../../components/libraries/uart/app_uart_fifo.c \
../../../../../../components/libraries/fifo/app_fifo.c \
(2.)在INC_PATH中加入
INC_PATHS += $(abspath../../../../../../components/libraries/fifo)

Saturday, June 21, 2014

LPC1114FN28的GPIO使用方式

在學習微控制器最基礎的想必是動動I/O接腳, 推個LED燈或是讀取外部按鈕輸入.但經過實驗發現, 改變上次實驗內容的電路圖接法,將LED接至其他GPIO並單純的修改程式碼中的腳位設定,其實是無法直接驅動LED的!
作為一顆32位元的多功能ARM微處理器, 對於GPIO的設定與操作使用自然比較複雜些, 此次的心得將紀錄LPC1114FN28的GPIO使用方式, 以及在datasheet中的相關章節閱讀提示.

元件列表

  1. NXP LPC1114FN28 x 1
  2. 按鈕 x 3
  3. 電阻 330 Ω x 1
  4. 電阻 4.7k Ω x 2
  5. LED x 1

使用工具

  1. USB轉UART轉接線
  2. 3.3V位準電源

電路圖

LPC1114_GPIO_experiment_schematic

電路說明

於本次實驗將LED接至PIO1_0接腳,藉以測試在多功能的IO接腳上如何進行功能的切換;同時將燒錄按鍵PIO0_1作為此次實驗的外部輸入.

操作原理

在這次的實驗中, 希望能夠藉由一組按鈕接腳輸入(PIO0_1)來改變另一組LED接腳(PIO1_0)輸出, 藉以驗證基礎的GPIO功能; 當按鈕按下時, LED燈熄滅, 反之當沒有按下按鈕時, LED啟動.

有別於AVR ATmega系列的8位元微控制器, 以ARM Cortex-M0作為核心的LPC1114內部結構較為複雜些, 對於時脈的掌控更是需要注意; 在LPC1114的使用手冊中第3.4節中, 便提示了有一組名為SYSAHBCLKCTRL的暫存器掌控了所有週邊界面的時脈. 在本次的實驗中需要使用GPIO, 因此在系統啟動時,必須開啟I/O部份的時脈輸入;在手冊3.5.14章節中有對SYSAHBCLKCTRL之內容進行說明, 針對I/O時脈引入的設定在第16位元(IOCON),需將此暫存器內容寫入1:

LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON;

為了達成多種應用, 現今的微控制器需要支援多種界面(peripheral),從一般GPIO,ADC轉換的單一接腳用途,以至於多組接腳所一起組成的通訊界面如SPI,UART,I2C等,加上計數器…如此眾多的功能需要在有限的接腳資源內完成, 想必一定有些接腳是具備多種功能以備切換的,這樣的狀況在LPC1114FN28接腳數較少(Low Pin Count)的封裝中格外明顯.
參閱手冊10.4的Table 168.可發現這次實驗中要連接LED的PIO1_0腳位除了可作為一般數位I/O外, 還能作為A/D類比轉換以及計數器使用. 因此在開始點滅LED前,必須指定該接腳作為一般數位I/O功能:

LPC_IOCON->R_PIO1_0 |= (1 << 0);    //GPIO function select, manual 8.4.29

而按鈕輸入的接腳PIO0_1在預設狀態下便已經是一般數位I/O功能, 此時可設定該接腳內部直接接上上拉電阻(Pull-up resistor), 在未有輸入的狀況下直接測得高位電位; 而透過與一按鈕與電阻串接至地, 可藉由按鈕按下時測得低電位.

 LPC_IOCON->PIO0_1 |= (1 << 4);     //Pull-up enable, manual 8.4.4

在設定完各接腳模式後, 接著需要設定訊號方向; 在手冊的12.3.2節提到有一組GPIO data direction register用來控制GPIO輸入輸出方向的切換,將所需設定腳位的register寫入1即為輸出, 反之0則為輸入.

LPC_GPIO0->DIR |= (1 << 0); //set PIO0_1 to be output
LPC_GPIO1->DIR &= ~(1 << 0);    //set PIO1_0 to be input

完成了接腳方向的設定後, 便可以對輸出腳位輸出高低電位的切換,以及從輸入腳位讀取外部電位資訊; 在此次實驗中的操作非常單純, 透過不斷讀取輸入接腳之按鈕狀態,直接反應在輸出接腳的LED上. 對於接腳資訊的讀取或寫入來自於GPIO data register, 其操作如下:

  LPC_GPIO1->DATA |= (1 << 0);  //write HIGH to PIO1_0
  LPC_GPIO1->DATA &= ~(1 << 0); //write LOW to PIO1_0
  LPC_GPIO0->DATA &= (1 << 1);  //check the state from PIO0_1

綜合以上的所有操作, 主程式簡短如下:
當PIO0_1的按鈕未被按下時, 由於內部已經被設定為Pull High組態, 因此讀取輸入為高電位,並將此狀態直接反應於接於PIO1_0接腳上的LED;反之, 在按鈕被按下時PIO0_1接地,讀取輸入為低電位,亦將此狀態反應於PIO1_0之LED上.

int main(void)
{
        volatile uint32_t count, count_max = 1000000; 
        pll_start(CRYSTAL, FREQUENCY);

        //generate the clock to I/O peripheral
        LPC_SYSCON->SYSAHBCLKCTRL |= SYSAHBCLKCTRL_IOCON;   

        //set PIO1_0 for GPIO function
        LPC_IOCON->R_PIO1_0 |= (1 << 0);    
        //set PIO0_1 with pull high 
        LPC_IOCON->PIO0_1 |= (1 << 4); 

        //set PIO1_0 to be output
        LPC_GPIO1->DIR |= (1 << 0); 
        //set PIO0_1 to be input
        LPC_GPIO0->DIR &= ~(1 << 1);   

        while (1)
        {
                //check the button state on PIO0_1
                if(LPC_GPIO0->DATA &= (1 << 1)){   
                    //turn on the LED on PIO1_0
                    LPC_GPIO1->DATA |= (1 << 0);    
                }else{
                    //turn down the LED
                    LPC_GPIO1->DATA &= ~(1 << 0);   
                }
        }
}

如果接線正常且程式運作順利, 應該在壓下按鍵時LED熄滅, 而在放開按鍵時LED啟動.
enter image description here

Sunday, June 1, 2014

麵包板上的ARM(LPC1114FN28 最簡電路)

每個有點年紀的台灣韌體工程師都不會忘記第一次在麵包版上插出8051電路時那如同初戀的感覺, 但現在已是2014年, 整個市場都在往ARM靠攏, 讓我們也歸順吧!

元件列表

  1. NXP LPC1114FN28 x 1 (ARM Cortex M0, Datasheet)
  2. 按鈕 x 2
  3. 電阻 330 Ω x 1
  4. 電阻 4.7k Ω x 2
  5. LED x 1

使用工具

  1. USB轉UART轉接線
  2. 3.3V位準電源

電路圖

LPC1114 Minimal Circuit

電路說明

  1. VDD需接上3.3V之電源, VSS需接地
  2. Pin 23為系統重置(reset)接腳, 此一接腳為低位準致能,因此需接一4.7k之上拉電阻至正電源, 以維持系統運作; 當需要重置系統時, 可透過一按鈕將此接腳接地.
  3. Pin 24為ISP(In System Programming)燒錄致能接腳,需接上4.7k之電阻串連一組按鈕接地;當此一接腳於晶片reset時處於低電位,將觸發ISP模式作用
  4. Pin 17為PIO1_8, 接上330之限流電阻與LED串接至地, 作為除錯用LED

LPC1114 on a Breadboard

Cable接線說明

使用 USB to 3.3V UART Cable 供電給微控制器,並進行序列通訊.cable有四個杜邦端子頭,VCC, GND, RX, TX;將VCC與GND接至微控制器之VDD與VSS, 將UART的RX接至微控制器的TX、TX接至RX。

軟體環境

使用Linux
- 下載”GNU Tools for ARM Embedded Processors” (Readme.txt)

$ tar -xf gcc-arm-none-eabi-4_8-2014q2-20140609-linux.tar.bz2 
$ sudo mv gcc-arm-none-eabi-4_8-2014q2 /opt/
$ echo "PATH=$PATH:/opt/gcc-arm-none-eabi-4_8-2014q2/bin" >> ~/.bashrc
  • 下載並編譯lpc21isp程式燒錄工具
$ svn checkout svn://svn.code.sf.net/p/lpc21isp/code/ lpc21isp-code
$ cd lpc21isp-code
$ make
$ mkdir -p $HOME/bin && cp lpc21isp $HOME/bin
  • 複製Zuph所修改製作之範例專案
$ git clone git://github.com/Zuph/lpc1114-blink
  • 編譯lpc1114-blink專案
$ cd lpc1114-blink
$ make
 
- 重複檢查電路接線是否正確; 完成後, 先按下RESET不放開, 再按下ISP按鍵, 爾後放開RESET, 再放開ISP按鍵, 進入ISP模式, 輸入下列指令進行燒錄
$ lpc21isp out/*.hex /dev/ttyUSB0 115200 12000 # FILE BAUDRATE CRYSTAL_HZ
  • 若操作正確無誤, 應該可看到LED以1.5Hz的頻率進行閃爍

參考資料

LPC1114FN28 with Open Source Tools