NXP LPC2388の GPIO を以下のとおり検証した。
概要 4つのLEDをTIMER0で点滅させる。
タイマ割り込みハンドラは startup.s で設定されたハンドラ CPU_IRQInterrupt を main() ソースファイルに、準備する。
1.GPIO使用 main()関数側
1)初期設定
GPIO_InitTypeDef GPIO_InitStructure;
// GPIO 0
GPIO_InitStructure.GPIO_ID = GPIO_Port_0;
GPIO_InitStructure.GPIO_Pins = GPIO_Pin_27;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_FAST;
GPIO_InitStructure.GPIO_ModeIO = GPIO_Mode_OUTPUT;
GPIO_InitStructure.GPIO_ModePin = GPIO_ModePin_PULLDOWN;
GPIO_Init(&GPIO_0,&GPIO_InitStructure);
※ システムコントロールレジスタ SCS(0xE01FC1A0) に0x01をセットするとGPIO0,GPIO1はFGPIOに設定されるが、設定の有無による違い未だ実感出来ず。(高速IFが必要にならない限り実感できないと思う。)
2)GPIO出力
GPIO ポート1の18番ピンに1出力 付録基板LED1消燈
GPIO ポート1の19番、22番ピンに0出力 外付けLEDが点灯
GPIO_SetBits(&GPIO_1,GPIO_Pin_18);
GPIO_ResetBits(&GPIO_1, GPIO_Pin_19 GPIO_Pin_22);
2.GPIO使用 LPC用GPIO関数側
1)GPIO設定構造体
typedef struct
{
GPIOPortID_TypeDef GPIO_ID;
u32 GPIO_Pins;
GPIOMode_TypeDef GPIO_Mode;
GPIOModeIO_TypeDef GPIO_ModeIO;
GPIOModePin_TypeDef GPIO_ModePin;
}GPIO_InitTypeDef;
2)GPIO構造体
typedef struct
{
vu32 *pIOPIN;
vu32 *pIOSET;
vu32 *pIODIR;
vu32 *pIOCLR;
vu32 *pFIODIR;
vu32 *pFIOMASK;
vu32 *pFIOPIN;
vu32 *pFIOSET;
vu32 *pFIOCLR;
} GPIO_TypeDef;
EXTERN GPIO_TypeDef GPIO_0;
EXTERN GPIO_TypeDef GPIO_1;
EXTERN GPIO_TypeDef GPIO_2;
EXTERN GPIO_TypeDef GPIO_3;
EXTERN GPIO_TypeDef GPIO_4;
3)関数 GPIO_Init
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
u32 i;
u32 *pPINSEL_H;
u32 *pPINSEL_L;
u32 *pPINMODE_H;
u32 *pPINMODE_L;
vu32 bitpattern;
switch(GPIO_InitStruct->GPIO_ID)
{
case GPIO_Port_0: //ポート0のピン選択レジスタポインタをセット
pPINSEL_L = (u32 *)(PINSEL_BASE_ADDR + 0x00);
pPINSEL_H = (u32 *)(PINSEL_BASE_ADDR + 0x04);
pPINMODE_L = (u32 *)(PINSEL_BASE_ADDR + 0x40);
pPINMODE_H = (u32 *)(PINSEL_BASE_ADDR + 0x44);
break;
case GPIO_Port_1:
pPINSEL_L = (u32 *)(PINSEL_BASE_ADDR + 0x08);
pPINSEL_H = (u32 *)(PINSEL_BASE_ADDR + 0x0c);
///////////////////////////////////////////
default:
return;
}
/* Setting Low Bits . for use GPIO (Bit Patern "00")*/
for(i=0;i<16;i++)
{
if( GPIO_InitStruct->GPIO_Pins & (0x00000001 << i))
{ // ピン選択レジスタの設定 Pin0-15
bitpattern = 0x0000003 << (2*i);
bitpattern ^= 0xFFFFFFFF;
*pPINSEL_L &= bitpattern;
//Bit Clear and Pin use GPIO
*pPINMODE_L &= bitpattern;
//Bit Clear
bitpattern = GPIO_InitStruct->GPIO_ModePin << (2*i);
*pPINMODE_L = bitpattern;
}
}
for(i=0;i<16;i++)
{
if( GPIO_InitStruct->GPIO_Pins & (0x00000001 << (i+16)))
{ // ピン選択レジスタの設定 Pin16-31
bitpattern = 0x0000003 << (2*i);
bitpattern ^= 0xFFFFFFFF;
*pPINSEL_H &= bitpattern;
//Bit Clear and Pin use GPIO
*pPINMODE_H &= bitpattern;
//Bit Clear
bitpattern = GPIO_InitStruct->GPIO_ModePin << (2*i);
*pPINMODE_H = bitpattern;
}
}
if( GPIO_InitStruct->GPIO_Mode == GPIO_Mode_REGACY)
{
switch(GPIO_InitStruct->GPIO_ID)
{ // GPIOレジスタポインタのGPIO構造体への登録
case GPIO_Port_0:
GPIOx->pIOPIN = (u32 *)(GPIO_BASE_ADDR + 0x00);
GPIOx->pIOSET = (u32 *)(GPIO_BASE_ADDR + 0x04);
GPIOx->pIOSET = (u32 *)(GPIO_BASE_ADDR + 0x04);
GPIOx->pIODIR = (u32 *)(GPIO_BASE_ADDR + 0x08); // Pin Control Reg. (0:input 1:output)
GPIOx->pIOCLR = (u32 *)(GPIO_BASE_ADDR + 0x0c); // Output Clear Reg.
break;
case GPIO_Port_1:
GPIOx->pIOPIN = (u32 *)(GPIO_BASE_ADDR + 0x10);
GPIOx->pIOSET = (u32 *)(GPIO_BASE_ADDR + 0x14);
GPIOx->pIODIR = (u32 *)(GPIO_BASE_ADDR + 0x18);
GPIOx->pIOCLR = (u32 *)(GPIO_BASE_ADDR + 0x1c);
break;
default:
return;
}
GPIOx->pFIODIR = NULL;
GPIOx->pFIOMASK = NULL;
GPIOx->pFIOPIN = NULL;
GPIOx->pFIOSET = NULL;
GPIOx->pFIOCLR = NULL;
for(i=0;i<32;i++)
{ // 各ピンの入出力の設定
if( GPIO_InitStruct->GPIO_Pins & (0x00000001 << i))
{
if(GPIO_InitStruct->GPIO_ModeIO == GPIO_Mode_INPUT)
{
bitpattern = 0x0000001 << i;
bitpattern ^= 0xFFFFFFFF;
*(GPIOx->pIODIR) &= bitpattern; // Input Mode bit off
}
else
{
bitpattern = 0x0000001 << i;
*(GPIOx->pIODIR) = bitpattern; // Output Mode bit on
}
}
}
}
else
{
/* Fast GPIO Mode */
switch(GPIO_InitStruct->GPIO_ID)
{ // GPIOレジスタ群のポインタをGPIO構造体へ登録
case GPIO_Port_0:
GPIOx->pFIODIR = (u32 *)(FIO_BASE_ADDR + 0x00); //Pin Control Reg. (0:input 1:output)
pFIOMASK = (u32 *)(FIO_BASE_ADDR + 0x10); //Pin Mask Reg. (0:input 1:output)
GPIOx->pFIOMASK = (u32 *)(FIO_BASE_ADDR + 0x10); //Pin Mask Reg. (0:input 1:output)
GPIOx->pFIOPIN = (u32 *)(FIO_BASE_ADDR + 0x14); // Pin Value Reg.
GPIOx->pFIOSET = (u32 *)(FIO_BASE_ADDR + 0x18); // Output Set Reg.
GPIOx->pFIOCLR = (u32 *)(FIO_BASE_ADDR + 0x1c); // Output Clear Reg.
break;
case GPIO_Port_1:
GPIOx->pFIODIR = (u32 *)(FIO_BASE_ADDR + 0x20);
///////////////////////////////////////////
default:
return;
}
GPIOx->pIOPIN = NULL;
GPIOx->pIOSET = NULL;
GPIOx->pIODIR = NULL;
GPIOx->pIOCLR = NULL;
for(i=0;i<32;i++)
{ // 各ピンの入出力の設定
if( GPIO_InitStruct->GPIO_Pins & (0x00000001 << i))
{
if(GPIO_InitStruct->GPIO_ModeIO == GPIO_Mode_INPUT)
{
bitpattern = 0x0000001 << i;
bitpattern ^= 0xFFFFFFFF;
*(GPIOx->pFIODIR) &= bitpattern; // Input Mode bit off
}
else
{
bitpattern = 0x0000001 << i;
*(GPIOx->pFIODIR) = bitpattern; // Output Mode bit on
}
bitpattern = 0x0000001 << i;
bitpattern ^= 0xFFFFFFFF;
*(GPIOx->pFIOMASK) &= bitpattern; // Mask bit off
}
}
}
return;
}
4)関数 GPIO_SetBits ポート単位でのPin設定
GPIO ポートビットセットレジスタを使い Pinに”1”(High)を設定
void GPIO_SetBits(GPIO_TypeDef* GPIOx, u32 GPIO_Pin)
{
if(GPIOx->pFIOSET != NULL) // FGPIOの判断
{
*(GPIOx->pFIOSET) = GPIO_Pin;
}
else
{
*(GPIOx->pIOSET) = GPIO_Pin;
}
}
5)関数 GPIO_ResetBits ポート単位でのPinクリア
GPIO ポートビットクリアレジスタを使い Pinに”0”(Low)を設定
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, u32 GPIO_Pin)
{
if(GPIOx->pFIOCLR != NULL)
{
*(GPIOx->pFIOCLR) = GPIO_Pin;
}
else
{
*(GPIOx->pIOCLR) = GPIO_Pin;
}
}
3.タイマ設定 main()側
1) タイマ設定および 割り込み設定
/* タイマコントローラへの供給クロック分周設定 */
*CLK_PCLKSEL0 = (*CLK_PCLKSEL0 & 0xfffffff3); /* 1/4 */ /* タイマ0のパラメータ設定 */
*TIMER_T0PR = 0x00000000; /* プリスケール無し */
*TIMER_T0MR0 = 1000000; /* 供給クロック周波数=1秒 */
*TIMER_T0MCR = 0x00000003; /* Match時にTCクリア&割り込み */
*TIMER_T0TCR = 1; /* タイマスタート*/
/* 割り込みコントローラ設定 */
*VIC_IntSelect = *VIC_IntSelect & (~0x10); /* IRQ選択 */
*VIC_IntEnable = *VIC_IntEnable 0x10; /* タイマ0のみ有効 */
/* 割り込み許可 */
CPU_EnableInterrupt();
2)割り込みハンドラ
IRQ割り込みでCALLされるハンドラをTIMER0の割り込みハンドラとして利用。
void CPU_IRQInterrupt(void)
{
if( toggle == 0 ) {
toggle = 1;
***************************************
*TIMER_T0IR =1; /* タイマ割り込みクリア */
}
4.startup.s
ここで IRQ割り込みを登録
CQ出版IF誌のサンプル使用
.text
.extern main
.extern _sp_base
#======================================
# Initialize vectors
#======================================
B _startup
nop
nop
nop
nop
nop
B _IRQ_handle
nop
.org 0x20
.global _startup
_startup:
#IRQ通知を受け取るように設定する
MRS R0, cpsr
eor R0, R0, #0x80
MSR cpsr, R0
#プロセッサモードをIRQモードへ
MRS r1, CPSR
BIC R1, R1, #0x1F
ORR R1, R1, #0x12
MSR CPSR, R1
#例外ハンドラ用スタックを設定
LDR sp, = _exception_sp_base
#プロセッサモードをスーパーバイザモードへ戻す
MRS r1, CPSR
BIC R1, R1, #0x1F
ORR R1, R1, #0x13
MSR CPSR, R1
# スタックを設定
LDR R13,=_sp_base
BL main
.align 0x4
_IRQ_handle:
#例外用スタックにレジスタ退避
STMDB sp!,{r0-r12, r14}
MRS r0, spsr
STMDB sp!, {r0}
bl CPU_IRQInterrupt
#例外用スタックからレジスタ復帰
LDMIA sp!, {r0}
MSR spsr_cf, r0
LDMIA sp!,{r0-r12,r14}
SUBS PC, R14, #4
2009年5月2日土曜日
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿