完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
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 中断,发生错误,这问题在哪里呢? |
|
相关推荐
8个回答
|
|
临时的解决办法:
uint64_t CmpValueAdd;/* just for wch's systick,don't have mtime */void vPortSetupTimerInterrupt( void ){ /* set software is lowest priority */ NVIC_SetPriority(Software_IRQn,0xf0); NVIC_EnableIRQ(Software_IRQn); /* set systick is lowest priority */ NVIC_SetPriority(SysTicK_IRQn,0xf0); NVIC_EnableIRQ(SysTicK_IRQn); SysTick->CTLR= 0; SysTick->SR = 0; SysTick->CNT = 0; /* ********* */ CmpValueAdd = configCPU_CLOCK_HZ/configTICK_RATE_HZ/8; SysTick->CMP = CmpValueAdd; SysTick->CTLR= 0x3; /* ********* */}/*-----------------------------------------------------------*/void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));void SysTick_Handler( void ){ GET_INT_SP(); portDISABLE_INTERRUPTS(); SysTick->SR=0; /* ********* */ SysTick->CMP = SysTick->CNT + CmpValueAdd; /* ********* */ if( xTaskIncrementTick() != pdFALSE ) { portYIELD(); } portENABLE_INTERRUPTS(); FREE_INT_SP();} |
|
|
|
我们让Systick不回零,始终向上计数,在Debug.c中
int pule_us = 0;int pule_ms = 0;/**************************************** 获得系统当前以1毫秒为单位的滴答计数 类似于 STM32的函数/****************************************uint64_t HAL_GetTick(){ return SysTick->CNT / pule_ms ;}/*************************************** 初始化***************************************/void Delay_Init(void){ pule_us = SystemCoreClock / 8000000; pule_ms = (uint16_t)pule_us * 1000; SysTick->CTLR = (1 << 5) | 1; // 计数器初始值更新=0, 启动计数器。 关中断、1/8时基、到比较值后继续、向上计数}/*************************************** 阻塞式的微秒延时***************************************/void Delay_Us(uint32_t n){uint64_t Cmp = SysTick->CNT + (uint32_t)n * pule_us; while(SysTick->CNT < Cmp);}/*************************************** 阻塞式的毫秒延时***************************************/void Delay_Ms(uint32_t n){uint64_t Cmp = SysTick->CNT + (uint32_t)n * pule_ms; while(SysTick->CNT < Cmp);} |
|
|
|
|
|
|
|
您好,请问你运行的是哪个工程?FreeRTOS那个么,我下载后上电正常运行,两个任务都在工作,LED正常闪烁,并没有出现死机现象,若方便,可以具体描述一下异常的现象和正常运行时的现象
|
|
|
|
是AppTest。 Hex文件可能较老(另外它的起始地址在8000,有可能刷了后运行的并不是它),需要重新编译(设置里是生成bin),.ld文件已经把地址改为 0x00000000。
还有,写了bootloader 文件,通过CAN总线刷写APP到FLASH,有时候连续成功,有时候连续不成功。表现是刷写20k的bin到85%左右发现校验错误,即写入的内容与读出的内容不一致。写入过程很简单:收到4字节以WORD方式写入,成功后向主机继续请求下一个WORD,收到后再次写入。 /* Program 32bit data into flash ---------------------------------------------*/bool Flash_Write32(uint32_t data){ if((flash_ptr > (FLASH_END_ADDRESS - 3)) || (flash_ptr < FLASH_STARTADDRESS) ) { FLASH_Lock(); return false; } if(FLASH_ProgramWord(flash_ptr,(uint64_t) data) == FLASH_COMPLETE) { /* Check the written value */ if(*(__IO uint32_t*)flash_ptr != data) { /* Flash content doesn't match source content */ printf("Write Error at: %prnWRITE: %xrnFLASH: %xrn", flash_ptr, data, *(__IO uint32_t*)flash_ptr); FLASH_Lock(); return false; } /* Increment Flash destination address */ flash_ptr += 4; } else { /* Error occurred while writing data into Flash */ printf("Write Errorrn", *(uint32_t*)flash_ptr, data); FLASH_Lock(); return false; } return true;}发生错误时4个字节中有一个字节某些位不对,有时候是多0,有时候是多1 |
|
|
|
我为了构建84MHz的时钟(以前STM项目继承的,搞了一个奇怪的CAN波特率,要有3和7的倍数),只好使用了两级PLL。但是代码库中的RCC_GetClocksFreq()编写的太原始,未考虑PLL2的作用,导致串口时钟不对,打印输出乱码。我已经进行了修改,将获取SYSCLK的过程单独拿出来作为一个弱函数。期待官方后期继续完善。
|
|
|
|
您好,这边对AppTest例程进行下载测试,并在下载之前删除了原有的bin文件和hex文件,重新生成bin文件下载,下载之后看不到任何现象,串口也没有打印,包括重新上电复位之后,为了问题快速解决,建议你那边测试一下发一个可复现问题的例程过来
|
|
|
|
Flash写错误的问题找到了,是我少擦除了一部分。在此提醒厂家,希望例子代码更严谨些。
问题的发生就在于例子中擦除块的计算: NbrOfPage = (PAGE_WRITE_END_ADDR - PAGE_WRITE_START_ADDR) / FLASH_PAGE_SIZE; 很显然,总擦除字节数不是FLASH_PAGE_SIZE整倍数的时候,一定少擦除了。另外当PAGE_WRITE_START_ADDR并非以FLASH_PAGE_SIZE对齐的时候也一定不正确。 我们开发人员由于对芯片运行机制了解的不一定全面,经常会将厂方例子代码奉为经典,经常不敢轻易改动。而厂方测试代码编写人员经常以测试为目的,考虑的不够全面,默认用户会仔细阅读并修改代码,所以希望厂方提高思想认识,以用户角度思考问题,多替用户着想,简化处理的部分也要写出详细注释,说明需要修改的地方和方法。 不要嫌我多嘴,我是支持国产替代才提意见,如果不想用,干嘛多费唾沫。 |
|
|
|
只有小组成员才能发言,加入小组>>
505 浏览 1 评论
CH579M+RT-Thread,RTC从Sleep模式唤醒失败是什么原因?
2899 浏览 2 评论
2387 浏览 1 评论
847浏览 2评论
CH32F103C8T6使用当前官网上的CDC例程会出现设备描述符请求失败
392浏览 1评论
670浏览 1评论
riscv-none-embed-objcopy: \'PWM_Output.elf\': No such file这个咋解决,
406浏览 1评论
501浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-12 22:57 , Processed in 1.208177 second(s), Total 93, Slave 76 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号