Forums: Help (Thread #37925)

周期タイマー割り込みの優先順位設定に関して (2016-08-08 14:42 by masayuki_arai #78476)

初めまして、現在、STマイクロ社のSTM32F302のファームウェアにてHOSを動作
させ、ステッピングモータの制御等を実施しております。
私の方は、今までマイコン制御ソフトウェアの開発経験がほとんどないのですが、
C言語のプログラミング経験はあります。

ここ1か月程度、前任者が制作した上記のファームウェアを色々解析したり、
いじくったりしていました。
今回、このファームウェアで、USB-CDCのシリアル通信機能を実装する必要が
あり、STマイクロ社のサイトよりダウンロードした、STM32F302用のUSB-CDC
通信のサンプルプログラムを参考に、元々のファームウェアプログラムに
USB-CDC通信処理を入れ込みました。
マイコンファームウェアがUSB-CDC通信を実施する相手側は、WindowsPCで、
WindowsPC側は、STマイクロ社が提供しているUSBデバイスドライバにより、
仮想COMポートとして認識し、このCOM Portに対してシリアル通信を実行する
ことにより、通信する構成となっています。

USB-CDCシリアル通信処理は正常に行えるようになったのですが、USBケーブル
接続時に、PC側からシリアルCOM Portのオープン処理に、1分半~3分程度の時間
がかかってしまう現象が発生しており、なかなか解決できず、困っております。

STマイクロ社のUSB-CDCサンプルプログラムのプロジェクトを単体で実行した
場合は、このような、オープン処理が遅い現象は発生しません。

STマイクロ社の方に色々と相談していたのですが、STマイクロ社・社内の
USB-CDCサンプルプログラムのTipsのようなものに、

> RTOSはOSのタイマをSysTickにアサインすることが多く、また最低の
> プライオリティ割り込みを使うように設計されている場合が多いです。
> しかし、USB-CDCサンプルプログラムの構造上、SysTickは最高の
> プライオリティで使うことを想定しているため、矛盾が生じてしまい
> ます。
> 対策は、OSのタイマはTIM6などのBasic Timerを使うようにして、
> その割込みレベルを最低に設定してください。

との記載があり、この設定を実施してみてほしいと話がありましたが、HOSの
タイマをTIM6などのTimerを使うようにする設定方法と、その割込みレベルを
最低に設定する方法がわかりません。

現在の、プログラムコードでは、
kernel_cfg.c にて、

~【前半省略】
/* ------------------------------------------ */
/* create cyclic handler objects */
/* ------------------------------------------ */

/* cyclic handler control block for rom area */
const T_KERNEL_CYCCB_ROM kernel_cyccb_rom[1] =
{
{(ATR)(TA_HLNG), (VP_INT)(0), (FP)(OsWrapper_enterTimerCyclicHandler), (RELTIM)(1)},
};

/* cyclic handler control block for ram area */
T_KERNEL_CYCCB_RAM kernel_cyccb_ram[1];

/* cyclic handler control block table */
T_KERNEL_CYCCB_RAM *kernel_cyccb_ram_tbl[1] =
{
&kernel_cyccb_ram[0],
};

~【途中省略】~

/* ------------------------------------------ */
/* initialize functions */
/* ------------------------------------------ */

/* object initialize */
void kernel_cfg_init(void)
{

~【途中省略】~

/* initialize cyclic handler control block */
for ( i = 0; i < 1; i++ )
{
kernel_cyccb_ram[i].cyccb_rom = &kernel_cyccb_rom[i];
}

/* initialize interrupt table */
kernel_intcb_tbl[SysTick_IRQn-(-14)].exinf = (VP_INT)(0);
kernel_intcb_tbl[SysTick_IRQn-(-14)].isr = (FP)(OsWrapper_interruptSysTick);
kernel_intcb_tbl[USART1_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_1);
kernel_intcb_tbl[USART1_IRQn-(-14)].isr = (FP)(Uart_interrupt);
kernel_intcb_tbl[USART2_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_2);
kernel_intcb_tbl[USART2_IRQn-(-14)].isr = (FP)(Uart_interrupt);
kernel_intcb_tbl[USART3_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_3);
kernel_intcb_tbl[USART3_IRQn-(-14)].isr = (FP)(Uart_interrupt);
kernel_intcb_tbl[UART4_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_4);
kernel_intcb_tbl[UART4_IRQn-(-14)].isr = (FP)(Uart_interrupt);
kernel_intcb_tbl[UART5_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_5);
kernel_intcb_tbl[UART5_IRQn-(-14)].isr = (FP)(Uart_interrupt);
kernel_intcb_tbl[I2C1_EV_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_1);
kernel_intcb_tbl[I2C1_EV_IRQn-(-14)].isr = (FP)(Iic_interruptEvent);
kernel_intcb_tbl[I2C1_ER_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_1);
kernel_intcb_tbl[I2C1_ER_IRQn-(-14)].isr = (FP)(Iic_interruptError);
kernel_intcb_tbl[I2C2_EV_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_2);
kernel_intcb_tbl[I2C2_EV_IRQn-(-14)].isr = (FP)(Iic_interruptEvent);
kernel_intcb_tbl[I2C2_ER_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_2);
kernel_intcb_tbl[I2C2_ER_IRQn-(-14)].isr = (FP)(Iic_interruptError);
kernel_intcb_tbl[TIM1_BRK_TIM15_IRQn-(-14)].exinf = (VP_INT)(PWM_CHANNEL_1);
kernel_intcb_tbl[TIM1_BRK_TIM15_IRQn-(-14)].isr = (FP)(Pwm_interrupt);
kernel_intcb_tbl[EXTI9_5_IRQn-(-14)].exinf = (VP_INT)(IOPORT_LINE_6);
kernel_intcb_tbl[EXTI9_5_IRQn-(-14)].isr = (FP)(IoPort_interrupt);
kernel_intcb_tbl[USB_LP_CAN_RX0_IRQn-(-14)].exinf = (VP_INT)(USB_CHANNEL_1);
kernel_intcb_tbl[USB_LP_CAN_RX0_IRQn-(-14)].isr = (FP)(USB_LP_CAN1_RX0_IRQHandler);
kernel_intcb_tbl[TIM4_IRQn-(-14)].exinf = (VP_INT)(0);
kernel_intcb_tbl[TIM4_IRQn-(-14)].isr = (FP)(TIMx_IRQHandler);
}
~【後半省略】



割込みの優先度の設定は、
stm32f30x.h 内で、

~【前半省略】
/**
* @brief STM32F30X Interrupt Number Definition, according to the selected device
* in @ref Library_configuration_section
*/
typedef enum IRQn
{
/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */
UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */
SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */
DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */
PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */
SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers **********************************************************************/
WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
TAMPER_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts */
RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI lines 17, 19 & 20 */
FLASH_IRQn = 4, /*!< FLASH global Interrupt */
~【以下省略】

のようになっております。
何分、勉強不足で、見当違いの質問でしたら申し訳ないのですが、
この中で、kernel_cyccb_rom[1] 内に定義している、OsWrapper_enterTimerCyclicHandler()
関数が、OSのタイマ処理の部分かなと考えておりますが、この認識で合って
おりますでしょうか?
また、上記した通り、OSタイマをTIM6等他のBasic Timerを使うようにする
方法や、その割込みレベルを最低に設定する方法に関して、アドバイスいた
だけると非常にありがたいです。

よろしくお願いいたします。

Reply to #78476×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-08 15:42 by hamayan #78477)

OsWrapper_enterTimerCyclicHandler()
> 関数が、OSのタイマ処理の部分かなと考えておりますが、この認識で合って
> おりますでしょうか?

よく判らないですが、関数名からは周期ハンドラに関する処理に思えます。
周期ハンドラであればタイマー処理の一部ではありますが、全体ではありません。

systic割り込みの優先度レベルが問題なっているのですから、まず優先度が幾つに設定されているのかを調べてみては如何でしょう。



[メッセージ #78476 への返信]
> 初めまして、現在、STマイクロ社のSTM32F302のファームウェアにてHOSを動作
> させ、ステッピングモータの制御等を実施しております。
> 私の方は、今までマイコン制御ソフトウェアの開発経験がほとんどないのですが、
> C言語のプログラミング経験はあります。
>
> ここ1か月程度、前任者が制作した上記のファームウェアを色々解析したり、
> いじくったりしていました。
> 今回、このファームウェアで、USB-CDCのシリアル通信機能を実装する必要が
> あり、STマイクロ社のサイトよりダウンロードした、STM32F302用のUSB-CDC
> 通信のサンプルプログラムを参考に、元々のファームウェアプログラムに
> USB-CDC通信処理を入れ込みました。
> マイコンファームウェアがUSB-CDC通信を実施する相手側は、WindowsPCで、
> WindowsPC側は、STマイクロ社が提供しているUSBデバイスドライバにより、
> 仮想COMポートとして認識し、このCOM Portに対してシリアル通信を実行する
> ことにより、通信する構成となっています。
>
> USB-CDCシリアル通信処理は正常に行えるようになったのですが、USBケーブル
> 接続時に、PC側からシリアルCOM Portのオープン処理に、1分半~3分程度の時間
> がかかってしまう現象が発生しており、なかなか解決できず、困っております。
>
> STマイクロ社のUSB-CDCサンプルプログラムのプロジェクトを単体で実行した
> 場合は、このような、オープン処理が遅い現象は発生しません。
>
> STマイクロ社の方に色々と相談していたのですが、STマイクロ社・社内の
> USB-CDCサンプルプログラムのTipsのようなものに、
>
> > RTOSはOSのタイマをSysTickにアサインすることが多く、また最低の
> > プライオリティ割り込みを使うように設計されている場合が多いです。
> > しかし、USB-CDCサンプルプログラムの構造上、SysTickは最高の
> > プライオリティで使うことを想定しているため、矛盾が生じてしまい
> > ます。
> > 対策は、OSのタイマはTIM6などのBasic Timerを使うようにして、
> > その割込みレベルを最低に設定してください。
>
> との記載があり、この設定を実施してみてほしいと話がありましたが、HOSの
> タイマをTIM6などのTimerを使うようにする設定方法と、その割込みレベルを
> 最低に設定する方法がわかりません。
>
> 現在の、プログラムコードでは、
> kernel_cfg.c にて、
>
> ~【前半省略】
> /* ------------------------------------------ */
> /* create cyclic handler objects */
> /* ------------------------------------------ */
>
> /* cyclic handler control block for rom area */
> const T_KERNEL_CYCCB_ROM kernel_cyccb_rom[1] =
> {
> {(ATR)(TA_HLNG), (VP_INT)(0), (FP)(OsWrapper_enterTimerCyclicHandler), (RELTIM)(1)},
> };
>
> /* cyclic handler control block for ram area */
> T_KERNEL_CYCCB_RAM kernel_cyccb_ram[1];
>
> /* cyclic handler control block table */
> T_KERNEL_CYCCB_RAM *kernel_cyccb_ram_tbl[1] =
> {
> &kernel_cyccb_ram[0],
> };
>
> ~【途中省略】~
>
> /* ------------------------------------------ */
> /* initialize functions */
> /* ------------------------------------------ */
>
> /* object initialize */
> void kernel_cfg_init(void)
> {
>
> ~【途中省略】~
>
> /* initialize cyclic handler control block */
> for ( i = 0; i < 1; i++ )
> {
> kernel_cyccb_ram[i].cyccb_rom = &kernel_cyccb_rom[i];
> }
>
> /* initialize interrupt table */
> kernel_intcb_tbl[SysTick_IRQn-(-14)].exinf = (VP_INT)(0);
> kernel_intcb_tbl[SysTick_IRQn-(-14)].isr = (FP)(OsWrapper_interruptSysTick);
> kernel_intcb_tbl[USART1_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_1);
> kernel_intcb_tbl[USART1_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> kernel_intcb_tbl[USART2_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_2);
> kernel_intcb_tbl[USART2_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> kernel_intcb_tbl[USART3_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_3);
> kernel_intcb_tbl[USART3_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> kernel_intcb_tbl[UART4_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_4);
> kernel_intcb_tbl[UART4_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> kernel_intcb_tbl[UART5_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_5);
> kernel_intcb_tbl[UART5_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> kernel_intcb_tbl[I2C1_EV_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_1);
> kernel_intcb_tbl[I2C1_EV_IRQn-(-14)].isr = (FP)(Iic_interruptEvent);
> kernel_intcb_tbl[I2C1_ER_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_1);
> kernel_intcb_tbl[I2C1_ER_IRQn-(-14)].isr = (FP)(Iic_interruptError);
> kernel_intcb_tbl[I2C2_EV_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_2);
> kernel_intcb_tbl[I2C2_EV_IRQn-(-14)].isr = (FP)(Iic_interruptEvent);
> kernel_intcb_tbl[I2C2_ER_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_2);
> kernel_intcb_tbl[I2C2_ER_IRQn-(-14)].isr = (FP)(Iic_interruptError);
> kernel_intcb_tbl[TIM1_BRK_TIM15_IRQn-(-14)].exinf = (VP_INT)(PWM_CHANNEL_1);
> kernel_intcb_tbl[TIM1_BRK_TIM15_IRQn-(-14)].isr = (FP)(Pwm_interrupt);
> kernel_intcb_tbl[EXTI9_5_IRQn-(-14)].exinf = (VP_INT)(IOPORT_LINE_6);
> kernel_intcb_tbl[EXTI9_5_IRQn-(-14)].isr = (FP)(IoPort_interrupt);
> kernel_intcb_tbl[USB_LP_CAN_RX0_IRQn-(-14)].exinf = (VP_INT)(USB_CHANNEL_1);
> kernel_intcb_tbl[USB_LP_CAN_RX0_IRQn-(-14)].isr = (FP)(USB_LP_CAN1_RX0_IRQHandler);
> kernel_intcb_tbl[TIM4_IRQn-(-14)].exinf = (VP_INT)(0);
> kernel_intcb_tbl[TIM4_IRQn-(-14)].isr = (FP)(TIMx_IRQHandler);
> }
> ~【後半省略】
>
>
>
> 割込みの優先度の設定は、
> stm32f30x.h 内で、
>
> ~【前半省略】
> /**
> * @brief STM32F30X Interrupt Number Definition, according to the selected device
> * in @ref Library_configuration_section
> */
> typedef enum IRQn
> {
> /****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/
> NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
> MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */
> BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */
> UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */
> SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */
> DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */
> PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */
> SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
> /****** STM32 specific Interrupt Numbers **********************************************************************/
> WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
> PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
> TAMPER_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts */
> RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI lines 17, 19 & 20 */
> FLASH_IRQn = 4, /*!< FLASH global Interrupt */
> ~【以下省略】
>
> のようになっております。
> 何分、勉強不足で、見当違いの質問でしたら申し訳ないのですが、
> この中で、kernel_cyccb_rom[1] 内に定義している、OsWrapper_enterTimerCyclicHandler()
> 関数が、OSのタイマ処理の部分かなと考えておりますが、この認識で合って
> おりますでしょうか?
> また、上記した通り、OSタイマをTIM6等他のBasic Timerを使うようにする
> 方法や、その割込みレベルを最低に設定する方法に関して、アドバイスいた
> だけると非常にありがたいです。
>
> よろしくお願いいたします。
Reply to #78476

Reply to #78477×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-08 19:51 by masayuki_arai #78481)

[メッセージ #78477 への返信]

hamayan様、アドバイスありがとうございます。
優先度の設定に関してですが、プログラムコードを解析した限りでは、
NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) という関数で、設定
されているのではないかと思います。
この関数内は、

__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */
else {
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */
}

と記述されており、
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
で呼び出されている為、

SysTick_IRQ = -1、
__NVIC_PRIO_BITS = 4 の為、
(1<<__NVIC_PRIO_BITS) - 1) = 15

となっております。
この為、

if(IRQn < 0) {
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */

の方が実行されていますが、
priority=15、__NVIC_PRIO_BITS=4
の場合、((priority << (8 - __NVIC_PRIO_BITS)) & 0xff) の部分は、0 となり、
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = 0
    ↓
SCB->SHP[15-4] = 0
    ↓
SCB->SHP[11] = 0
となっていると思います。

STマイクロから提供されているプログラムコードの、core_cm4.h 内で、

【~前半省略】
/** \brief Structure type to access the System Control Block (SCB).
*/
typedef struct
{
__I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
__IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
__IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
__IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */  ←★☆★☆この部分
__IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
__IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
__IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
__IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
__IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
__IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
__IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
__I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
__I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
__I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
__I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
__I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
uint32_t RESERVED0[5];
__IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
} SCB_Type;

【~途中省略~】

#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */

【~以下省略】

となっており、
__IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */

System Handlers Priority Registerの設定が、要素11が0となっておりますが、
これは優先順位がいくつに設定されていることになるのかと言うところが
わかりません。

それとも、まったく見当違いの部分を解析している感じでしょうか?
私の知識が不足しており、的を射たお返事ができず、申し訳ないのですが、
アドバイスいただけるとありがたいです。


> OsWrapper_enterTimerCyclicHandler()
> > 関数が、OSのタイマ処理の部分かなと考えておりますが、この認識で合って
> > おりますでしょうか?
>
> よく判らないですが、関数名からは周期ハンドラに関する処理に思えます。
> 周期ハンドラであればタイマー処理の一部ではありますが、全体ではありません。
>
> systic割り込みの優先度レベルが問題なっているのですから、まず優先度が幾つに設定されているのかを調べてみては如何でしょう。
>
>
>
> [メッセージ #78476 への返信]
> > 初めまして、現在、STマイクロ社のSTM32F302のファームウェアにてHOSを動作
> > させ、ステッピングモータの制御等を実施しております。
> > 私の方は、今までマイコン制御ソフトウェアの開発経験がほとんどないのですが、
> > C言語のプログラミング経験はあります。
> >
> > ここ1か月程度、前任者が制作した上記のファームウェアを色々解析したり、
> > いじくったりしていました。
> > 今回、このファームウェアで、USB-CDCのシリアル通信機能を実装する必要が
> > あり、STマイクロ社のサイトよりダウンロードした、STM32F302用のUSB-CDC
> > 通信のサンプルプログラムを参考に、元々のファームウェアプログラムに
> > USB-CDC通信処理を入れ込みました。
> > マイコンファームウェアがUSB-CDC通信を実施する相手側は、WindowsPCで、
> > WindowsPC側は、STマイクロ社が提供しているUSBデバイスドライバにより、
> > 仮想COMポートとして認識し、このCOM Portに対してシリアル通信を実行する
> > ことにより、通信する構成となっています。
> >
> > USB-CDCシリアル通信処理は正常に行えるようになったのですが、USBケーブル
> > 接続時に、PC側からシリアルCOM Portのオープン処理に、1分半~3分程度の時間
> > がかかってしまう現象が発生しており、なかなか解決できず、困っております。
> >
> > STマイクロ社のUSB-CDCサンプルプログラムのプロジェクトを単体で実行した
> > 場合は、このような、オープン処理が遅い現象は発生しません。
> >
> > STマイクロ社の方に色々と相談していたのですが、STマイクロ社・社内の
> > USB-CDCサンプルプログラムのTipsのようなものに、
> >
> > > RTOSはOSのタイマをSysTickにアサインすることが多く、また最低の
> > > プライオリティ割り込みを使うように設計されている場合が多いです。
> > > しかし、USB-CDCサンプルプログラムの構造上、SysTickは最高の
> > > プライオリティで使うことを想定しているため、矛盾が生じてしまい
> > > ます。
> > > 対策は、OSのタイマはTIM6などのBasic Timerを使うようにして、
> > > その割込みレベルを最低に設定してください。
> >
> > との記載があり、この設定を実施してみてほしいと話がありましたが、HOSの
> > タイマをTIM6などのTimerを使うようにする設定方法と、その割込みレベルを
> > 最低に設定する方法がわかりません。
> >
> > 現在の、プログラムコードでは、
> > kernel_cfg.c にて、
> >
> > ~【前半省略】
> > /* ------------------------------------------ */
> > /* create cyclic handler objects */
> > /* ------------------------------------------ */
> >
> > /* cyclic handler control block for rom area */
> > const T_KERNEL_CYCCB_ROM kernel_cyccb_rom[1] =
> > {
> > {(ATR)(TA_HLNG), (VP_INT)(0), (FP)(OsWrapper_enterTimerCyclicHandler), (RELTIM)(1)},
> > };
> >
> > /* cyclic handler control block for ram area */
> > T_KERNEL_CYCCB_RAM kernel_cyccb_ram[1];
> >
> > /* cyclic handler control block table */
> > T_KERNEL_CYCCB_RAM *kernel_cyccb_ram_tbl[1] =
> > {
> > &kernel_cyccb_ram[0],
> > };
> >
> > ~【途中省略】~
> >
> > /* ------------------------------------------ */
> > /* initialize functions */
> > /* ------------------------------------------ */
> >
> > /* object initialize */
> > void kernel_cfg_init(void)
> > {
> >
> > ~【途中省略】~
> >
> > /* initialize cyclic handler control block */
> > for ( i = 0; i < 1; i++ )
> > {
> > kernel_cyccb_ram[i].cyccb_rom = &kernel_cyccb_rom[i];
> > }
> >
> > /* initialize interrupt table */
> > kernel_intcb_tbl[SysTick_IRQn-(-14)].exinf = (VP_INT)(0);
> > kernel_intcb_tbl[SysTick_IRQn-(-14)].isr = (FP)(OsWrapper_interruptSysTick);
> > kernel_intcb_tbl[USART1_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_1);
> > kernel_intcb_tbl[USART1_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> > kernel_intcb_tbl[USART2_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_2);
> > kernel_intcb_tbl[USART2_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> > kernel_intcb_tbl[USART3_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_3);
> > kernel_intcb_tbl[USART3_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> > kernel_intcb_tbl[UART4_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_4);
> > kernel_intcb_tbl[UART4_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> > kernel_intcb_tbl[UART5_IRQn-(-14)].exinf = (VP_INT)(UART_CHANNEL_5);
> > kernel_intcb_tbl[UART5_IRQn-(-14)].isr = (FP)(Uart_interrupt);
> > kernel_intcb_tbl[I2C1_EV_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_1);
> > kernel_intcb_tbl[I2C1_EV_IRQn-(-14)].isr = (FP)(Iic_interruptEvent);
> > kernel_intcb_tbl[I2C1_ER_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_1);
> > kernel_intcb_tbl[I2C1_ER_IRQn-(-14)].isr = (FP)(Iic_interruptError);
> > kernel_intcb_tbl[I2C2_EV_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_2);
> > kernel_intcb_tbl[I2C2_EV_IRQn-(-14)].isr = (FP)(Iic_interruptEvent);
> > kernel_intcb_tbl[I2C2_ER_IRQn-(-14)].exinf = (VP_INT)(IIC_CHANNEL_2);
> > kernel_intcb_tbl[I2C2_ER_IRQn-(-14)].isr = (FP)(Iic_interruptError);
> > kernel_intcb_tbl[TIM1_BRK_TIM15_IRQn-(-14)].exinf = (VP_INT)(PWM_CHANNEL_1);
> > kernel_intcb_tbl[TIM1_BRK_TIM15_IRQn-(-14)].isr = (FP)(Pwm_interrupt);
> > kernel_intcb_tbl[EXTI9_5_IRQn-(-14)].exinf = (VP_INT)(IOPORT_LINE_6);
> > kernel_intcb_tbl[EXTI9_5_IRQn-(-14)].isr = (FP)(IoPort_interrupt);
> > kernel_intcb_tbl[USB_LP_CAN_RX0_IRQn-(-14)].exinf = (VP_INT)(USB_CHANNEL_1);
> > kernel_intcb_tbl[USB_LP_CAN_RX0_IRQn-(-14)].isr = (FP)(USB_LP_CAN1_RX0_IRQHandler);
> > kernel_intcb_tbl[TIM4_IRQn-(-14)].exinf = (VP_INT)(0);
> > kernel_intcb_tbl[TIM4_IRQn-(-14)].isr = (FP)(TIMx_IRQHandler);
> > }
> > ~【後半省略】
> >
> >
> >
> > 割込みの優先度の設定は、
> > stm32f30x.h 内で、
> >
> > ~【前半省略】
> > /**
> > * @brief STM32F30X Interrupt Number Definition, according to the selected device
> > * in @ref Library_configuration_section
> > */
> > typedef enum IRQn
> > {
> > /****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/
> > NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
> > MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */
> > BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */
> > UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */
> > SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */
> > DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */
> > PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */
> > SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
> > /****** STM32 specific Interrupt Numbers **********************************************************************/
> > WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
> > PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
> > TAMPER_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts */
> > RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI lines 17, 19 & 20 */
> > FLASH_IRQn = 4, /*!< FLASH global Interrupt */
> > ~【以下省略】
> >
> > のようになっております。
> > 何分、勉強不足で、見当違いの質問でしたら申し訳ないのですが、
> > この中で、kernel_cyccb_rom[1] 内に定義している、OsWrapper_enterTimerCyclicHandler()
> > 関数が、OSのタイマ処理の部分かなと考えておりますが、この認識で合って
> > おりますでしょうか?
> > また、上記した通り、OSタイマをTIM6等他のBasic Timerを使うようにする
> > 方法や、その割込みレベルを最低に設定する方法に関して、アドバイスいた
> > だけると非常にありがたいです。
> >
> > よろしくお願いいたします。

Reply to #78477

Reply to #78481×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-09 00:59 by hamayan #78485)

> priority=15、__NVIC_PRIO_BITS=4
> の場合、((priority << (8 - __NVIC_PRIO_BITS)) & 0xff) の部分は、0 となり、

priorityを4bit左シフトしているので、0xf0ですね。
STM32F4の場合は優先度は4bitの16レベルになります。
この内0がもっとも優先度が高く、15が最低になります。
また割込み優先度レジスタの各割込み要因毎に8bitの領域がありますが、STM32Fで有効なのは上位の4bitのみなので、
(priority << (8 - __NVIC_PRIO_BITS)) & 0xff
この様な式になっているのだと思われます。

つまり前任の方はシステムタイマーの割込みレベルを最低に設定していた可能性が出てきました。

以下の関数も用意されていますので、これで確認も可能かと思われます。

/** \brief Get Interrupt Priority

This function reads the priority for the specified interrupt. The interrupt
number can be positive to specify an external (device specific)
interrupt, or negative to specify an internal (core) interrupt.

The returned priority value is automatically aligned to the implemented
priority bits of the microcontroller.

\param [in] IRQn Number of the interrupt for get priority
\return Interrupt Priority
*/
static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
{

if(IRQn < 0) {
return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */
else {
return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
}

なお
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
は、
NVIC_SetPriority (SysTick_IRQn, 15);
で良いと思いますね。
Reply to #78481

Reply to #78485×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-09 11:07 by masayuki_arai #78491)

[メッセージ #78485 への返信]
hamayan様

返信ありがとうございます。

> > priority=15、__NVIC_PRIO_BITS=4
> > の場合、((priority << (8 - __NVIC_PRIO_BITS)) & 0xff) の部分は、0 となり、
>
> priorityを4bit左シフトしているので、0xf0ですね。

ご指摘ありがとうございます。
priority=15と書いておきながら、頭の中で16で計算してしまっておりました。
ご指摘の通り、0ではなく、0xf0ですね。

また、割込み優先度レジスタの説明も丁寧に書いていただき、非常に勉強になります。
まず、SysTick割込みの優先順位を最高に設定する為に、priority=0で関数を呼ぶ
ように修正してみようと思います。
また、割込み優先順位の確認用の関数もご紹介いただき、ありがとうございます!
正常に設定されたかどうか、確認する際に使ってみたいと思います。

それと、もう一点、
最初に書きました通り、STマイクロ社から、
> RTOSはOSのタイマをSysTickにアサインすることが多く、また最低の
> プライオリティ割り込みを使うように設計されている場合が多いです。
> しかし、USB-CDCサンプルプログラムの構造上、SysTickは最高の
> プライオリティで使うことを想定しているため、矛盾が生じてしまい
> ます。
> 対策は、OSのタイマはTIM6などのBasic Timerを使うようにして、
> その割込みレベルを最低に設定してください。
との話があり、この中のOSのタイマをTIM6などのBasic Timerを使うように
する為には、どの部分を修正すればよいのでしょうか?

現在、system.cfg の中身は、下記のようになっております。



/* ------------------------------------------------------------------------ */
/* Hyper Operating System V4 μITRON4.0仕様 Real-Time OS */
/* コンフィギュレーションファイル */
/* */
/* Copyright (C) 1998-2002 by Project HOS */
/* http://sourceforge.jp/projects/hos/ */
/* ------------------------------------------------------------------------ */

/* HOS 独自の設定 */
HOS_KERNEL_HEAP(1536); /* カーネルヒープの設定(省略時 0) */
HOS_MAX_SEMID(64); /* 最大セマフォID番号 */
HOS_MIN_INTNO(-14); /* 割り込み番号の最小値(省略時 0) */
HOS_MAX_INTNO(81); /* 割り込み番号の最大値(省略時 0) */
HOS_TIM_TIC(1, 1); /* タイムティックの設定(省略時 1/1 ) */
HOS_IDL_STK(192, NULL); /* IDLEスタックの設定 */

/* インクルードファイルの指定 */
INCLUDE("\"commandtask.h\"");
INCLUDE("\"timertask.h\"");
INCLUDE("\"stm32f30x.h\"");
INCLUDE("\"uart.h\"");
INCLUDE("\"iic.h\"");
INCLUDE("\"pwm.h\"");
INCLUDE("\"encodertask.h\"");
INCLUDE("\"ioport.h\"");

/* USBを追加 */
INCLUDE("\"main.h\"");
INCLUDE("\"stm32f3xx_it.h\"");
INCLUDE("\"usb.h\"");

/* 2016.07.13 <Arai> TIMx Timerを追加 */
//INCLUDE("\"usbd_cdc_interface.h\"");
INCLUDE("\"stm32f3xx_it.h\"");

/* 割込時スタックの設定 */
HOS_INT_STK(512, NULL);

/* 割込ハンドラの登録 */
ATT_ISR({TA_HLNG, 0, SysTick_IRQn, OsWrapper_interruptSysTick});
ATT_ISR({TA_HLNG, UART_CHANNEL_1, USART1_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_2, USART2_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_3, USART3_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_4, UART4_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_5, UART5_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, IIC_CHANNEL_1, I2C1_EV_IRQn, Iic_interruptEvent});
ATT_ISR({TA_HLNG, IIC_CHANNEL_1, I2C1_ER_IRQn, Iic_interruptError});
ATT_ISR({TA_HLNG, IIC_CHANNEL_2, I2C2_EV_IRQn, Iic_interruptEvent});
ATT_ISR({TA_HLNG, IIC_CHANNEL_2, I2C2_ER_IRQn, Iic_interruptError});
ATT_ISR({TA_HLNG, PWM_CHANNEL_1, TIM1_BRK_TIM15_IRQn, Pwm_interrupt});
ATT_ISR({TA_HLNG, IOPORT_LINE_6, EXTI9_5_IRQn, IoPort_interrupt});

/* USBを追加 nakajima */
// ATT_ISR({TA_HLNG, USB_CHANNEL_1, USB_HP_CAN1_TX_IRQn, USB_HP_CAN1_TX_IRQHandler});
ATT_ISR({TA_HLNG, USB_CHANNEL_1, USB_LP_CAN_RX0_IRQn, USB_LP_CAN1_RX0_IRQHandler});

/* 2016.08.04 <Arai> TIM3 TimerをTIM4 Timerに変更 */
///* 2016.07.13 <Arai> TIM3 Timerを追加 */
//ATT_ISR({TA_HLNG, 0, TIM3_IRQn, TIMx_IRQHandler});
ATT_ISR({TA_HLNG, 0, TIM4_IRQn, TIMx_IRQHandler});


/* タスクの生成 (※タスク優先度は数字が小さいほうが優先されます) */
CRE_TSK(ID_TASK_COMMAND, {TA_HLNG | TA_ACT, 0, CommandTask_executeTask, 6, 1024, NULL});
CRE_TSK(ID_TASK_TIMER, {TA_HLNG, 0, TimerTask_executeTask, 4, 700, NULL});
CRE_TSK(ID_TASK_ENCODER, {TA_HLNG, 0, EncoderTask_executeTask, 2, 512, NULL});

/* イベントフラグの生成 */
CRE_FLG(ID_FLAG_COMMANDTASK, {TA_TFIFO | TA_WSGL | TA_CLR, 0});
CRE_FLG(ID_FLAG_TIMERTASK, {TA_TFIFO | TA_WSGL | TA_CLR, 0});

/* セマフォの生成 */
CRE_SEM(ID_SEM_ALARM, {TA_TFIFO, 1, 1});
CRE_SEM(ID_SEM_ALARM_ALWAYS, {TA_TFIFO, 1, 1});
CRE_SEM(ID_SEM_PRIORITY_ALARM, {TA_TFIFO, 1, 1});
CRE_SEM(ID_SEM_PRIORITY_ALARM_ALWAYS, {TA_TFIFO, 1, 1});
CRE_SEM(ID_SEM_EEPROM, {TA_TFIFO, 1, 1});
CRE_SEM(ID_SEM_LINKEDLIST, {TA_TFIFO, 1, 1});
CRE_SEM(ID_SEM_ENCODER, {TA_TFIFO, 0, 1});

/* メールボックスの生成 */

/* DATA QUEUE */

/* 周期タイマの生成 */
CRE_CYC(ID_CYC_TIMERTASK, {TA_HLNG, 0, OsWrapper_enterTimerCyclicHandler, 1, 0});

/* ------------------------------------------------------------------------ */
/* Copyright (C) 1998-2002 by Project HOS */
/* ------------------------------------------------------------------------ */



上記の中の、
/* 割込ハンドラの登録 */
ATT_ISR({TA_HLNG, 0, SysTick_IRQn, OsWrapper_interruptSysTick});

の部分を、
/* 割込ハンドラの登録 */
ATT_ISR({TA_HLNG, 0, TIM6_IRQn, OsWrapper_interruptSysTick});

に修正して、kernel_cfg.c を生成し、上記でご教授いただいた、
NVIC_SetPriority (SysTick_IRQn, 15);

と同等のプログラムコードの部分で、

NVIC_SetPriority (SysTick_IRQn, 0); /* SysTick割込み優先度最高に設定*/
NVIC_SetPriority (TIM6_IRQn, 15); /* HOSのタイマをTIM6使用し優先度最低に設定*/

のように修正すれば良いでしょうか?
重ね重ね質問ばかりで申し訳ないのですが、ご教授いただけるとありがたいです。
Reply to #78485

Reply to #78491×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-09 11:22 by hamayan #78492)

> それと、もう一点、
> 最初に書きました通り、STマイクロ社から、
> > RTOSはOSのタイマをSysTickにアサインすることが多く、また最低の
> > プライオリティ割り込みを使うように設計されている場合が多いです。
> > しかし、USB-CDCサンプルプログラムの構造上、SysTickは最高の
> > プライオリティで使うことを想定しているため、矛盾が生じてしまい
> > ます。
> > 対策は、OSのタイマはTIM6などのBasic Timerを使うようにして、
> > その割込みレベルを最低に設定してください。
> との話があり、この中のOSのタイマをTIM6などのBasic Timerを使うように
> する為には、どの部分を修正すればよいのでしょうか?
>
> 現在、system.cfg の中身は、下記のようになっております。
>

> /* 割込ハンドラの登録 */
> ATT_ISR({TA_HLNG, 0, SysTick_IRQn, OsWrapper_interruptSysTick});
ここを

// ATT_ISR({TA_HLNG, 0, SysTick_IRQn, OsWrapper_interruptSysTick});
ATT_ISR({TA_HLNG, 0, TIM6_IRQn, OsWrapper_interruptSysTick});
この様に書き換えて、TIM6を1ms周期で割込みが発生する様に書き換えたら如何でしょうか?この時、TIM6の割込みの優先度はSysTick割込みより低くします。
と言いますか、RTOSで使用する割込みは全てSysTickと、もしかしたらUSB関連の
割込み優先度よりも低く設定して置く必要があるかもしれません。

そうすれば、OSの伺い知らないところでUSB関連の処理が実行されると思われます。
ただ、タスクの中で割込み禁止を入れた場合、その影響がどうなるか判りません。

しかし、USB廻りのタイミングの問題は、USBアナライザー等で確認した方が良い気がしないでも無いです。

Reply to #78491

Reply to #78492×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-09 21:15 by masayuki_arai #78493)

[メッセージ #78492 への返信]
hamayan様、ありがとうございます。

取り敢えず、下記のアドバイスの通り、TIM6の割込みで、OsWrapper_interruptSysTick
を起動させたいのですが、うまく動作してくれません。

> > /* 割込ハンドラの登録 */
> > ATT_ISR({TA_HLNG, 0, SysTick_IRQn, OsWrapper_interruptSysTick});
> ここを
>
> // ATT_ISR({TA_HLNG, 0, SysTick_IRQn, OsWrapper_interruptSysTick});
> ATT_ISR({TA_HLNG, 0, TIM6_IRQn, OsWrapper_interruptSysTick});
> この様に書き換えて、TIM6を1ms周期で割込みが発生する様に書き換えたら如何でしょうか?この時、TIM6の割込みの優先度はSysTick割込みより低くします。

system.cfg の /*割り込みハンドラの登録*/ の部分を下記のように
修正しました。

★☆★☆ここから
【~前半省略】
/* 割込ハンドラの登録 */
ATT_ISR({TA_HLNG, 0, TIM6_DAC_IRQn, OsWrapper_interruptSysTick});
ATT_ISR({TA_HLNG, UART_CHANNEL_1, USART1_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_2, USART2_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_3, USART3_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_4, UART4_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, UART_CHANNEL_5, UART5_IRQn, Uart_interrupt});
ATT_ISR({TA_HLNG, IIC_CHANNEL_1, I2C1_EV_IRQn, Iic_interruptEvent});
ATT_ISR({TA_HLNG, IIC_CHANNEL_1, I2C1_ER_IRQn, Iic_interruptError});
ATT_ISR({TA_HLNG, IIC_CHANNEL_2, I2C2_EV_IRQn, Iic_interruptEvent});
ATT_ISR({TA_HLNG, IIC_CHANNEL_2, I2C2_ER_IRQn, Iic_interruptError});
ATT_ISR({TA_HLNG, PWM_CHANNEL_1, TIM1_BRK_TIM15_IRQn, Pwm_interrupt});

【~途中省略~】

/* タスクの生成 (※タスク優先度は数字が小さいほうが優先されます) */
CRE_TSK(ID_TASK_COMMAND, {TA_HLNG | TA_ACT, 0, CommandTask_executeTask, 6, 1024, NULL});

【~以下省力】
★☆★☆ここまで


※修正したのは、
ATT_ISR({TA_HLNG, 0, TIM6_DAC_IRQn, OsWrapper_interruptSysTick});
の部分だけです。

割込みの周期の設定や、割込みの起動部分は、既存のプログラム内で上記の通り、
TIM1_BRK_TIM15_IRQn を使っていたため、このTIM15の設定や起動部分の
コードを真似て、下記のように追加しました。

以下が追加したプログラムコードです。


☆★☆★ここから
#define PWM_INITIAL_FREQUENCY (1000)

// OsWrapper_interruptSysTick用を作成 2016.08.09
struct Pwm2 {
uint32_t frequency;
// interrupt
uint32_t interruptCycle;

bool busy;
bool stopRequest;
TIM_TypeDef *timModule;
};

// OsWrapper_interruptSysTick用を作成 2016.08.09
typedef struct Pwm2 Pwm2;

// OsWrapper_interruptSysTick用を作成 2016.08.09
static Pwm2 *OsWrapperInstance;

// OsWrapper_interruptSysTick用を作成 2016.08.09
static void OsWrapper_construct(Pwm2 *self);

static void Pwm_initializeTimer(Pwm *self);

// OsWrapper_interruptSysTick用を作成 2016.08.09
static void OsWrapper_initializeTimer(Pwm2 *self);



// OsWrapper_interruptSysTick用を作成 2016.08.09
Pwm2 *OsWrapper_new()
{
Pwm2 *self;
self = (Pwm2 *)MemoryAllocator_allocate(sizeof(Pwm2));
assert(self);
OsWrapper_construct(self);
OsWrapperInstance = self;
return self;
}

// OsWrapper_interruptSysTick用を作成 2016.08.09
static void OsWrapper_construct(Pwm2 *self)
{
self->frequency = PWM_INITIAL_FREQUENCY;

RCC->APB2ENR |= RCC_APB1ENR_TIM6EN;
self->timModule = TIM6;
OsWrapper_initializeTimer(self);
ena_int(TIM6_DAC_IRQn);

// 周期タイマーをStartさせるため取り敢えず追加してみる
self->timModule->EGR |= TIM_EGR_UG;
self->timModule->SR &= ~TIM_SR_UIF;
self->timModule->CR1 |= TIM_CR1_CEN;
self->timModule->DIER |= TIM_DIER_UIE;

}

// OsWrapper_interruptSysTick用を作成 2016.08.09
static void OsWrapper_initializeTimer(Pwm2 *self)
{
uint32_t coreClock = Processor_getSystemClock();
self->timModule->CR1 |= TIM_CR1_ARPE;
self->timModule->BDTR |= TIM_BDTR_MOE;
self->timModule->CCMR1 &= ~TIM_CCMR1_OC1M;
self->timModule->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // PWM Mode1
self->timModule->CCER = 0x7;
self->timModule->ARR = coreClock / self->frequency - 1;
self->timModule->CCR1 = (coreClock / self->frequency - 1) / 2;
self->timModule->PSC = PWM_PRESCALE_VALUE - 1;
self->timModule->CCR1 = 1;
}
☆★☆★ここまで


上記、system.cfg 内で定義している、
/* タスクの生成 (※タスク優先度は数字が小さいほうが優先されます) */
CRE_TSK(ID_TASK_COMMAND, {TA_HLNG | TA_ACT, 0, CommandTask_executeTask, 6, 1024, NULL});

の、CommandTask_executeTask() 関数から、
// OsWrapper_interruptSysTick用を作成 2016.08.09
pwm2 = OsWrapper_new();

を実行していますが、上記の改造では、OsWrapper_interruptSysTick() 関数の周期起動が
かかりません。
(OsWrapper_interruptSysTick() 関数内のブレークに引っかからないです)

私がよく理解できていない部分は、

uint32_t coreClock = Processor_getSystemClock();
self->timModule->CR1 |= TIM_CR1_ARPE;
self->timModule->BDTR |= TIM_BDTR_MOE;
self->timModule->CCMR1 &= ~TIM_CCMR1_OC1M;
self->timModule->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // PWM Mode1
self->timModule->CCER = 0x7;
self->timModule->ARR = coreClock / self->frequency - 1;
self->timModule->CCR1 = (coreClock / self->frequency - 1) / 2;
self->timModule->PSC = PWM_PRESCALE_VALUE - 1;
self->timModule->CCR1 = 1;

や、

// 周期タイマーをStartさせるため取り敢えず追加してみる
self->timModule->EGR |= TIM_EGR_UG;
self->timModule->SR &= ~TIM_SR_UIF;
self->timModule->CR1 |= TIM_CR1_CEN;
self->timModule->DIER |= TIM_DIER_UIE;

の部分で、stm32f30x.h ファイル内で、下記の構造体が定義されている部分です。

/**
* @brief TIM
*/
typedef struct
{
__IO uint16_t CR1; /*!< TIM control register 1, Address offset: 0x00 */
uint16_t RESERVED0; /*!< Reserved, 0x02 */
__IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */
__IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */
__IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */
__IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */
__IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */
__IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
__IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
__IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */
__IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */
__IO uint16_t PSC; /*!< TIM prescaler, Address offset: 0x28 */
uint16_t RESERVED9; /*!< Reserved, 0x2A */
__IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */
__IO uint16_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */
uint16_t RESERVED10; /*!< Reserved, 0x32 */
__IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */
__IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */
__IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */
__IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */
__IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */
__IO uint16_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */
uint16_t RESERVED12; /*!< Reserved, 0x4A */
__IO uint16_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */
uint16_t RESERVED13; /*!< Reserved, 0x4E */
__IO uint16_t OR; /*!< TIM option register, Address offset: 0x50 */
__IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */
__IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */
__IO uint32_t CCR6; /*!< TIM capture/compare register 4, Address offset: 0x5C */
} TIM_TypeDef;

これらのレジスタの値の設定がよくわかりません。
既存のTIM15のプログラムコードを真似ているせいで、余計なものが入ったり
設定が間違っている可能性が高いと思っています。

OsWrapper_interruptSysTickをTIM6を使って1ms周期でタイマー起動させる為に
どの項目を、どのような値に設定すればよいか、アドバイスいただけませんでしょうか?


また、
static void OsWrapper_construct(Pwm2 *self) 内の、
RCC->APB2ENR |= RCC_APB1ENR_TIM6EN;
の部分も、これで合っているのかどうかがよくわかっていません。
他にも、割込みを起動させるために、不足や間違いがあれば、アドバイスいただけると
非常にありがたいです。

何度もお手数をおかけし、申し訳ありません。よろしくお願いいたします。
Reply to #78492

Reply to #78493×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-09 21:43 by hamayan #78494)

とりあえず、タイマーは何を使っても構わないですよ。
TIM3やTIM4は使った形跡がありますし、TIM3かTIM4のどちらかを使ってタイムティックの供給をしてみては如何でしょう。
また、タイムティックの供給はisig_tim();を呼び出すだけです。


Reply to #78493

Reply to #78494×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login

Re: 周期タイマー割り込みの優先順位設定に関して (2016-08-09 22:35 by masayuki_arai #78495)

[メッセージ #78494 への返信]
hamayan様

早速の返信ありがとうございます。

> とりあえず、タイマーは何を使っても構わないですよ。
> TIM3やTIM4は使った形跡がありますし、TIM3かTIM4のどちらかを使ってタイムティックの供給をしてみては如何でしょう。
> また、タイムティックの供給はisig_tim();を呼び出すだけです。

TIM4でもやってみたのですが、うまく動作させられませんでした。
TIM4の方は、現状、USB-CDC通信のメッセージ送信用の周期起動タイマーとして
使っているのですが、その部分を流用して、(USB-CDCの送信タイマー割込みとしての
処理部分はとりあえずコメントアウトして)

system.cfgで、

/* 割込ハンドラの登録 */
ATT_ISR({TA_HLNG, 0, TIM4_IRQn, OsWrapper_interruptSysTick});

と記述し、kernel_cfg.c を生成、

void CommandTask_executeTask(VP_INT exinf)
関数内で、

TIMx_CLK_ENABLE();
HAL_NVIC_SetPriority(TIM4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(TIM4_IRQn);
TIM_Config();
if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
{
// Error_Handler();
}

と記述しました。
↑上記のあたりは、修正前のプログラムコードでは、USBケーブルが接続されたときに、
割込みで呼ばれる処理内に記載されており、この処理でTIM4のタイマーが起動開始します。

別途、既存のヘッダファイル内で、

#define TIMx_CLK_ENABLE __HAL_RCC_TIM4_CLK_ENABLE

#define __HAL_RCC_TIM4_CLK_ENABLE() do { \
__IO uint32_t tmpreg; \
SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM4EN);\
/* Delay after an RCC peripheral clock enabling */ \
tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM4EN);\
UNUSED(tmpreg); \
} while(0)

と定義されています。

/**
* @brief TIM_Config: Configure TIMx timer
* @param None.
* @retval None.
*/
void TIM_Config(void)
{
/* Set TIMx instance */
TimHandle.Instance = TIMx;

/* Initialize TIM4 peripheral as follow:
+ Period = 10000 - 1
+ Prescaler = ((SystemCoreClock/2)/10000) - 1
+ ClockDivision = 0
+ Counter direction = Up
*/
TimHandle.Init.Period = (CDC_POLLING_INTERVAL*1000) - 1;
TimHandle.Init.Prescaler = 84-1;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
}


現状、TIM4やTIM6で周期起動させようとしている、
OsWrapper_interruptSysTick() 関数内で、isig_tim(); を実行しています。

ですが、
void CommandTask_executeTask(VP_INT exinf)
関数内で、
TIM4タイマーの設定処理を通った後、
if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
が実行された後、この中で止まってしまい、それ以降のプログラムが実行
されなくなってしまいました。
この状態で、OsWrapper_interruptSysTick() 関数は周期的に実行されて
いる=isig_tim(); も実行されているのですが(isig_tim();の部分にブレークを
張っておくと繰り返し止まる)、CommandTask_executeTask()関数の方の
それ以降の処理が動作しなくなってしまいます。

具体的には、HAL_TIM_Base_Start_IT() 関数内の、

/**
* @brief Starts the TIM Base generation in interrupt mode.
* @param htim: TIM handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));

/* Enable the TIM Update interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);

/* Enable the Peripheral */
__HAL_TIM_ENABLE(htim);
↑↑↑↑↑↑↑↑この行を実行し、以降の行に処理が進みません。

色々と試してみているのですが、まったく上手くいかず、どうすれば良いのか
わからなくなってしまっています。

void OsWrapper_interruptSysTick(VP_INT exinf)
{
isig_tim();
}
OsWrapper_interruptSysTick() 関数内は上記の状態です。

以上です。
Reply to #78494

Reply to #78495×

You can not use Wiki syntax
You are not logged in. To discriminate your posts from the rest, you need to pick a nickname. (The uniqueness of nickname is not reserved. It is possible that someone else could use the exactly same nickname. If you want assurance of your identity, you are recommended to login before posting.) Login