ch32v307中64位的Systick可以不回绕地一直计数,是系统很好的一个绝对时标,不必用中断而能提供阻塞式的和非阻塞式的延时。公版的Systick延时示例不是一个理想的应用方式,它会复位计数器,只适合单线程的应用,我们可以让它一直计时而不重载,要让它计满得几千年。
为了不浪费Systick,想用TIM1替代FreeRtos示例里的Systick,不过事情很奇怪,重新上电后的第一次运行总是出错,进行一次手工Reset复位后却能正常运行,而使用Systick不会发生。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时钟的预分频值,使其转化为微秒
? ? TIM_TimeBaseStructure.TIM_Period = 1000000 / configTICK_RATE_HZ - 1;? ? ? //指定下次更新事件时要加载到活动自动重新加载寄存器中的周期值
? ? TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;? ? ? ? ?//时钟分频因子
? ? TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;? ? ?//TIM计数模式,向上计数模式
? ? TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);? ? ? ? ? ? ? ? ?//根据指定的参数初始化TIMx的时间基数单位
? ? TIM_Cmd(TIM1, ENABLE);
? ? /* set TIM1 is lowest priority */
//? ? NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;? ? ? ? ? ? ?//TIM1中断
//? ? NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;? ? ? ?//设置抢占优先级1
//? ? NVIC_InitStructure.NVIC_IRQChannelSubPriority = 15;? ? ? ? ? ? ? //设置响应优先级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的中断正常触发后,在执行到TIM1_UP_IRQHandler中的xTaskIncrementTick( )后,跟踪到task.c:
? ? ? ? const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
执行后直接触发HardFault_Handler 中断,发生错误,这问题在哪里呢?