私は現在、等間隔のタイミングで特定のパルス シーケンスを出力するための組み込みシステムに取り組んでいます。したがって、最初のテストとして、FreeRTOS カーネルを搭載した STM32 - DISCO ボードを使用します。TIM1 をトリガーするマスターとして TIM3 を構成しました。TIM1 は、1Hz または毎秒の頻度でトリガーされます。次に、TIM3 はその出力でパルス シーケンスを生成します。TIM3 出力を PB4 に、TIM1 を PA9 に設定しました。この構成は期待どおりに機能しますが、設定を保存し、両方のタイマーを構成する関数へのポインターとして渡すことができる構造体を使用して、その場で構成を変更したいと考えました。
最初のステップとして、データ構造を生成し、タイマー関数で初期化して TIM3 を構成しました。
PG_ERR TIM_Master_Init(void){
PG_HandleTypeDef hPG_timer;
hPG_timer.PLS.Prescaler = 139;
hPG_timer.PLS.Period = 60000;
hPG_timer.PLS.DutyCycle = 30000;
hPG_timer.PLS.RepetitionCounter = 5;
hPG_timer.PLS.PercentChange = 0;
/* Timer3 handler declaration: Master */
TIM_HandleTypeDef TimMasterHandle;
/* Master configuration structure */
TIM_MasterConfigTypeDef sMasterConfig;
/* Output compare structure */
TIM_OC_InitTypeDef sOCConfig;
__TIM3_CLK_ENABLE();
PG_ERR xPGERR = PG_ERR_NONE;
/* Compute the prescaler value to have TIM3 counter clock equal to 60 KHz */
/* Set TIMx instance */
TimMasterHandle.Instance = MASTER_TIM;
/* Master configuration: TIM3 */
TimMasterHandle.Init.Period = 60000 - 1;
TimMasterHandle.Init.Prescaler = 1399;
TimMasterHandle.Init.ClockDivision = 0;
TimMasterHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
if (HAL_TIM_PWM_Init(&TimMasterHandle) != HAL_OK){
xPGERR = PG_ERR_TIM;
}
/* Configure the PWM_channel_1 */
sOCConfig.OCMode = TIM_OCMODE_PWM1;
sOCConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
sOCConfig.OCFastMode = TIM_OCFAST_ENABLE;
sOCConfig.Pulse = 30000;
if (HAL_TIM_PWM_ConfigChannel(&TimMasterHandle, &sOCConfig, TIM_CHANNEL_1) != HAL_OK){
xPGERR = PG_ERR_TIM;
}
/* Configure TIM3 as master & use the update event as Trigger Output (TRGO) */
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if(HAL_TIMEx_MasterConfigSynchronization(&TimMasterHandle, &sMasterConfig) != HAL_OK){
xPGERR = PG_ERR_TIM;
}
/* Start PWM Timer3*/
if(HAL_TIM_PWM_Start(&TimMasterHandle, TIM_CHANNEL_1) != HAL_OK){
xPGERR = PG_ERR_TIM;
}
if(HAL_TIM_Base_Start_IT(&TimMasterHandle) != HAL_OK){
xPGERR = PG_ERR_TIM;
}
return xPGERR;
}
1) この構成では、非常に奇妙な動作が発生します。データ構造を含めた後:
PG_HandleTypeDef hPG_timer;
hPG_timer.PLS.Prescaler = 139;
hPG_timer.PLS.Period = 60000;
hPG_timer.PLS.DutyCycle = 30000;
hPG_timer.PLS.RepetitionCounter = 5;
hPG_timer.PLS.PercentChange = 0;
そのコードが切り取られた後、PIN PB4 (マスター - TIM3) で出力が得られず、1Hz でトグルする必要があります。
2) さらに混乱させるために、コード ブロックをハンドルに置き換えると、次のようになります。
PG_HandleTypeDef hPG_timer;
PG_HandleTypeDef *hPG_timer;
hPG_timer = &hPG_timer_config;
hPG_timer.PLS.Prescaler = 139;
hPG_timer.PLS.Period = 60000;
hPG_timer.PLS.DutyCycle = 30000;
hPG_timer.PLS.RepetitionCounter = 5;
hPG_timer.PLS.PercentChange = 0;
これで、PB4 (マスター - TIM3) の出力が 1Hz で表示されますが、PA9 (スレーブ - TIM1) の出力極性が逆になっています。
問題を調査しようとしましたが、FreeRTOS のスタック/ヒープに注目しました。大きなヒープ/スタック = (uint32_t) 65535; でシステムをテストしました。行動に変化は見られませんでした。
誰かが同様の問題に遭遇したか、これを解決する方法を知っていることを願っています。残念ながら、私は私の知識の終わりにいます。
編集:私は問題にもう少し時間を費やし、より具体的にできると思います。ポインタ使用の場合、TimMasterHandle は初期化直後にロックされます。ハンドルのロックを解除すると、TimMasterHandle.lock = HAL_UNLOCK; すべてうまくいきますが、それは問題を隠しているだけです。これがどこから来ているのか知りたいです。
まだヒープまたはスタックの問題のように見えます。ヒープまたはスタック オーバーフローをチェックする方法はありますか。Keil uVision 5.10 を使用しています。
お時間を割いていただき、ありがとうございました。
アイマー