“Blinky”を読む

今度はLPC810でテストした”Blinky”を読む。

“Blinky”は次の3つのソースファイルで構成されている。
1. cr_startup_lpc8xx.c
2. crp.c
3. main.c

まずはmain関数のあるmain.cから。

/****************************************************************************
 *   $Id:: blinky.c 3634 2012-10-31 00:09:55Z usb00423                      $
 *   Project: NXP LPC8xx Blinky example
 *
 *   Description:
 *     This file contains LED blink code example which include timer,
 *     GPIO initialization, and clock monitoring.
 *
 ****************************************************************************
略
****************************************************************************/
#ifdef __USE_CMSIS
#include "LPC8xx.h"
#endif


#include "lpc8xx_clkconfig.h"
#include "lpc8xx_gpio.h"
#include "lpc8xx_mrt.h"

extern uint32_t mrt_counter;



/* Main Program */

int main (void) {
  uint32_t regVal;


  SystemCoreClockUpdate();

  /* Config CLKOUT, mostly used for debugging. */
  regVal = LPC_SWM->PINASSIGN8 & ~( 0xFF << 16 );
  LPC_SWM->PINASSIGN8 = regVal | ( 12 << 16 );	/* P0.12 is CLKOUT, ASSIGN(23:16). */
  CLKOUT_Setup( CLKOUTCLK_SRC_MAIN_CLK );

#if 0
	regVal = LPC_SWM->PINASSIGN0 & ~( (0xFF << 0) | (0xFF << 8) );
	LPC_SWM->PINASSIGN0 = regVal | ( (2 << 0) | (3 << 8) );	/* P0.2 is UART0 TX, ASSIGN(7:0); P0.3 is UART0 RX. ASSIGN(15:8). */
#endif

  /* Enable AHB clock to the GPIO domain. */
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

  /* Set port p0.0 to output */
  GPIOSetDir( 0, 0, 1 );

  /* Set port p0.16 to output */
  GPIOSetDir( 0, 16, 1 );

  /* Set port p0.17 to output */
  GPIOSetDir( 0, 17, 1 );

  init_mrt(0x8000);
	
  while (1)                                /* Loop forever */
  {
		/* I/O configuration and LED setting pending. */
		if ( (mrt_counter > 0) && (mrt_counter <= 200) )
		{
			GPIOSetBitValue( 0, 0, 0 );
		}
		if ( (mrt_counter > 200) && (mrt_counter <= 400) )
		{
			GPIOSetBitValue( 0, 0, 1 );
		}
		if ( (mrt_counter > 400) && (mrt_counter <= 600) )
		{
			GPIOSetBitValue( 0, 16, 0 );
		}
		if ( (mrt_counter > 600) && (mrt_counter <= 800) )
		{
			GPIOSetBitValue( 0, 16, 1 );
		}

		if ( (mrt_counter > 800) && (mrt_counter <= 1000) )
		{
			GPIOSetBitValue( 0, 17, 0 );
		}
		if ( (mrt_counter > 1000) && (mrt_counter <= 1200) )
		{
			GPIOSetBitValue( 0, 17, 1 );
		}

		else if ( mrt_counter > 1200 )
		{
			mrt_counter = 0;
		}
  }
}

main関数の頭からざーっと見ていくと、クロックの設定をして、LPC_SWM->PINASSIGN8関連のところはクロックをP0.12ピンに出力する?

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);ここは飛ばして。

GPIOSetDir( 0, 0, 1 );ここでGPIOの入出力を設定。ここではGPIO P0.0ピンを"出力"に設定。

init_mrt(0x8000);ここも飛ばして。

while (1)でループ。
ループ内でmrt_counterの値によってGPIOSetBitValue( 0, 0, 0 );とか、GPIOSetBitValue( 0, 0, 1 );でGPIO P0.0(P0.16, P0.17も)をLOにしたりHIGHにしている。
mrt_counterは1200より大きくなると0にクリアする。

では、さっき飛ばしたinit_mrt(0x8000);の定義を見てみると、lpc800_driver_libプロジェクトの"lpc8xx_mrt.c"で定義されている。
void init_mrt(uint32_t TimerInterval)となっていて、処理内容としてはタイマーを設定していて、インターバルは引数で指定している。

で、同ソースファイルのちょっと上にvoid MRT_IRQHandler(void)が定義されていて、その中で mrt_counterがカウントアップされている。

次はLPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);この行。
SYSAHBCLKCTRLは意味がわからないので、ユーザーズマニュアルを見るとp.36のTable 30にあって、6ビットを1にしているので、GPIOポートレジスタおよびGPIOピン1割り込みレジスタのクロックを有効にしているということ(?)。

と、ここまで読んできてSYSAHBCLKCTRLでググってたら詳しく解説しているサイトを見つけました。
このサンプルでは元々LPC812用でしたが、私のソースコードはLPC810用にGPIO p0.7をp0.0に書き換えています。

この行LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);の意味は、GPIOにクロックを供給することでGPIOが有効になるということのようです。

で、その上のLPC_SWM->PINASSIGN8関連のところは予想通りp0.12ピンにクロックを出力しているようです。
ただし、この機能はデバッグのためのようで、GPIOにクロックを出力する必要性は無いようです。
先のサイトではUARTのページのおまけの項でボード上のLEDが点灯するからくりのところで解説しています。

まぁ、大体の雰囲気はつかめたから"Blinky"はこれで終わり。
次は自分で新しいプロジェクト(I2CでMPU-6050を使う)を作りたい。

カテゴリー: ARM, ソフトウェア パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください