概要
前回はADCで今回はI2Cの予定でしたが、I2Cがうまく動きません。アドレススキャンと限定的な読み出しまではできましたが、まだまだ実用レベルには達していません。そこで割り込み関係の調査とEVTのファイル構成を確認したいと思います。
CH32Vでの割り込みについて
CH32VはSTM32のアーキテクチャを参考にしているのでSTM32に非常によくにています。ただしSTM32はCubeIDEなどである程度設定を自動生成してくれるのですが、CH32Vはすべて自力でする必要があり、いろいろ面倒な感じになっています。
CH32Vシリーズでの割り込み一覧
IT | Note |
---|---|
ADC_IRQHandler | ADC |
ADC1_IRQHandler | ADC1 |
ADC1_2_IRQHandler | ADC1_2 |
AWU_IRQHandler | Auto Wake up |
BB_IRQHandler | BLE BB |
LLE_IRQHandler | BLE LLE |
CAN1_RX1_IRQHandler | CAN1 RX1 |
CAN1_SCE_IRQHandler | CAN1 SCE |
CAN2_RX0_IRQHandler | CAN2 RX0 |
CAN2_RX1_IRQHandler | CAN2 RX1 |
CAN2_SCE_IRQHandler | CAN2 SCE |
CAN2_TX_IRQHandler | CAN2 TX |
CMPWakeUp_IRQHandler | CMP Wake Up |
DMA1_Channel1_IRQHandler | DMA1 Channel 1 |
DMA1_Channel2_IRQHandler | DMA1 Channel 2 |
DMA1_Channel3_IRQHandler | DMA1 Channel 3 |
DMA1_Channel4_IRQHandler | DMA1 Channel 4 |
DMA1_Channel5_IRQHandler | DMA1 Channel 5 |
DMA1_Channel6_IRQHandler | DMA1 Channel 6 |
DMA1_Channel7_IRQHandler | DMA1 Channel 7 |
DMA1_Channel8_IRQHandler | DMA1 Channel 8 |
DMA2_Channel1_IRQHandler | DMA2 Channel 1 |
DMA2_Channel2_IRQHandler | DMA2 Channel 2 |
DMA2_Channel3_IRQHandler | DMA2 Channel 3 |
DMA2_Channel4_IRQHandler | DMA2 Channel 4 |
DMA2_Channel5_IRQHandler | DMA2 Channel 5 |
DMA2_Channel6_IRQHandler | DMA2 Channel 6 |
DMA2_Channel7_IRQHandler | DMA2 Channel 7 |
DMA2_Channel8_IRQHandler | DMA2 Channel 8 |
DMA2_Channel9_IRQHandler | DMA2 Channel 9 |
DMA2_Channel10_IRQHandler | DMA2 Channel 10 |
DMA2_Channel11_IRQHandler | DMA2 Channel 11 |
DVP_IRQHandler | DVP |
ETH_IRQHandler | ETH |
ETH_WKUP_IRQHandler | ETH WakeUp |
ETHWakeUp_IRQHandler | ETHWakeUp |
EXTI0_IRQHandler | EXTI Line 0 |
EXTI1_IRQHandler | EXTI Line 1 |
EXTI2_IRQHandler | EXTI Line 2 |
EXTI3_IRQHandler | EXTI Line 3 |
EXTI4_IRQHandler | EXTI Line 4 |
EXTI9_5_IRQHandler | EXTI Line 9..5 |
EXTI15_10_IRQHandler | EXTI Line 15..10 |
EXTI7_0_IRQHandler | EXTI Line 7..0 |
EXTI15_8_IRQHandler | EXTI Line 15..8 |
EXTI25_16_IRQHandler | EXTI Line 25..16 |
FLASH_IRQHandler | Flash |
I2C1_ER_IRQHandler | I2C1 Error |
I2C1_EV_IRQHandler | I2C1 Event |
I2C2_ER_IRQHandler | I2C2 Error |
I2C2_EV_IRQHandler | I2C2 Event |
LPTIM_IRQHandler | LPTIM |
LPTIMWakeUp_IRQHandler | LPTIM Wake up |
OPA_IRQHandler | OPA |
OPCM_IRQHandler | OPCM |
OSC32KCal_IRQHandler | OSC32 KCal |
OSCWakeUp_IRQHandler | OSC Wake Up |
PIOC_IRQHandler | PIOC |
PVD_IRQHandler | PVD through EXTI Line detect |
RCC_IRQHandler | RCC |
RNG_IRQHandler | RNG |
RTC_IRQHandler | RTC |
RTCAlarm_IRQHandler | RTC Alarm through EXTI Line |
SDIO_IRQHandler | SDIO |
SPI1_IRQHandler | SPI1 |
SPI2_IRQHandler | SPI2 |
SPI3_IRQHandler | SPI3 |
TAMPER_IRQHandler | TAMPER |
TIM1_BRK_IRQHandler | TIM1 Break |
TIM1_CC_IRQHandler | TIM1 Capture Compare |
TIM1_TRG_COM_IRQHandler | TIM1 Trigger and Commutation |
TIM1_UP_IRQHandler | TIM1 Update |
TIM2_BRK_IRQHandler | TIM2 Break |
TIM2_CC_IRQHandler | TIM2 Capture Compare |
TIM2_TRG_COM_IRQHandler | TIM2 Trigger and Commutation |
TIM2_UP_IRQHandler | TIM2 Update |
TIM2_IRQHandler | TIM2 |
TIM3_IRQHandler | TIM3 |
TIM4_IRQHandler | TIM4 |
TIM5_IRQHandler | TIM5 |
TIM6_IRQHandler | TIM6 |
TIM7_IRQHandler | TIM7 |
TIM8_BRK_IRQHandler | TIM8 Break |
TIM8_CC_IRQHandler | TIM8 Capture Compare |
TIM8_TRG_COM_IRQHandler | TIM8 Trigger and Commutation |
TIM8_UP_IRQHandler | TIM8 Update |
TIM9_BRK_IRQHandler | TIM9 Break |
TIM9_CC_IRQHandler | TIM9 Capture Compare |
TIM9_TRG_COM_IRQHandler | TIM9 Trigger and Commutation |
TIM9_UP_IRQHandler | TIM9 Update |
TIM10_BRK_IRQHandler | TIM10 Break |
TIM10_CC_IRQHandler | TIM10 Capture Compare |
TIM10_TRG_COM_IRQHandler | TIM10 Trigger and Commutation |
TIM10_UP_IRQHandler | TIM10 Update |
USART1_IRQHandler | USART1 |
USART2_IRQHandler | USART2 |
USART3_IRQHandler | USART3 |
USART4_IRQHandler | USART4 |
UART4_IRQHandler | UART4 |
UART5_IRQHandler | UART5 |
UART6_IRQHandler | UART6 |
UART7_IRQHandler | UART7 |
UART8_IRQHandler | UART8 |
USB_HP_CAN1_TX_IRQHandler | USB HP and CAN1 TX |
USB_LP_CAN1_RX0_IRQHandler | USB LP and CAN1RX0 |
USBFS_IRQHandler | USBFS Break |
USBFSWakeUp_IRQHandler | USBFS Wake up from suspend |
USBHS_IRQHandler | USBHS |
USBHSWakeup_IRQHandler | USBHS Wakeup |
USBPD_IRQHandler | USBPD |
USBPDWakeUp_IRQHandler | USBPD Wake up |
USBWakeUp_IRQHandler | USB Wakeup from suspend |
WWDG_IRQHandler | Window Watchdog |
上記が割り込み名とその説明になります。基本はSTM32と同じ名前のはずですが、独自拡張したものも増えています。「ETH_WKUP_IRQHandler」と「ETHWakeUp_IRQHandler」などはおそらく同じ役割だと思いますが命名がわかれてしまっています。
CH32Vシリーズでの割り込みチップ別一覧
IT | c h 3 2 l 1 0 3 | c h 3 2 v 0 0 3 | c h 3 2 v 0 0 6 | c h 3 2 v 1 0 3 | c h 3 2 v 2 0 x _ D 6 | c h 3 2 v 2 0 x _ D 8 | c h 3 2 v 2 0 x _ D 8 W | c h 3 2 v 3 0 x _ D 8 | c h 3 2 v 3 0 x _ D 8 C | c h 3 2 x 0 3 5 |
---|---|---|---|---|---|---|---|---|---|---|
ADC_IRQHandler | O | |||||||||
ADC1_IRQHandler | O | O | O | |||||||
ADC1_2_IRQHandler | O | O | O | O | O | O | ||||
AWU_IRQHandler | O | O | O | |||||||
BB_IRQHandler | O | |||||||||
LLE_IRQHandler | O | |||||||||
CAN1_RX1_IRQHandler | O | O | O | O | O | O | ||||
CAN1_SCE_IRQHandler | O | O | O | O | O | O | ||||
CAN2_RX0_IRQHandler | O | |||||||||
CAN2_RX1_IRQHandler | O | |||||||||
CAN2_SCE_IRQHandler | O | |||||||||
CAN2_TX_IRQHandler | O | |||||||||
CMPWakeUp_IRQHandler | O | |||||||||
DMA1_Channel1_IRQHandler | O | O | O | O | O | O | O | O | O | O |
DMA1_Channel2_IRQHandler | O | O | O | O | O | O | O | O | O | O |
DMA1_Channel3_IRQHandler | O | O | O | O | O | O | O | O | O | O |
DMA1_Channel4_IRQHandler | O | O | O | O | O | O | O | O | O | O |
DMA1_Channel5_IRQHandler | O | O | O | O | O | O | O | O | O | O |
DMA1_Channel6_IRQHandler | O | O | O | O | O | O | O | O | O | O |
DMA1_Channel7_IRQHandler | O | O | O | O | O | O | O | O | O | O |
DMA1_Channel8_IRQHandler | O | O | O | O | O | |||||
DMA2_Channel1_IRQHandler | O | O | ||||||||
DMA2_Channel2_IRQHandler | O | O | ||||||||
DMA2_Channel3_IRQHandler | O | O | ||||||||
DMA2_Channel4_IRQHandler | O | O | ||||||||
DMA2_Channel5_IRQHandler | O | O | ||||||||
DMA2_Channel6_IRQHandler | O | O | ||||||||
DMA2_Channel7_IRQHandler | O | O | ||||||||
DMA2_Channel8_IRQHandler | O | O | ||||||||
DMA2_Channel9_IRQHandler | O | O | ||||||||
DMA2_Channel10_IRQHandler | O | O | ||||||||
DMA2_Channel11_IRQHandler | O | O | ||||||||
DVP_IRQHandler | O | |||||||||
ETH_IRQHandler | O | O | O | |||||||
ETH_WKUP_IRQHandler | O | |||||||||
ETHWakeUp_IRQHandler | O | O | ||||||||
EXTI0_IRQHandler | O | O | O | O | O | O | O | |||
EXTI1_IRQHandler | O | O | O | O | O | O | O | |||
EXTI2_IRQHandler | O | O | O | O | O | O | O | |||
EXTI3_IRQHandler | O | O | O | O | O | O | O | |||
EXTI4_IRQHandler | O | O | O | O | O | O | O | |||
EXTI9_5_IRQHandler | O | O | O | O | O | O | O | |||
EXTI15_10_IRQHandler | O | O | O | O | O | O | O | |||
EXTI7_0_IRQHandler | O | O | O | |||||||
EXTI15_8_IRQHandler | O | |||||||||
EXTI25_16_IRQHandler | O | |||||||||
FLASH_IRQHandler | O | O | O | O | O | O | O | O | O | O |
I2C1_ER_IRQHandler | O | O | O | O | O | O | O | O | O | O |
I2C1_EV_IRQHandler | O | O | O | O | O | O | O | O | O | O |
I2C2_ER_IRQHandler | O | O | O | O | O | O | O | |||
I2C2_EV_IRQHandler | O | O | O | O | O | O | O | |||
LPTIM_IRQHandler | O | |||||||||
LPTIMWakeUp_IRQHandler | O | |||||||||
OPA_IRQHandler | O | O | ||||||||
OPCM_IRQHandler | O | |||||||||
OSC32KCal_IRQHandler | O | O | ||||||||
OSCWakeUp_IRQHandler | O | O | ||||||||
PIOC_IRQHandler | O | |||||||||
PVD_IRQHandler | O | O | O | O | O | O | O | O | O | O |
RCC_IRQHandler | O | O | O | O | O | O | O | O | O | |
RNG_IRQHandler | O | O | ||||||||
RTC_IRQHandler | O | O | O | O | O | O | O | |||
RTCAlarm_IRQHandler | O | O | O | O | O | O | O | |||
SDIO_IRQHandler | O | O | ||||||||
SPI1_IRQHandler | O | O | O | O | O | O | O | O | O | O |
SPI2_IRQHandler | O | O | O | O | O | O | O | |||
SPI3_IRQHandler | O | O | ||||||||
TAMPER_IRQHandler | O | O | O | O | O | O | O | |||
TIM1_BRK_IRQHandler | O | O | O | O | O | O | O | O | O | O |
TIM1_CC_IRQHandler | O | O | O | O | O | O | O | O | O | O |
TIM1_TRG_COM_IRQHandler | O | O | O | O | O | O | O | O | O | O |
TIM1_UP_IRQHandler | O | O | O | O | O | O | O | O | O | O |
TIM2_BRK_IRQHandler | O | |||||||||
TIM2_CC_IRQHandler | O | |||||||||
TIM2_TRG_COM_IRQHandler | O | |||||||||
TIM2_UP_IRQHandler | O | |||||||||
TIM2_IRQHandler | O | O | O | O | O | O | O | O | O | |
TIM3_IRQHandler | O | O | O | O | O | O | O | O | ||
TIM4_IRQHandler | O | O | O | O | O | O | O | |||
TIM5_IRQHandler | O | O | O | O | ||||||
TIM6_IRQHandler | O | O | ||||||||
TIM7_IRQHandler | O | O | ||||||||
TIM8_BRK_IRQHandler | O | O | ||||||||
TIM8_CC_IRQHandler | O | O | ||||||||
TIM8_TRG_COM_IRQHandler | O | O | ||||||||
TIM8_UP_IRQHandler | O | O | ||||||||
TIM9_BRK_IRQHandler | O | O | ||||||||
TIM9_CC_IRQHandler | O | O | ||||||||
TIM9_TRG_COM_IRQHandler | O | O | ||||||||
TIM9_UP_IRQHandler | O | O | ||||||||
TIM10_BRK_IRQHandler | O | O | ||||||||
TIM10_CC_IRQHandler | O | O | ||||||||
TIM10_TRG_COM_IRQHandler | O | O | ||||||||
TIM10_UP_IRQHandler | O | O | ||||||||
USART1_IRQHandler | O | O | O | O | O | O | O | O | O | O |
USART2_IRQHandler | O | O | O | O | O | O | O | O | O | |
USART3_IRQHandler | O | O | O | O | O | O | O | O | ||
USART4_IRQHandler | O | O | ||||||||
UART4_IRQHandler | O | O | O | O | O | |||||
UART5_IRQHandler | O | O | ||||||||
UART6_IRQHandler | O | O | ||||||||
UART7_IRQHandler | O | O | ||||||||
UART8_IRQHandler | O | O | ||||||||
USB_HP_CAN1_TX_IRQHandler | O | O | O | O | O | O | ||||
USB_LP_CAN1_RX0_IRQHandler | O | O | O | O | O | O | ||||
USBFS_IRQHandler | O | O | O | O | O | O | O | O | ||
USBFSWakeUp_IRQHandler | O | O | O | O | O | |||||
USBHS_IRQHandler | O | |||||||||
USBHSWakeup_IRQHandler | O | |||||||||
USBPD_IRQHandler | O | O | ||||||||
USBPDWakeUp_IRQHandler | O | O | ||||||||
USBWakeUp_IRQHandler | O | O | O | O | O | |||||
WWDG_IRQHandler | O | O | O | O | O | O | O | O | O | O |
上記が一覧になります。チップごとに微妙に違います。割り込みをみることである程度チップごとの機能差もわかると思います。
割り込みが呼ばれる順序
定義
割り込み自体は「startup_ch32v10x.S」などというアセンブラで記述されたスタートアップコードにて定義されています。
...
.option rvc;
.section .text.vector_handler, "ax", @progbits
.weak NMI_Handler
.weak HardFault_Handler
.weak SysTick_Handler
.weak SW_Handler
.weak WWDG_IRQHandler
.weak PVD_IRQHandler
.weak TAMPER_IRQHandler
.weak RTC_IRQHandler
.weak FLASH_IRQHandler
.weak RCC_IRQHandler
.weak EXTI0_IRQHandler
.weak EXTI1_IRQHandler
.weak EXTI2_IRQHandler
.weak EXTI3_IRQHandler
.weak EXTI4_IRQHandler
...
上記のようにweakで定義されており、仮の関数も登録されているため未定義でもビルドできるようになっています。この関数を自分で定義することにより割り込み時に呼ばれるコールバック関数になります。
宣言部
void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM1_CC_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void NMI_Handler(void)
{
while(1)
{
}
}
void HardFault_Handler(void)
{
while(1)
{
}
}
void TIM1_CC_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
{
printf("CH1_Val:%d\r\n", TIM_GetCapture1(TIM1));
TIM_SetCounter(TIM1, 0);
}
if(TIM_GetITStatus(TIM1, TIM_IT_CC2) != RESET)
{
printf("CH2_Val:%d\r\n", TIM_GetCapture2(TIM1));
}
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 | TIM_IT_CC2);
}
CH32V103のTIM/Input_Captureプロジェクトのch32v10x_it.cから抜粋したものです。WCH-Interrupt-fast属性をつけて上書きすることで割り込み時に呼び出されます。
そしてこの割り込み関数はどこに宣言しても動きます。通常は_it.cで宣言されている事が多いですが、main.cに記述があったりと非常にばらつきがあります。EVTを確認するときにも_it.cの中身も確認したほうがよいと思います。
その他のファイル構成
User/main.c
main関数が宣言されている基本となるファイル。このファイルから中を確認する。
User/ch32v10x_conf.h
内部で利用しているPeripheralを読み込む宣言部分。GPIO_Toggleだと基本的なベーシックなものがincludeされている。Arduino化するときにはすべてのファイルを列挙したものに書き換えてあります。通常使うときにも全部入りでリンク時に未使用のものを除外する動きでも問題ないと思います。
User/system_ch32v10x.c
クロックの指定をしているファイル。EVTでも例によって微妙にクロック指定が違うので気をつける必要があります。またCH32V103はMAX80MHzと書いてありますが、指定は72MHzまでしかできないなどの微妙な仕様です。
SRC/Core
RISC-V向けの関数をインラインアセンブラで記述してあるファイルです。通常は編集する必要はないと思います。
SRC/Debug
UARTの初期化や、printfをしたときにどこに出力をするのかの_write関数などが定義されています。
SRC/Ld
リンクで利用するLink.ldが保存されています。
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}
上記のようにメモリやフラッシュ容量が記述されていますがEVTでは同じファイルを使いまわしています。
SRC/Peripheral
実際の機能を利用するためのラッパー関数が入っています。ある程度チップ差を吸収してくれるようになっていますが微妙に欲しい機能がなかったりします。
void GPIO_DeInit(GPIO_TypeDef *GPIOx)
{
if(GPIOx == GPIOA)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);
}
else if(GPIOx == GPIOB)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);
}
...
例えば上記のように初期状態に戻す関数はあるのですが、初期化する関数がありません。そのためENABLEする場合にはチップ別に上記と同じような処理を書く必要があります。
SRC/Startup
スタートアップのアセンブラが保存されています。チップのバリエーション等で複数のファイルが入っている場合があったり、openwchのArduino Coreだと動作させる電圧で違うスタートアップになったりするのですが細かい情報がないのでなかなか手をいれるのが難しいです。
まとめ
なかなかEVTは便利なのですが、単一機能だけのシンプルなものがなかったり、実際に利用するときのユースケースがなかったりと試行錯誤する必要があるものが多いです。
コメント