ch32v307中64位的Systick可以不回繞地一直計(jì)數(shù),是系統(tǒng)很好的一個(gè)絕對(duì)時(shí)標(biāo),不必用中斷而能提供阻塞式的和非阻塞式的延時(shí)。公版的Systick延時(shí)示例不是一個(gè)理想的應(yīng)用方式,它會(huì)復(fù)位計(jì)數(shù)器,只適合單線程的應(yīng)用,我們可以讓它一直計(jì)時(shí)而不重載,要讓它計(jì)滿得幾千年。
為了不浪費(fèi)Systick,想用TIM1替代FreeRtos示例里的Systick,不過(guò)事情很奇怪,重新上電后的第一次運(yùn)行總是出錯(cuò),進(jìn)行一次手工Reset復(fù)位后卻能正常運(yùn)行,而使用Systick不會(huì)發(fā)生。port.c中的代碼如下:
#define CFGR0_PPRE2_Set_Mask? ? ? ?((uint32_t)0x00003800)
/* just for wch's systick,don't have mtime */
void vPortSetupTimerInterrupt( void )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
? ? /* set software is lowest priority */
? ? NVIC_SetPriority(Software_IRQn,0xf0);
? ? NVIC_EnableIRQ(Software_IRQn);
? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
? ? RCC_ClocksTypeDef RCC_ClocksStatus;
? ? RCC_GetClocksFreq(&RCC_ClocksStatus);
? ? uint32_t tmp = RCC->CFGR0 & CFGR0_PPRE2_Set_Mask;
? ? tmp = tmp >> 11;
? ? if(tmp != 0) RCC_ClocksStatus.PCLK2_Frequency *= 2;
? ? TIM_InternalClockConfig(TIM1);
? ? TIM_TimeBaseStructure.TIM_Prescaler = RCC_ClocksStatus.PCLK2_Frequency / 1000000 - 1;? ?//指定用于劃分TIM時(shí)鐘的預(yù)分頻值,使其轉(zhuǎn)化為微秒
? ? TIM_TimeBaseStructure.TIM_Period = 1000000 / configTICK_RATE_HZ - 1;? ? ? //指定下次更新事件時(shí)要加載到活動(dòng)自動(dòng)重新加載寄存器中的周期值
? ? TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;? ? ? ? ?//時(shí)鐘分頻因子
? ? TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;? ? ?//TIM計(jì)數(shù)模式,向上計(jì)數(shù)模式
? ? TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);? ? ? ? ? ? ? ? ?//根據(jù)指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
? ? TIM_Cmd(TIM1, ENABLE);
? ? /* set TIM1 is lowest priority */
//? ? NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;? ? ? ? ? ? ?//TIM1中斷
//? ? NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;? ? ? ?//設(shè)置搶占優(yōu)先級(jí)1
//? ? NVIC_InitStructure.NVIC_IRQChannelSubPriority = 15;? ? ? ? ? ? ? //設(shè)置響應(yīng)優(yōu)先級(jí)7
//? ? NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;? ? ? ? ? ? ? ? ?//使能通道1中斷
//? ? NVIC_Init(&NVIC_InitStructure);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//初始化NVIC
? ? /* set systick is lowest priority */
? ? NVIC_SetPriority(TIM1_UP_IRQn,0xf0);
? ? NVIC_EnableIRQ(TIM1_UP_IRQn);
? ? TIM_ITConfig( TIM1, TIM_IT_Update, ENABLE );
}
/*-----------------------------------------------------------*/
void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM1_UP_IRQHandler( void )
{
? ? /* TIM Update event */
? ? if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
? ? {
? ? ? ? GET_INT_SP();
? ? ? ? portDISABLE_INTERRUPTS();
? ? ? ? if( xTaskIncrementTick() != pdFALSE )
? ? ? ? {
? ? ? ? ? ? portYIELD();
? ? ? ? }
? ? ? ? portENABLE_INTERRUPTS();
? ? ? ? FREE_INT_SP();
? ? ? ? TIM_ClearITPendingBit( TIM1, TIM_IT_Update );
? ? }
}
TIM1的中斷正常觸發(fā)后,在執(zhí)行到TIM1_UP_IRQHandler中的xTaskIncrementTick( )后,跟蹤到task.c:
? ? ? ? const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
執(zhí)行后直接觸發(fā)HardFault_Handler 中斷,發(fā)生錯(cuò)誤,這問(wèn)題在哪里呢?