前回からの続きです。
このテーマを最初からご覧になる場合はこちらからどうぞ。
サンプルプロジェクトの説明
このページ(TOPPERS/ASPのビルドからデバッグまで~サンプルプロジェクトで遊ぼう)を参照してください。
PIC32MX版カーネルについて
以下、このカーネルにおける備考です。
●割り込み優先度
このカーネルでは、-1(優先度最低)から-7(優先度最高)の7段階の優先度設定が可能です。
PIC32MXは、実は64段階までの割り込み優先度をサポートしています。
でも…そんなに要らんでしょ?
ということで、私の実装では7段階までに抑えています。
7段階の根拠は、元祖TOPPERS/ASPの「m68k」版と合わせただけで深い意味はありません。
実用レベルでは十分かと…。
●割り込み番号の指定方法
このマイコンは、割り込み番号と、割り込みベクタ番号が一致しないタイプです。
ちょっと小さいので、クリックしてご覧いただきたいのですが、以下は、データシートからの一覧表です。
割り込み番号を意味する「IRQ#」と、割り込みベクタ番号を意味する「Vector#」の不一致がお分かりいただけるかと。
例えば、デバッグシリアルの割り込み設定例を見てみましょう。
「..\target\1_2_5_starterlit_gcc\target_serial.h」において、以下のように定義しています。
- ...
- /*
- * SIOの割込み番号,優先度,属性の定義
- */
- #define INTNO_SIO_RX INT_SOURCE_USART_1_RECEIVE
- #define INTNO_SIO_TX INT_SOURCE_USART_1_TRANSMIT
- #define INHNO_SIO _UART_1_VECTOR
- #define INTPRI_SIO -6 /* 割込み優先度 */
- #define INTATR_SIO TA_NULL /* 割込み属性 */
- ...
この定義において、シリアル通信の受信割り込みの割り込み番号が「INT_SOURCE_USART_1_RECEIVE」、送信割り込みの割り込み番号が「INT_SOURCE_USART_1_TRANSMIT」、更に両方の割り込みのベクタ番号は「_UART_1_VECTOR」と設定されていることが分かります。
この設定は「make depend」実行時に「..\target\1_2_5_starterlit_gcc\target_serial.cfg」によってコンフィグレータに渡されます。
では「INT_SOURCE_USART_1_RECEIVE」や「INT_SOURCE_USART_1_TRANSMIT」の実際の割り込み番号の値がどこに定義されているのか?
分かりにくい場所にあるのですが、今回の評価ボード「PIC32MX1/2/5 Starter Kit」に搭載されているマイコンの型番が「PIC32MX570F512L」ですので、「..\arch\pic32mx_gcc\framework\peripheral\int\processor\int_p32mx570f512l.h」の中の以下の記述にあります。
- ...
- typedef enum {
- INT_SOURCE_TIMER_CORE = 0,
- INT_SOURCE_SOFTWARE_0 = 1,
- INT_SOURCE_SOFTWARE_1 = 2,
- INT_SOURCE_EXTERNAL_0 = 3,
- INT_SOURCE_TIMER_1 = 4,
- INT_SOURCE_INPUT_CAPTURE_1_ERROR = 5,
- INT_SOURCE_INPUT_CAPTURE_1 = 6,
- INT_SOURCE_OUTPUT_COMPARE_1 = 7,
- INT_SOURCE_EXTERNAL_1 = 8,
- INT_SOURCE_TIMER_2 = 9,
- INT_SOURCE_INPUT_CAPTURE_2_ERROR = 10,
- INT_SOURCE_INPUT_CAPTURE_2 = 11,
- INT_SOURCE_OUTPUT_COMPARE_2 = 12,
- INT_SOURCE_EXTERNAL_2 = 13,
- INT_SOURCE_TIMER_3 = 14,
- INT_SOURCE_INPUT_CAPTURE_3_ERROR = 15,
- INT_SOURCE_INPUT_CAPTURE_3 = 16,
- INT_SOURCE_OUTPUT_COMPARE_3 = 17,
- INT_SOURCE_EXTERNAL_3 = 18,
- INT_SOURCE_TIMER_4 = 19,
- INT_SOURCE_INPUT_CAPTURE_4_ERROR = 20,
- INT_SOURCE_INPUT_CAPTURE_4 = 21,
- INT_SOURCE_OUTPUT_COMPARE_4 = 22,
- INT_SOURCE_EXTERNAL_4 = 23,
- INT_SOURCE_TIMER_5 = 24,
- INT_SOURCE_INPUT_CAPTURE_5_ERROR = 25,
- INT_SOURCE_INPUT_CAPTURE_5 = 26,
- INT_SOURCE_OUTPUT_COMPARE_5 = 27,
- INT_SOURCE_ADC_1 = 28,
- INT_SOURCE_SPI_1_ERROR = 35,
- INT_SOURCE_SPI_1_RECEIVE = 36,
- INT_SOURCE_SPI_1_TRANSMIT = 37,
- INT_SOURCE_USART_1_ERROR = 38,
- INT_SOURCE_USART_1_RECEIVE = 39,
- INT_SOURCE_USART_1_TRANSMIT = 40,
- INT_SOURCE_I2C_1_BUS = 41,
- INT_SOURCE_I2C_1_ERROR = 41,
- INT_SOURCE_I2C_1_SLAVE = 42,
- INT_SOURCE_I2C_1_MASTER = 43,
- INT_SOURCE_CHANGE_NOTICE_A = 44,
- INT_SOURCE_CHANGE_NOTICE_B = 45,
- INT_SOURCE_CHANGE_NOTICE_C = 46,
- INT_SOURCE_CHANGE_NOTICE_D = 47,
- INT_SOURCE_CHANGE_NOTICE_E = 48,
- INT_SOURCE_CHANGE_NOTICE_F = 49,
- INT_SOURCE_CHANGE_NOTICE_G = 50,
- INT_SOURCE_PARALLEL_PORT = 51,
- INT_SOURCE_PARALLEL_PORT_ERROR = 52,
- INT_SOURCE_COMPARATOR_1 = 32,
- INT_SOURCE_COMPARATOR_2 = 33,
- INT_SOURCE_USB_1 = 34,
- INT_SOURCE_DMA_0 = 72,
- INT_SOURCE_DMA_1 = 73,
- INT_SOURCE_DMA_2 = 74,
- INT_SOURCE_DMA_3 = 75,
- INT_SOURCE_SPI_2_ERROR = 53,
- INT_SOURCE_SPI_2_RECEIVE = 54,
- INT_SOURCE_SPI_2_TRANSMIT = 55,
- INT_SOURCE_USART_2_ERROR = 56,
- INT_SOURCE_USART_2_RECEIVE = 57,
- INT_SOURCE_USART_2_TRANSMIT = 58,
- INT_SOURCE_I2C_2_BUS = 59,
- INT_SOURCE_I2C_2_ERROR = 59,
- INT_SOURCE_I2C_2_SLAVE = 60,
- INT_SOURCE_I2C_2_MASTER = 61,
- INT_SOURCE_CAN_1 = 77,
- INT_SOURCE_SPI_3_ERROR = 78,
- INT_SOURCE_SPI_3_RECEIVE = 79,
- INT_SOURCE_SPI_3_TRANSMIT = 80,
- INT_SOURCE_USART_3_ERROR = 62,
- INT_SOURCE_USART_3_RECEIVE = 63,
- INT_SOURCE_USART_3_TRANSMIT = 64,
- INT_SOURCE_SPI_4_ERROR = 81,
- INT_SOURCE_SPI_4_RECEIVE = 82,
- INT_SOURCE_SPI_4_TRANSMIT = 83,
- INT_SOURCE_USART_4_ERROR = 65,
- INT_SOURCE_USART_4_RECEIVE = 66,
- INT_SOURCE_USART_4_TRANSMIT = 67,
- INT_SOURCE_USART_5_ERROR = 68,
- INT_SOURCE_USART_5_RECEIVE = 69,
- INT_SOURCE_USART_5_TRANSMIT = 70,
- INT_SOURCE_CLOCK_MONITOR = 29,
- INT_SOURCE_RTCC = 30,
- INT_SOURCE_FLASH_CONTROL = 31,
- INT_SOURCE_COMPARATOR_3 = 76,
- INT_SOURCE_CTMU = 71
- } INT_SOURCE;
- ...
これによると「INT_SOURCE_USART_1_RECEIVE」は「39」、「INT_SOURCE_USART_1_TRANSMIT」は「40」となっています。
上記のデータシートからの表と照らし合わせてください。
一致しますよね?
次に、割り込みのベクタ番号についてですが、割り込み番号と同様、「..\arch\pic32mx_gcc\framework\peripheral\int\processor\int_p32mx570f512l.h」の中の以下の記述にあります。
- ...
- typedef enum {
- INT_VECTOR_CT = _CORE_TIMER_VECTOR,
- INT_VECTOR_CS0 = _CORE_SOFTWARE_0_VECTOR,
- INT_VECTOR_CS1 = _CORE_SOFTWARE_1_VECTOR,
- INT_VECTOR_INT0 = _EXTERNAL_0_VECTOR,
- INT_VECTOR_T1 = _TIMER_1_VECTOR,
- INT_VECTOR_IC1 = _INPUT_CAPTURE_1_VECTOR,
- INT_VECTOR_IC1_ERROR = _INPUT_CAPTURE_1_VECTOR,
- INT_VECTOR_OC1 = _OUTPUT_COMPARE_1_VECTOR,
- INT_VECTOR_INT1 = _EXTERNAL_1_VECTOR,
- INT_VECTOR_T2 = _TIMER_2_VECTOR,
- INT_VECTOR_IC2 = _INPUT_CAPTURE_2_VECTOR,
- INT_VECTOR_IC2_ERROR = _INPUT_CAPTURE_2_VECTOR,
- INT_VECTOR_OC2 = _OUTPUT_COMPARE_2_VECTOR,
- INT_VECTOR_INT2 = _EXTERNAL_2_VECTOR,
- INT_VECTOR_T3 = _TIMER_3_VECTOR,
- INT_VECTOR_IC3 = _INPUT_CAPTURE_3_VECTOR,
- INT_VECTOR_IC3_ERROR = _INPUT_CAPTURE_3_VECTOR,
- INT_VECTOR_OC3 = _OUTPUT_COMPARE_3_VECTOR,
- INT_VECTOR_INT3 = _EXTERNAL_3_VECTOR,
- INT_VECTOR_T4 = _TIMER_4_VECTOR,
- INT_VECTOR_IC4 = _INPUT_CAPTURE_4_VECTOR,
- INT_VECTOR_IC4_ERROR = _INPUT_CAPTURE_4_VECTOR,
- INT_VECTOR_OC4 = _OUTPUT_COMPARE_4_VECTOR,
- INT_VECTOR_INT4 = _EXTERNAL_4_VECTOR,
- INT_VECTOR_T5 = _TIMER_5_VECTOR,
- INT_VECTOR_IC5 = _INPUT_CAPTURE_5_VECTOR,
- INT_VECTOR_IC5_ERROR = _INPUT_CAPTURE_5_VECTOR,
- INT_VECTOR_OC5 = _OUTPUT_COMPARE_5_VECTOR,
- INT_VECTOR_SPI1_FAULT = _SPI_1_VECTOR,
- INT_VECTOR_SPI1_RX = _SPI_1_VECTOR,
- INT_VECTOR_SPI1_TX = _SPI_1_VECTOR,
- INT_VECTOR_UART1_FAULT = _UART_1_VECTOR,
- INT_VECTOR_UART1_RX = _UART_1_VECTOR,
- INT_VECTOR_UART1_TX = _UART_1_VECTOR,
- INT_VECTOR_I2C1_BUS = _I2C_1_VECTOR,
- INT_VECTOR_I2C1_SLAVE = _I2C_1_VECTOR,
- INT_VECTOR_I2C1_MASTER = _I2C_1_VECTOR,
- INT_VECTOR_SPI2_FAULT = _SPI_2_VECTOR,
- INT_VECTOR_SPI2_RX = _SPI_2_VECTOR,
- INT_VECTOR_SPI2_TX = _SPI_2_VECTOR,
- INT_VECTOR_UART2_FAULT = _UART_2_VECTOR,
- INT_VECTOR_UART2_RX = _UART_2_VECTOR,
- INT_VECTOR_UART2_TX = _UART_2_VECTOR,
- INT_VECTOR_I2C2_BUS = _I2C_2_VECTOR,
- INT_VECTOR_I2C2_SLAVE = _I2C_2_VECTOR,
- INT_VECTOR_I2C2_MASTER = _I2C_2_VECTOR,
- INT_VECTOR_SPI3_FAULT = _SPI_3_VECTOR,
- INT_VECTOR_SPI3_RX = _SPI_3_VECTOR,
- INT_VECTOR_SPI3_TX = _SPI_3_VECTOR,
- INT_VECTOR_UART3_FAULT = _UART_3_VECTOR,
- INT_VECTOR_UART3_RX = _UART_3_VECTOR,
- INT_VECTOR_UART3_TX = _UART_3_VECTOR,
- INT_VECTOR_SPI4_FAULT = _SPI_4_VECTOR,
- INT_VECTOR_SPI4_RX = _SPI_4_VECTOR,
- INT_VECTOR_SPI4_TX = _SPI_4_VECTOR,
- INT_VECTOR_UART4_FAULT = _UART_4_VECTOR,
- INT_VECTOR_UART4_RX = _UART_4_VECTOR,
- INT_VECTOR_UART4_TX = _UART_4_VECTOR,
- INT_VECTOR_UART5_FAULT = _UART_5_VECTOR,
- INT_VECTOR_UART5_RX = _UART_5_VECTOR,
- INT_VECTOR_UART5_TX = _UART_5_VECTOR,
- INT_VECTOR_CHANGE_NOTICE_A = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_CHANGE_NOTICE_B = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_CHANGE_NOTICE_C = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_CHANGE_NOTICE_D = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_CHANGE_NOTICE_E = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_CHANGE_NOTICE_F = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_CHANGE_NOTICE_G = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_PMP = _PMP_VECTOR,
- INT_VECTOR_PMP_ERROR = _PMP_VECTOR,
- INT_VECTOR_USB1 = _USB_1_VECTOR,
- INT_VECTOR_RTCC = _RTCC_VECTOR,
- INT_VECTOR_FLASH = _FCE_VECTOR,
- INT_VECTOR_SPI1 = _SPI_1_VECTOR,
- INT_VECTOR_UART1 = _UART_1_VECTOR,
- INT_VECTOR_SPI3 = _SPI_3_VECTOR,
- INT_VECTOR_I2C1 = _I2C_1_VECTOR,
- INT_VECTOR_CN = _CHANGE_NOTICE_VECTOR,
- INT_VECTOR_AD1 = _ADC_VECTOR,
- INT_VECTOR_CMP1 = _COMPARATOR_1_VECTOR,
- INT_VECTOR_CMP2 = _COMPARATOR_2_VECTOR,
- INT_VECTOR_CMP3 = _COMPARATOR_3_VECTOR,
- INT_VECTOR_UART3 = _UART_3_VECTOR,
- INT_VECTOR_SPI2 = _SPI_2_VECTOR,
- INT_VECTOR_UART2 = _UART_2_VECTOR,
- INT_VECTOR_SPI4 = _SPI_4_VECTOR,
- INT_VECTOR_I2C2 = _I2C_2_VECTOR,
- INT_VECTOR_FSCM = _FAIL_SAFE_MONITOR_VECTOR,
- INT_VECTOR_CTMU = _CTMU_VECTOR,
- INT_VECTOR_DMA0 = _DMA_0_VECTOR,
- INT_VECTOR_DMA1 = _DMA_1_VECTOR,
- INT_VECTOR_DMA2 = _DMA_2_VECTOR,
- INT_VECTOR_DMA3 = _DMA_3_VECTOR,
- INT_VECTOR_FCE = _FCE_VECTOR,
- INT_VECTOR_CAN1 = _CAN_1_VECTOR,
- INT_VECTOR_UART4 = _UART_4_VECTOR,
- INT_VECTOR_UART5 = _UART_5_VECTOR
- } INT_VECTOR;
- ...
これによると「INT_VECTOR_UART1_RX」や「INT_VECTOR_UART1_TX」は共に「_UART_1_VECTOR」という同じ値の割り込みベクタ番号に定義されています。
今回の場合、「..\target\1_2_5_starterlit_gcc\target_serial.h」において、割り込みベクタ番号を「INT_VECTOR_UART1_RX」や「INT_VECTOR_UART1_TX」とは書かずに「_UART_1_VECTOR」と直に記述しましたが、どちらでも結果は同じです。
ちなみに「_UART_1_VECTOR」の実際の割り込みベクタ番号の値は、これまた分かりにくい場所に…。
このブログの記述通り開発環境を作っていただいた場合は、
「C:\Program Files\Microchip\xc32\v4.30\pic32mx\include\proc\PIC32MX\p32mx570f512l.h」の中の以下の記述にあります。
ここはもう、ツールチェーンのディレクトリですよね。
- ...
- /* Vector Numbers */
- #define _CORE_TIMER_VECTOR 0
- #define _CORE_SOFTWARE_0_VECTOR 1
- #define _CORE_SOFTWARE_1_VECTOR 2
- #define _EXTERNAL_0_VECTOR 3
- #define _TIMER_1_VECTOR 4
- #define _INPUT_CAPTURE_1_VECTOR 5
- #define _OUTPUT_COMPARE_1_VECTOR 6
- #define _EXTERNAL_1_VECTOR 7
- #define _TIMER_2_VECTOR 8
- #define _INPUT_CAPTURE_2_VECTOR 9
- #define _OUTPUT_COMPARE_2_VECTOR 10
- #define _EXTERNAL_2_VECTOR 11
- #define _TIMER_3_VECTOR 12
- #define _INPUT_CAPTURE_3_VECTOR 13
- #define _OUTPUT_COMPARE_3_VECTOR 14
- #define _EXTERNAL_3_VECTOR 15
- #define _TIMER_4_VECTOR 16
- #define _INPUT_CAPTURE_4_VECTOR 17
- #define _OUTPUT_COMPARE_4_VECTOR 18
- #define _EXTERNAL_4_VECTOR 19
- #define _TIMER_5_VECTOR 20
- #define _INPUT_CAPTURE_5_VECTOR 21
- #define _OUTPUT_COMPARE_5_VECTOR 22
- #define _ADC_VECTOR 23
- #define _FAIL_SAFE_MONITOR_VECTOR 24
- #define _RTCC_VECTOR 25
- #define _FCE_VECTOR 26
- #define _COMPARATOR_1_VECTOR 27
- #define _COMPARATOR_2_VECTOR 28
- #define _USB_1_VECTOR 29
- #define _SPI_1_VECTOR 30
- #define _UART_1_VECTOR 31
- #define _I2C_1_VECTOR 32
- #define _CHANGE_NOTICE_VECTOR 33
- #define _PMP_VECTOR 34
- #define _SPI_2_VECTOR 35
- #define _UART_2_VECTOR 36
- #define _I2C_2_VECTOR 37
- #define _UART_3_VECTOR 38
- #define _UART_4_VECTOR 39
- #define _UART_5_VECTOR 40
- #define _CTMU_VECTOR 41
- #define _DMA_0_VECTOR 42
- #define _DMA_1_VECTOR 43
- #define _DMA_2_VECTOR 44
- #define _DMA_3_VECTOR 45
- #define _COMPARATOR_3_VECTOR 46
- #define _CAN_1_VECTOR 47
- #define _SPI_3_VECTOR 48
- #define _SPI_4_VECTOR 49
- ...
これによると「_UART_1_VECTOR」は「31」となっています。
こちらも、上記のデータシートからの表と一致しますね!
このように、もし新たな割り込みを実装する場合には、割り込みの設定は割り込み番号と割り込みベクタ番号をそれぞれ調べて設定するようにしてください。
面倒だけども…。
●例外ハンドラ
例外ハンドラは、以下の表のものが使用できます。
今回のサンプルプロジェクトでターミナルから「z」や「Z」を入力して起こる例外は、13番の「Trap exception」例外です。
この設定は「..\arch\pic32mx_gcc\prc_test.h」の以下の記述で設定されています。
- ...
- #define CPUEXC1 13 /* ゼロ除算例外 */
- #define RAISE_CPU_EXCEPTION syslog(LOG_NOTICE, "zerodiv = %d", 10 / 0)
- ...
ご覧の通り「Trap exception」は、ゼロ除算を行った結果引き起こされるものです。
小文字の「z」と大文字の「Z」の違いは、CPU例外が小文字の場合はカーネル管轄内で、大文字の場合はカーネル管轄外でそれぞれ実行されるということだけです。
各CPU例外の詳細については、PIC32MXのデータシートを熟読していただく必要がありますが、これらが引き起こされた時点で致命的な状況が多く、デバッグでの用途以外、あまり使い道はないでしょう。
●一部サービスコールは未対応
性能評価用システム時刻取得のための「get_utm()」サービスコールは未実装です。
ライセンスについて
このカーネルは「TOPPERSライセンス」で配布しております。
無償ですが、使用に関しては自己責任です。
万が一、このカーネルを商用利用する方は、このリンク先の条項に従ってください。
さて、今回はPIC32MXを取り上げてみました。
「PIC32」と呼べるものは、今回の「MX」他にも「MM」、「MC」、「MK」や「MZ」などがラインナップされています。
これらの「M系」は、全てMIPSアーキテクチャです。
しかし、先ごろ「C系」のPIC32が発表されました。
「CM」、「CX」や「CZ」などです。
https://www.microchip.com/en-us/products/microcontrollers-and-microprocessors/32-bit-mcus
重要なことは、これらの「C系」PIC32が、遂にARMアーキテクチャになってしまったことです!
う~ん、ARM化の波が遂にここまでも。
世の中何でもかんでもARM一辺倒になって、ホントにいいんでしょうかね?
まあ、プログラマーとしては仕事の面では楽になりますが、趣味の面では退屈だし、寂しく思うのです…。
だいたい、同じARMアーキテクチャで各社しのぎを削っても、横一線で尖った特徴もなくなるので、製品のウリをアピールするのが難しくなると思うのですが。
私は、こういうピーキーなマイコンの方が好きだなぁ…。
そのARMも、いずれは今ホットな「RISC-V」に置き換わってしまうのか?
諸行無常、盛者必衰…。
注目して見ていきましょう!
<終わり>