SAMD21のイベント・ライブラリを作ってみた。
このライブラリはイベント・チャネルの割当管理が主であり、一個のイベント・ジェネレータからのイベント出力を複数のイベント・ユーザーへ送信することができる。(1:n接続)
イベント連携は直書きしてもチャネル固定なら数行で書けるのでライブラリが必要かどうかは微妙な気もしたが、必要な情報がeventsys.hに定義されているためヘッダーを探し回る必要がないという点はメリットかもしれない。
サンプル・スケッチは、XIAOのD9ポートの立下りエッジによりタイマーカウンタTC3にイベントを送信する。TC3のイベントアクション設定がスタートやリトリガーならTC3はカウントを開始する。こういう組み合わせができるというのは意外に便利そうだ。CPUを介さない連携なのでCPUが停止していても機能する点にもメリットを感じる。
だだ、残念なのは、DMAをイベント駆動できるのにDMA経由でIOPORTアクセスができないこと。これができればBit-Bangモードが可能なのに...と思うのは私だけ?
【メソッドの概要】
1 |
void begin(bool gclkreq = false) |
ライブラリを初期化する。
1 |
void end(void) |
ライブラリを終了する。
1 |
EVENTSYS_CHANNEL allocChannel(void) |
イベント・チャネルを割り当てる。
1 |
void releaseChannel(EVENTSYS_CHANNEL ch) |
割り当てたイベント・チャネル(ch)を解放する。
1 |
void addEventUser(EVENTSYS_CHANNEL ch, EVENTSYS_USER user) |
割り当てたイベント・チャネル(ch)にイベント・ユーザー(user)を接続する。
1 |
void setEventGen(EVENTSYS_CHANNEL ch, EVENTSYS_GEN evgen, EVENTSYS_PATH path = EVENTSYS_PATH_ASYNCHRONOUS, EVENTSYS_EDGSEL edgsel = EVENTSYS_EDGSEL_NO_EVT_OUTPUT) |
割り当てたイベント・チャネル(ch)にイベント・ジェネレータ(gen)を接続する。
EVENTSYS_PATHの指定はペリフェラルにより異なるがイベントユーザーにDMAを指定する場合だけEVENTSYS_PATH_RESYNCHRONIZEDを指定し、それ以外は、省略値であるEVENTSYS_PATH_ASYNCHRONOUSのままで良いと思う。たぶん...
1 |
void softwareEvent(EVENTSYS_CHANNEL ch) |
割り当てたイベント・チャネル(ch)にソフトウェアでイベントを発生させる。デバック用くらいにしか使い道がないかも。
1 |
void interrupt(EVENTSYS_CHANNEL ch, EVENTSYS_CALLBACK cb) |
割り当てたイベント・チャネル(ch)の割り込みハンドラ(cb)設定と割り込みを制御する。
1 |
bool isChannelBusy(EVENTSYS_CHANNEL ch) |
割り当てたイベント・チャネル(ch)のビジー・ステータスを取得する。
1 |
bool isUserReady(EVENTSYS_CHANNEL ch) |
割り当てたイベント・チャネル(ch)に接続された全てのイベント・ユーザーがイベント受信可能か確認する。
【サンプル・スケッチ】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include "IOBUS.h" #include "extint.h" #include "eventsys.h" void setup() { GClock::begin(); IOBUS::pinMode(EXTINT_PIN_D9, INPUT_PULLUP); ExtInt::begin(); ExtInt::config(EXTINT_PIN_D9, EXTINT_SENSE_FALL); EVENTSYS_GEN evgen = ExtInt::eventOutput(EXTINT_PIN_D9, true); (TC3のセットアップ処理) EventSys::begin(); EVENTSYS_CHANNEL ch = EventSys::allocChannel(); EventSys::addEventUser(ch, EVENTSYS_USER_TC3); EventSys::setEventGen(ch, evgen); } void loop() { } |
【修正】
2020-05-26
割り込みコールバック関数にEVENT_CHANNEL型引数を追加。
2020-05-24
EVENTSYS_USER型にEVENTSYS_USER_NONEを追加。それにともないaddEventUser()を修正。
【ライブラリ】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
/* eventsys.h - Event System Library for Microchip ATSAMD21 (Cortex®-M0+) Copyright (c) 2020 Sasapea's Lab. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __EVENTSYS_H #define __EVENTSYS_H #include <stdint.h> #include <stdbool.h> #include <sam.h> #include "gclock.h" typedef enum { EVENTSYS_USER_DMAC_CH_0 = EVSYS_ID_USER_DMAC_CH_0, EVENTSYS_USER_DMAC_CH_1 = EVSYS_ID_USER_DMAC_CH_1, EVENTSYS_USER_DMAC_CH_2 = EVSYS_ID_USER_DMAC_CH_2, EVENTSYS_USER_DMAC_CH_3 = EVSYS_ID_USER_DMAC_CH_3, EVENTSYS_USER_TCC0_EV_0 = EVSYS_ID_USER_TCC0_EV_0, EVENTSYS_USER_TCC0_EV_1 = EVSYS_ID_USER_TCC0_EV_1, EVENTSYS_USER_TCC0_MC_0 = EVSYS_ID_USER_TCC0_MC_0, EVENTSYS_USER_TCC0_MC_1 = EVSYS_ID_USER_TCC0_MC_1, EVENTSYS_USER_TCC0_MC_2 = EVSYS_ID_USER_TCC0_MC_2, EVENTSYS_USER_TCC0_MC_3 = EVSYS_ID_USER_TCC0_MC_3, EVENTSYS_USER_TCC1_EV_0 = EVSYS_ID_USER_TCC1_EV_0, EVENTSYS_USER_TCC1_EV_1 = EVSYS_ID_USER_TCC1_EV_1, EVENTSYS_USER_TCC1_MC_0 = EVSYS_ID_USER_TCC1_MC_0, EVENTSYS_USER_TCC1_MC_1 = EVSYS_ID_USER_TCC1_MC_1, EVENTSYS_USER_TCC2_EV_0 = EVSYS_ID_USER_TCC2_EV_0, EVENTSYS_USER_TCC2_EV_1 = EVSYS_ID_USER_TCC2_EV_1, EVENTSYS_USER_TCC2_MC_0 = EVSYS_ID_USER_TCC2_MC_0, EVENTSYS_USER_TCC2_MC_1 = EVSYS_ID_USER_TCC2_MC_1, EVENTSYS_USER_TC3 = EVSYS_ID_USER_TC3_EVU, EVENTSYS_USER_TC4 = EVSYS_ID_USER_TC4_EVU, EVENTSYS_USER_TC5 = EVSYS_ID_USER_TC5_EVU, EVENTSYS_USER_TC6 = EVSYS_ID_USER_TC6_EVU, EVENTSYS_USER_TC7 = EVSYS_ID_USER_TC7_EVU, EVENTSYS_USER_ADC_START = EVSYS_ID_USER_ADC_START, EVENTSYS_USER_ADC_SYNC = EVSYS_ID_USER_ADC_SYNC, EVENTSYS_USER_AC_SOC_0 = EVSYS_ID_USER_AC_SOC_0, EVENTSYS_USER_AC_SOC_1 = EVSYS_ID_USER_AC_SOC_1, EVENTSYS_USER_DAC_START = EVSYS_ID_USER_DAC_START, EVENTSYS_USER_PTC_STCONV = EVSYS_ID_USER_PTC_STCONV, EVENTSYS_USER_NONE = EVENTSYS_USER_PTC_STCONV + 1, } EVENTSYS_USER; typedef enum { EVENTSYS_GEN_NONE = 0, EVENTSYS_GEN_RTC_CMP_0 = EVSYS_ID_GEN_RTC_CMP_0, EVENTSYS_GEN_RTC_CMP_1 = EVSYS_ID_GEN_RTC_CMP_1, EVENTSYS_GEN_RTC_OVF = EVSYS_ID_GEN_RTC_OVF, EVENTSYS_GEN_RTC_PER_0 = EVSYS_ID_GEN_RTC_PER_0, EVENTSYS_GEN_RTC_PER_1 = EVSYS_ID_GEN_RTC_PER_1, EVENTSYS_GEN_RTC_PER_2 = EVSYS_ID_GEN_RTC_PER_2, EVENTSYS_GEN_RTC_PER_3 = EVSYS_ID_GEN_RTC_PER_3, EVENTSYS_GEN_RTC_PER_4 = EVSYS_ID_GEN_RTC_PER_4, EVENTSYS_GEN_RTC_PER_5 = EVSYS_ID_GEN_RTC_PER_5, EVENTSYS_GEN_RTC_PER_6 = EVSYS_ID_GEN_RTC_PER_6, EVENTSYS_GEN_RTC_PER_7 = EVSYS_ID_GEN_RTC_PER_7, EVENTSYS_GEN_EIC_EXTINT_0 = EVSYS_ID_GEN_EIC_EXTINT_0, EVENTSYS_GEN_EIC_EXTINT_1 = EVSYS_ID_GEN_EIC_EXTINT_1, EVENTSYS_GEN_EIC_EXTINT_2 = EVSYS_ID_GEN_EIC_EXTINT_2, EVENTSYS_GEN_EIC_EXTINT_3 = EVSYS_ID_GEN_EIC_EXTINT_3, EVENTSYS_GEN_EIC_EXTINT_4 = EVSYS_ID_GEN_EIC_EXTINT_4, EVENTSYS_GEN_EIC_EXTINT_5 = EVSYS_ID_GEN_EIC_EXTINT_5, EVENTSYS_GEN_EIC_EXTINT_6 = EVSYS_ID_GEN_EIC_EXTINT_6, EVENTSYS_GEN_EIC_EXTINT_7 = EVSYS_ID_GEN_EIC_EXTINT_7, EVENTSYS_GEN_EIC_EXTINT_8 = EVSYS_ID_GEN_EIC_EXTINT_8, EVENTSYS_GEN_EIC_EXTINT_9 = EVSYS_ID_GEN_EIC_EXTINT_9, EVENTSYS_GEN_EIC_EXTINT_10 = EVSYS_ID_GEN_EIC_EXTINT_10, EVENTSYS_GEN_EIC_EXTINT_11 = EVSYS_ID_GEN_EIC_EXTINT_11, EVENTSYS_GEN_EIC_EXTINT_12 = EVSYS_ID_GEN_EIC_EXTINT_12, EVENTSYS_GEN_EIC_EXTINT_13 = EVSYS_ID_GEN_EIC_EXTINT_13, EVENTSYS_GEN_EIC_EXTINT_14 = EVSYS_ID_GEN_EIC_EXTINT_14, EVENTSYS_GEN_EIC_EXTINT_15 = EVSYS_ID_GEN_EIC_EXTINT_15, EVENTSYS_GEN_EIC_EXTINT_16 = EVSYS_ID_GEN_EIC_EXTINT_16, EVENTSYS_GEN_EIC_EXTINT_17 = EVSYS_ID_GEN_EIC_EXTINT_17, EVENTSYS_GEN_DMAC_CH_0 = EVSYS_ID_GEN_DMAC_CH_0, EVENTSYS_GEN_DMAC_CH_1 = EVSYS_ID_GEN_DMAC_CH_1, EVENTSYS_GEN_DMAC_CH_2 = EVSYS_ID_GEN_DMAC_CH_2, EVENTSYS_GEN_DMAC_CH_3 = EVSYS_ID_GEN_DMAC_CH_3, EVENTSYS_GEN_TCC0_OVF = EVSYS_ID_GEN_TCC0_OVF, EVENTSYS_GEN_TCC0_TRG = EVSYS_ID_GEN_TCC0_TRG, EVENTSYS_GEN_TCC0_CNT = EVSYS_ID_GEN_TCC0_CNT, EVENTSYS_GEN_TCC0_MCX_0 = EVSYS_ID_GEN_TCC0_MCX_0, EVENTSYS_GEN_TCC0_MCX_1 = EVSYS_ID_GEN_TCC0_MCX_1, EVENTSYS_GEN_TCC0_MCX_2 = EVSYS_ID_GEN_TCC0_MCX_2, EVENTSYS_GEN_TCC0_MCX_3 = EVSYS_ID_GEN_TCC0_MCX_3, EVENTSYS_GEN_TCC1_OVF = EVSYS_ID_GEN_TCC1_OVF, EVENTSYS_GEN_TCC1_TRG = EVSYS_ID_GEN_TCC1_TRG, EVENTSYS_GEN_TCC1_CNT = EVSYS_ID_GEN_TCC1_CNT, EVENTSYS_GEN_TCC1_MCX_0 = EVSYS_ID_GEN_TCC1_MCX_0, EVENTSYS_GEN_TCC1_MCX_1 = EVSYS_ID_GEN_TCC1_MCX_1, EVENTSYS_GEN_TCC2_OVF = EVSYS_ID_GEN_TCC2_OVF, EVENTSYS_GEN_TCC2_TRG = EVSYS_ID_GEN_TCC2_TRG, EVENTSYS_GEN_TCC2_CNT = EVSYS_ID_GEN_TCC2_CNT, EVENTSYS_GEN_TCC2_MCX_0 = EVSYS_ID_GEN_TCC2_MCX_0, EVENTSYS_GEN_TCC2_MCX_1 = EVSYS_ID_GEN_TCC2_MCX_1, EVENTSYS_GEN_TC3_OVF = EVSYS_ID_GEN_TC3_OVF, EVENTSYS_GEN_TC3_MCX_0 = EVSYS_ID_GEN_TC3_MCX_0, EVENTSYS_GEN_TC3_MCX_1 = EVSYS_ID_GEN_TC3_MCX_1, EVENTSYS_GEN_TC4_OVF = EVSYS_ID_GEN_TC4_OVF, EVENTSYS_GEN_TC4_MCX_0 = EVSYS_ID_GEN_TC4_MCX_0, EVENTSYS_GEN_TC4_MCX_1 = EVSYS_ID_GEN_TC4_MCX_1, EVENTSYS_GEN_TC5_OVF = EVSYS_ID_GEN_TC5_OVF, EVENTSYS_GEN_TC5_MCX_0 = EVSYS_ID_GEN_TC5_MCX_0, EVENTSYS_GEN_TC5_MCX_1 = EVSYS_ID_GEN_TC5_MCX_1, EVENTSYS_GEN_TC6_OVF = EVSYS_ID_GEN_TC6_OVF, EVENTSYS_GEN_TC6_MCX_0 = EVSYS_ID_GEN_TC6_MCX_0, EVENTSYS_GEN_TC6_MCX_1 = EVSYS_ID_GEN_TC6_MCX_1, EVENTSYS_GEN_TC7_OVF = EVSYS_ID_GEN_TC7_OVF, EVENTSYS_GEN_TC7_MCX_0 = EVSYS_ID_GEN_TC7_MCX_0, EVENTSYS_GEN_TC7_MCX_1 = EVSYS_ID_GEN_TC7_MCX_1, EVENTSYS_GEN_ADC_RESRDY = EVSYS_ID_GEN_ADC_RESRDY, EVENTSYS_GEN_ADC_WINMON = EVSYS_ID_GEN_ADC_WINMON, EVENTSYS_GEN_AC_COMP_0 = EVSYS_ID_GEN_AC_COMP_0, EVENTSYS_GEN_AC_COMP_1 = EVSYS_ID_GEN_AC_COMP_1, EVENTSYS_GEN_AC_WIN_0 = EVSYS_ID_GEN_AC_WIN_0, EVENTSYS_GEN_DAC_EMPTY = EVSYS_ID_GEN_DAC_EMPTY, EVENTSYS_GEN_PTC_EOC = EVSYS_ID_GEN_PTC_EOC, EVENTSYS_GEN_PTC_WCOMP = EVSYS_ID_GEN_PTC_WCOMP, } EVENTSYS_GEN; typedef enum { EVENTSYS_EDGSEL_NO_EVT_OUTPUT = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT_Val, EVENTSYS_EDGSEL_RISING_EDGE = EVSYS_CHANNEL_EDGSEL_RISING_EDGE_Val, EVENTSYS_EDGSEL_FALLING_EDGE = EVSYS_CHANNEL_EDGSEL_FALLING_EDGE_Val, EVENTSYS_EDGSEL_BOTH_EDGES = EVSYS_CHANNEL_EDGSEL_BOTH_EDGES_Val, } EVENTSYS_EDGSEL; typedef enum { EVENTSYS_PATH_SYNCHRONOUS = EVSYS_CHANNEL_PATH_SYNCHRONOUS_Val, EVENTSYS_PATH_RESYNCHRONIZED = EVSYS_CHANNEL_PATH_RESYNCHRONIZED_Val, EVENTSYS_PATH_ASYNCHRONOUS = EVSYS_CHANNEL_PATH_ASYNCHRONOUS_Val, } EVENTSYS_PATH; typedef enum { EVENTSYS_INT_EVENTDETECTION = 0, EVENTSYS_INT_OVERRUN = 1, } EVENTSYS_INT; typedef uint32_t EVENTSYS_CHANNEL; typedef void (*EVENTSYS_CALLBACK)(EVENTSYS_CHANNEL, EVENTSYS_INT); #define EVENTSYS_EVD(ch) ((ch) < 8 ? EVSYS_INTENSET_EVD (1 << (ch)) : EVSYS_INTENSET_EVDp8 (1 << ((ch) - 8))) #define EVENTSYS_OVR(ch) ((ch) < 8 ? EVSYS_INTENSET_OVR (1 << (ch)) : EVSYS_INTENSET_OVRp8 (1 << ((ch) - 8))) #define EVENTSYS_CHBUSY(ch) ((ch) < 8 ? EVSYS_CHSTATUS_CHBUSY(1 << (ch)) : EVSYS_CHSTATUS_CHBUSYp8(1 << ((ch) - 8))) #define EVENTSYS_USRRDY(ch) ((ch) < 8 ? EVSYS_CHSTATUS_USRRDY(1 << (ch)) : EVSYS_CHSTATUS_USRRDYp8(1 << ((ch) - 8))) class EventSys { private: static void controlGCLK(EVENTSYS_CHANNEL ch, bool enable) { GClock::control((GCLOCK_ID)(GCLOCK_ID_EVSYS_0 + ch), enable); } static void setCallback(uint8_t no, EVENTSYS_CALLBACK cb); public: static void begin(bool gclkreq = false); static void end(void); static EVENTSYS_CHANNEL allocChannel(void); static void releaseChannel(EVENTSYS_CHANNEL ch); static void addEventUser(EVENTSYS_CHANNEL ch, EVENTSYS_USER user) { if (user != EVENTSYS_USER_NONE) EVSYS->USER.reg = EVSYS_USER_USER(user) | EVSYS_USER_CHANNEL(ch); } static void setEventGen(EVENTSYS_CHANNEL ch, EVENTSYS_GEN evgen, EVENTSYS_PATH path = EVENTSYS_PATH_ASYNCHRONOUS, EVENTSYS_EDGSEL edgsel = EVENTSYS_EDGSEL_NO_EVT_OUTPUT) { if (ch--) { controlGCLK(ch, (path != EVENTSYS_PATH_ASYNCHRONOUS) && (edgsel != EVENTSYS_EDGSEL_NO_EVT_OUTPUT)); EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(ch) | EVSYS_CHANNEL_EVGEN(evgen) | EVSYS_CHANNEL_PATH(path) | EVSYS_CHANNEL_EDGSEL(edgsel); } } static void softwareEvent(EVENTSYS_CHANNEL ch) { if (ch--) { controlGCLK(ch, true); EVSYS->CTRL.reg = EVSYS_CTRL_GCLKREQ; *(volatile uint8_t *)&EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(ch); uint32_t save = EVSYS->CHANNEL.reg; // BUG???: after setEventGen(EVENTSYS_EDGSEL_NO_EVT_OUTPUT) // EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(ch) // | EVSYS_CHANNEL_EVGEN(EVSYS->CHANNEL.bit.EVGEN) // | EVSYS_CHANNEL_PATH(EVENTSYS_PATH_SYNCHRONOUS) // | EVSYS_CHANNEL_EDGSEL(EVENTSYS_EDGSEL_RISING_EDGE); // ////////////////////////////////////////////////////////////// EVSYS->CHANNEL.reg = EVSYS_CHANNEL_CHANNEL(ch) | EVSYS_CHANNEL_EVGEN(EVSYS->CHANNEL.bit.EVGEN) | EVSYS_CHANNEL_PATH(EVENTSYS_PATH_SYNCHRONOUS) | EVSYS_CHANNEL_EDGSEL(EVENTSYS_EDGSEL_RISING_EDGE) | EVSYS_CHANNEL_SWEVT; EVSYS->CHANNEL.reg = save; } } static void interrupt(EVENTSYS_CHANNEL ch, EVENTSYS_CALLBACK cb) { if (ch--) { setCallback(ch, cb); if (cb) EVSYS->INTENSET.reg = EVENTSYS_EVD(ch) | EVENTSYS_OVR(ch); else EVSYS->INTENCLR.reg = EVENTSYS_EVD(ch) | EVENTSYS_OVR(ch); } } static bool isChannelBusy(EVENTSYS_CHANNEL ch) { return ch-- ? (EVSYS->CHSTATUS.reg & EVENTSYS_CHBUSY(ch)) != 0 : false; } static bool isUserReady(EVENTSYS_CHANNEL ch) { return ch-- ? (EVSYS->CHSTATUS.reg & EVENTSYS_USRRDY(ch)) != 0 : false; } }; #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
/* eventsys.cpp - Event System Library for Microchip ATSAMD21 (Cortex®-M0+) Copyright (c) 2020 Sasapea's Lab. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <string.h> #include "eventsys.h" static uint32_t _channels; static EVENTSYS_CALLBACK _callback[EVSYS_CHANNELS]; #define INTFLAG_MASK (EVSYS_INTFLAG_EVD_Msk | EVSYS_INTFLAG_EVDp8_Msk | EVSYS_INTFLAG_OVR_Msk | EVSYS_INTFLAG_OVRp8_Msk) void EVSYS_Handler(void) { for (EVENTSYS_CHANNEL i = 0; (i < EVSYS_CHANNELS) && (EVSYS->INTFLAG.reg & INTFLAG_MASK); ++i) { uint32_t evd = EVENTSYS_EVD(i); uint32_t ovr = EVENTSYS_OVR(i); if (EVSYS->INTFLAG.reg & evd) { EVSYS->INTFLAG.reg = evd; if (_callback[i]) _callback[i]((EVENTSYS_CHANNEL)(i + 1), EVENTSYS_INT_EVENTDETECTION); } if (EVSYS->INTFLAG.reg & ovr) { EVSYS->INTFLAG.reg = ovr; if (_callback[i]) _callback[i]((EVENTSYS_CHANNEL)(i + 1), EVENTSYS_INT_OVERRUN); } } } void EventSys::setCallback(uint8_t no, EVENTSYS_CALLBACK cb) { _callback[no] = cb; } void EventSys::begin(bool gclkreq) { PM->APBCMASK.bit.EVSYS_ = 1; EVSYS->CTRL.reg = EVSYS_CTRL_SWRST; if (gclkreq) EVSYS->CTRL.reg = EVSYS_CTRL_GCLKREQ; NVIC_EnableIRQ(EVSYS_IRQn); NVIC_SetPriority(EVSYS_IRQn, 0); memset(_callback, 0, sizeof(_callback)); _channels = 0; } void EventSys::end(void) { if (PM->APBCMASK.bit.EVSYS_) { NVIC_DisableIRQ(EVSYS_IRQn); EVSYS->CTRL.reg = EVSYS_CTRL_SWRST; PM->APBCMASK.bit.EVSYS_ = 0; } } EVENTSYS_CHANNEL EventSys::allocChannel(void) { uint32_t b = 1; for (EVENTSYS_CHANNEL i = 0; i < EVSYS_CHANNELS; ++i, b <<= 1) { if ((_channels & b) == 0) { _channels |= b; return i + 1; } } return 0; } void EventSys::releaseChannel(EVENTSYS_CHANNEL ch) { if (ch) { interrupt(ch, 0); setEventGen(ch, EVENTSYS_GEN_NONE, EVENTSYS_PATH_SYNCHRONOUS, EVENTSYS_EDGSEL_NO_EVT_OUTPUT); // release users for (uint32_t user = EVENTSYS_USER_DMAC_CH_0; user <= EVENTSYS_USER_PTC_STCONV; ++user) { *(volatile uint8_t *)&EVSYS->USER.reg = EVSYS_USER_USER(user); if (EVSYS->USER.bit.CHANNEL == ch) EVSYS->USER.reg = EVSYS_USER_USER(user) | EVSYS_USER_CHANNEL(0); } controlGCLK(ch - 1, false); setCallback(ch, 0); _channels &= ~(1 << (ch - 1)); } } |
【参照ライブラリ】
Seeeduino XIAO (ATSAMD21G18) のGCLKライブラリ (gclock.h/gclock.cpp)