LPC810メモ:pattern match engine
pattern match engineを試す。
pattern match engineは、前に試したpin interruptsを高度化したような機能であり、単独のpinでなく複数pinの状態の組み合わせで割り込みを発生させる。
前提とする環境はこちら→LPC810メモ 共通の準備
- pattern match engineは概略こんな感じ。
- 0-7番の8つの「slice」を定義できる。
- 各sliceでは、のpinから入力するか、どういう条件に反応するか(rising edgeとか、HIGH levelである、とか)を設定する。
- 連続した複数のsliceの条件が、endpointのsliceまですべて成立すれば、割り込み発生。
- このイメージは、「UM10601 8.5.2 Pattern match engine」のFig8,Fig9あたりをじっくり眺めていると理解できる。
- 例) slice0を1番pinのrising edge、slice1を2番pinのrising edgeに設定して、slice1がendpointとすると、「1番pinと2番pinのrising edgeがそれぞれ1回づつあったら」割り込み発生。
- 本例の動作
- 1,2,3,4番pinに、押すとLOWになるpushボタンがそれぞれついている。それぞれボタン1,2,3,4と呼ぶ。
- ボタン1,2,3,4を任意の順番で1回づつ押すと、LED点灯。これをslice0,1,2,3で実現。
- ボタン1,3,を押下、ボタン2,4を離した状態になると、LED消灯。これをslice4,5,6,7で実現。
サンプルコード
#include "LPC8xx.h" int main(void) { // GPIOの設定 8番pinを出力に設定して消灯しておく // (pattern matchとは直接関係ない) LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); LPC_GPIO_PORT->DIR0 |= (1<<0); LPC_GPIO_PORT->CLR0 |= (1<<0); // SWMの設定 // 固定pin機能をreset含めて無効化 // (pattern matchとは直接関係ない) LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); LPC_SWM->PINENABLE0 = 0xffffffffUL; // (pin interruptではなく)pattern matchを利用する旨の設定 // UM10601 8.6.11 Pattern Match Interrupt Control Register LPC_PIN_INT->PMCTRL |= (1 << 0); // 各pinをpattern matchの入力に設定 // 4.6.27 Pin interrupt select registers LPC_SYSCON->PINTSEL[0] = 5; // PIO0_5(1番pin)をPINTSEL0に設定 LPC_SYSCON->PINTSEL[1] = 4; // PIO0_4(2番pin)をPINTSEL1に設定 LPC_SYSCON->PINTSEL[2] = 3; // PIO0_3(3番pin)をPINTSEL2に設定 LPC_SYSCON->PINTSEL[3] = 2; // PIO0_2(4番pin)をPINTSEL3に設定 // 各sliceにどのPINTSELを割り当てるか設定 // 8.6.12 Pattern Match Interrupt Bit-Slice Source register LPC_PIN_INT->PMSRC = (0 << 8) // slice0にPINTSEL0(1番pin)を設定 | (1 << 11) // slice1にPINTSEL1(2番pin)を設定 | (2 << 14) // slice2にPINTSEL2(3番pin)を設定 | (3 << 17) // slice3にPINTSEL3(4番pin)を設定 | (0 << 20) // slice4にPINTSEL0(1番pin)を設定 | (1 << 23) // slice5にPINTSEL1(2番pin)を設定 | (2 << 26) // slice6にPINTSEL2(3番pin)を設定 | (3 << 29) // slice7にPINTSEL3(4番pin)を設定 ; // 各sliceの条件を設定 // 8.6.13 Pattern Match Interrupt Bit Slice Configuration register LPC_PIN_INT->PMCFG = (0x2 << 8) // CFG0 = 0x2 slice0(1番pin)のfalling edge | (0x2 << 11) // CFG1 = 0x2 slice1(2番pin)のfalling edge | (0x2 << 14) // CFG2 = 0x2 slice2(3番pin)のfalling edge | (0x2 << 17) // CFG3 = 0x2 slice3(4番pin)のfalling edge | (1 << 3) // PROD_ENDPTS3 = 1 slice3をendpointとする。 // 以上合わせて、「1,2,3,4番pinの押下(falling edge)が各1回づつあったら割り込み発生」となる。 | (0x5 << 20) // CFG4 = 0x5 slice4(1番pin)がLow leel | (0x4 << 23) // CFG5 = 0x4 slice5(2番pin)がHigh leel | (0x5 << 26) // CFG6 = 0x5 slice6(3番pin)がLow leel | (0x4 << 29) // CFG7 = 0x4 slice7(4番pin)がHigh leel // 以上合わせて、「1,3番pinが押された状態(Low)、2,4番pinが押されてない状態(High)で // 割り込み発生」となる。 // ちなみに、slice7はデフォルトでend pointなので、end pointの設定は不要 ; // slice3と7の割り込み有効化。 // UM10601 3.3.1 Interrupt sources NVIC->ISER[0] = (0x1 << 27) | (0x1 << 31); return 0 ; } extern "C" { // slice3に対応する割り込みハンドラ。 // cr_startup_lpc8xx.cpp で定義されている名称。 void PININT3_IRQHandler(void) { // 割り込みをクリア // UM10601 8.6.13 Pattern Match Interrupt Bit Slice Configuration register // のRemarkより、SEL_PMATCHをclear(して、再度set) LPC_PIN_INT->PMCTRL &= ~0x1; LPC_PIN_INT->PMCTRL |= 0x1; // LED(8番pin)点灯 LPC_GPIO_PORT->SET0 |= (1<<0); } // slice7に対応する割り込みハンドラ。 void PININT7_IRQHandler(void) { // 割り込みをクリア LPC_PIN_INT->PMCTRL &= ~0x1; LPC_PIN_INT->PMCTRL |= 0x1; // LED(8番pin)消灯 LPC_GPIO_PORT->CLR0 |= (1<<0); } }
接続
- 1,2,3,4番pinはそれぞれとりあえず3kΩでpull upしてあり、それぞれプッシュボタンを押すとLOWになるようにつないである
- LEDは8番pin
- 6,7番pin(Vdd,GND)は0.1μFのコンデンサ。
補足/雑感
- UM10601の「8.5.2 Pattern match engine」とか「8.7.2 Pattern Match engine example」とかを最初に読んだ時に、かなり柔軟なbool式を構成できるのかと誤解。なぜそんな事ができるのかわからず混乱。
- 「UM10601 8.5.2 Pattern match engine」のFig8,Fig9を眺めて、基本的には連続するsliceをAND接続するだけということに気づいてからは理解早かった。
- これをもって、当初試したいと思っていたLPC810の機能は全部試せた。3ヶ月くらいかかった。まだ初心者脱却を達成したとは思わないが、かなり勉強にはなったと思う。
- せっかくなので成果をまとめたいところ。