- 2024-07-21
-
回复了主题帖:
关于FreeRTOS的任务消息替代事件组问题
freebsder 发表于 2024-7-16 15:24
看看它下面的定时器是什么情况
不知是哪个下面的定时器?
- 2024-07-15
-
回复了主题帖:
FreeRTOS怎样分配任务堆栈大小
freebsder 发表于 2024-7-15 18:50
现在的IDE对freertos支持挺好的,你翻翻应该还有线程插件
这个有,之前用TI的CCS有用过,调试的时候可以发挥大用,STM32CubeIDE找了一下也有不过还没使用过
-
回复了主题帖:
FreeRTOS怎样分配任务堆栈大小
walker2048 发表于 2024-7-14 22:25
首先、你可以定期打印堆栈大小和占用比例,设置超过80%或者多少就打印错误。
其次、Static Stack Anal ...
我觉得定期打印的办法有很高的局限性,没有出现堆栈溢出的时候还能看一下堆栈的使用情况,如果真出现堆栈溢出了定期打印根本来不及反应就进入HardFault了
- 2024-07-14
-
回复了主题帖:
FreeRTOS怎样分配任务堆栈大小
walker2048 发表于 2024-7-14 10:48
FreeRTOS自己就有堆栈占用和CPU占用分析,好好用工具也容易发现问题
这种的需要在软件运行以后串口打印出来吧?如果发生堆栈溢出程序就进入HardFault了你这个工具就失去作用了吧?
Static Stack Analyzer工具不需要debug也不需要把程序烧写进MCU,只要编译完了就可以直接看到每个任务的堆栈需求大小
- 2024-07-13
-
发表了主题帖:
FreeRTOS怎样分配任务堆栈大小
最近寡人在使用FreeRTOS的时候老是碰到一些稀奇古怪的软件BUG,网上搜了一圈后发现似乎这些问题都是我一个人遇到,搜索结果毫无头绪。而且这些BUG让人有点无从下手。比如软件运行在内核代码中莫名其妙它就进入HardFault了,这个问题还好说一点大概你还能想到可能是堆栈溢出了,但是你却无法定位究竟是哪一个任务的堆栈出了问题。再比如当你在等待一个任务通知位阻塞任务时:另外一个不相干的任务通知位突然毫无征兆的打断了任务阻塞状态,对此你根本毫无头绪。此时你的代码就像是一个千疮百孔的巨轮随时都有沉入海底的风险,总有一种无助到泪流满面的感觉。但是如果你充分信任FreeRTOS本身,那以上所有问题的根源我认为很可能都是由于堆栈溢出所导致的问题。那么此时你就需要一个火眼金睛的工具来告诉你到底是什么任务的堆栈出了问题,这些任务的堆栈究竟要分配多少才不会溢出?这个问题同样困扰了我很久,网上也搜索过但是一直没有找到满意的答案。事情的转机刚好就发生在今天上午一个神奇的时刻:楼主之前使用过TI的CCS软件,对它的堆栈分析功能印象深刻,我想到STM32CubeIDE的软件和TI的CCS软件同样都是基于eclipse,本是同根生CCS可以没理由STM32CubeIDE不行啊?此时我总算是开窍了,从此一发不可收拾,终于让我找到了正确的解决问题的方法:
点击红框中的“Max cost”可以将堆栈占用最高的函数排在最前
根据“Max cost”中的值将对应任务堆栈分配略大于即可,另外本次探索我还发现了另外一个好玩的东东:
翻译了才知道这个工具是用来分析函数复杂度的complexity值越高函数就越复杂,我这个函数的complexity值最高的已经到了89了,这个函数连我自己看起来都有点费劲,因此对继承者很不友好。
-
回复了主题帖:
关于FreeRTOS的任务消息替代事件组问题
Jacktang 发表于 2024-7-13 09:19
当DMA传输完成后置位“CPL_U3TX_SIG”任务消息,此时任务中ReadEvent = osSignalWait(ACK_U3TX_S ...
“CPL_U3TX_SIG”消息位用来指示DMA传输完成,"ACK_U3TX_SIG"消息位我在串口接收处理中置位,用来指示串口数据收到从机应答不需要再重发此数据了。因为我做了一个串口数据重发机制,只有收到目标设备应答才会退出重发,否则会重发10次数据。
- 2024-07-12
-
发表了主题帖:
关于FreeRTOS的任务消息替代事件组问题
最近在使用FreeRTOS的任务消息功能替代事件组,遇到一个毫无头绪的问题:当在中断函数中置位任务消息osSignalSet(TaskHandle,1);时会导致osEvent ReadEvent = osSignalWait(2,100);退出等待状态。仿真调试此时的ReadEvent.value.v=1,但是osSignalWait(2,100);却并没有阻塞100毫秒,不知是何原因?请大神们指教!
以下我附上我的源码:
#define CPL_U3TX_SIG 0x00000001u
#define ACK_U3TX_SIG 0x00000002u
复制
void StartTaskAndroidTx(void const * argument)
{
MyDataStruct_t *tx_buffer;
osSignalSet(AndroidTxHandle,CPL_U3TX_SIG);//osSemaphoreRelease(myBinarySemU3TxHandle);
/* Infinite loop */
for(;;)
{
if (pdPASS==xQueueReceive(U3TxQueueHandle, (uint8_t*)&tx_buffer, osWaitForever))
{
if (NULL!=tx_buffer) {
uint8_t data_len=tx_buffer->length;
if (0!=data_len) {
osEvent ReadEvent;
osSignalWait(CPL_U3TX_SIG,100);
osSignalWait(ACK_U3TX_SIG,0);
memcpy(DMA_USART3_TxBuf,tx_buffer->DatArea,data_len);
vPortFree((uint8_t*)tx_buffer);
for (int i = 0; i < 10; ++i) {
LCD_RS485_DE=LCD_RS485_RE=1;
LL_DMA_DisableStream(DMA1,LL_DMA_STREAM_3);
LL_DMA_SetDataLength(DMA1,LL_DMA_STREAM_3,data_len);
LL_DMA_EnableStream(DMA1,LL_DMA_STREAM_3);
ReadEvent = osSignalWait(ACK_U3TX_SIG,100);
if (ReadEvent.value.v & ACK_U3TX_SIG)break;
}
}
else vPortFree((uint8_t*)tx_buffer);
}
}
}
}
以下为中断中发送任务消息:
复制
void DMA1_Stream3_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream3_IRQn 0 */
if (LL_DMA_IsEnabledIT_TC(DMA1,LL_DMA_STREAM_3)!=RESET && LL_DMA_IsActiveFlag_TC3(DMA1) != RESET)
{
LL_DMA_ClearFlag_TC3(DMA1);
LL_DMA_DisableStream(DMA1,LL_DMA_STREAM_3);
osSignalSet(AndroidTxHandle,CPL_U3TX_SIG);
}
/* USER CODE END DMA1_Stream3_IRQn 0 */
/* USER CODE BEGIN DMA1_Stream3_IRQn 1 */
/* USER CODE END DMA1_Stream3_IRQn 1 */
}
当DMA传输完成后置位“CPL_U3TX_SIG”任务消息,此时任务中ReadEvent = osSignalWait(ACK_U3TX_SIG,100);也退出等待了,我的本意是要收到ACK_U3TX_SIG消息才退出阻塞
使用特权
更多操作
- 2024-03-25
-
回复了主题帖:
osPriorityRealtime任务不能被终止
wangerxian 发表于 2024-3-25 15:17
意思是想开机时,先停止GUI任务创建的线程?
是的,主要是上电不让这个任务运行,或者我的本意是上电时并不想创建某个任务,但是STM32CubeIDE好像没有这个选项,只要你在.ioc文件中新增了某个任务那么这个任务默认就在FRERTOS_Init()函数中被创建了你没得选。当然你也可以选择全手动创建这个任务就没有这个问题了,但我却没有这么干因此遇到了问题,发出来希望能帮助到有缘人
- 2024-03-23
-
发表了主题帖:
osPriorityRealtime任务不能被终止
本帖最后由 shipeng 于 2024-3-23 16:02 编辑
最近用STM32CubeIDE配置FreeRTOS的时候发现:osPriorityRealtime级别的任务创建之后在内核启动(调用函数osKernelStart())前不能被终止,否则会导致HardFault异常中断。至于在内核启动后能不能终止任务我没有试。我的操作是在函数void MX_FREERTOS_Init(void)中创建任务REMOTE_CMDHandle,在MX_FREERTOS_Init函数返回前调用了osThreadTerminate(REMOTE_CMDHandle);并且将任务句柄清空REMOTE_CMDHandle = NULL;我这么做的初衷是REMOTE_CMDHandle任务上电不让它运行,等待用户操作后再创建运行。由于使用STM32CubeIDE图形化创建任务后默认都会上电运行,所以在创建后加了一句任务终止以达到我不可告人的目的。
debug跟踪发现具体原因是在堆栈初始化函数pxPortInitialiseStack返回时进入prvIdleTask函数->prvCheckTasksWaitingTermination()->( void ) uxListRemove( &( pxTCB->xStateListItem ) )运行到“if( pxList->pxIndex == pxItemToRemove )”时出现非法地址0xfffffffd触发HardFault_Handler()异常中断,最后的解决办法是将优先级设置为osPriorityHigh成功解决,要深究具体原因还需要各位大神们指点迷津。
- 2024-03-14
-
回复了主题帖:
TM4C123芯片锁死无法烧写
研究了半天发现我这个不是芯片锁死的问题,换了一个第三方做的XDS100V3发现可以正常烧写程序了,感情官方的大几千块的XDS110还不如一百块的第三方XDS100V3好用,我也是服了TI
- 2024-03-11
-
回复了主题帖:
TM4C123芯片锁死无法烧写
Jacktang 发表于 2024-3-10 15:18
分享一下别人的方法,可能不一定解决楼主的问题,可以借鉴一下
由于本人刚接触到TM4C123Glaun ...
感谢大佬热情回复
- 2024-03-10
-
发表了主题帖:
TM4C123芯片锁死无法烧写
使用TI官方的UniFlash+XDS110正常烧写软件,之前都一直未出问题。最近频繁遇到“Error -1170 @ 0x0”错误无法再次烧录。网上搜索说是芯片进入生产模式了,需要进入开发模式才能烧录。但是找了一圈也没有找到可行的进入开发模式的方法。在此恳请各位大牛指点迷津...
- 2023-12-23
-
回复了主题帖:
FreeRTOS中的互斥锁在中断中Give
本帖最后由 shipeng 于 2023-12-23 17:14 编辑
lugl4313820 发表于 2023-12-23 10:15 现在最新版的好象说修复了这个问题,楼主可以去试试。
不知道我用的是不是最新版,总之用了互斥量就一堆的问题,各种报Assert错误,我也不知道是不是因为谁上锁谁解锁的原因导致的。总之如果遵循谁上锁谁解锁的原则使用互斥量就可以运行。否则就会报各种ASSERT错误。如果把互斥量换成二值信号量就没有这个问题。
下面是我的源码,说一下我的软件逻辑:每次DMA传输完成后启动一个10毫秒定时器,在定时器回调函数中Give互斥量。从而保证帧最小间隔为10毫秒,以防止发送帧粘连。
SemaphoreHandle_t DMA2C5MuxSem_Handle = NULL;
TimerHandle_t xHandleTimerU4Tx = NULL;
TaskHandle_t xHandleTaskU4TX = NULL;
static void U4TxTimerCallback(void);
static void CreateU4TxFrameDelay(TickType_t xTimerPeriodInTicks );
static void vTaskU4TX_Handler(void *pvParameters);
void UART4_DMA_Init(void);
void BSP_UART4_Init(void);
void BSP_USART_Config(void)
{
BSP_UART4_Init();
UART4_DMA_Init();
NVIC_EnableIRQRequest(UART4_IRQn, 2, 0);
USART_EnableInterrupt(UART4, USART_INT_IDLE);
/* Enable UART4 RX and UART4 TX DMA */
USART_EnableDMA(UART4, USART_DMA_TX_RX);
U4RxQueue = xQueueCreate(U4RX_QUE_DEPTH, U4RX_QUE_SIZE);//msgs , length of msg(byte)
if (NULL==U4RxQueue)printf("U4RxQueue Creating Failed!\r\n");
U4TxQueue = xQueueCreate(4, 4);
if (NULL==U4TxQueue)printf("U4TxQueue Creating Failed!\r\n");
#ifndef USE_DMA_WITH_MUTEX
DMA2C5MuxSem_Handle = xSemaphoreCreateBinary();
#else
DMA2C5MuxSem_Handle = xSemaphoreCreateMutex();
#endif
if (NULL==DMA2C5MuxSem_Handle)printf("DMA2C5MuxSem Creating Failed!\r\n");
#ifndef USE_DMA_WITH_MUTEX
else if (0==uxSemaphoreGetCount(DMA2C5MuxSem_Handle) && pdPASS!=xSemaphoreGive(DMA2C5MuxSem_Handle))printf("DMA2C5MuxSem Giving Failed!\r\n");
#endif
CreateU4TxFrameDelay(10);
xTaskCreate((TaskFunction_t )vTaskU4TX_Handler,
(const char* )"UART4 TX Task",
(uint16_t )256,
(void* )NULL,
(UBaseType_t )5,
(TaskHandle_t* )&xHandleTaskU4TX);
}
static void U4TxTimerCallback(void)
{
#ifndef USE_DMA_WITH_MUTEX
if (0==uxSemaphoreGetCount(DMA2C5MuxSem_Handle) && pdPASS != xSemaphoreGive( DMA2C5MuxSem_Handle))printf("DMA2C5MuxSem Giving failed!");
#else
if (NULL!=xSemaphoreGetMutexHolder(DMA2C5MuxSem_Handle) && pdPASS != xSemaphoreGive( DMA2C5MuxSem_Handle))printf("DMA2C5MuxSem Giving failed!");
#endif
else if (0!=uxQueueMessagesWaiting(U4TxQueue))portYIELD();//if the queue is not empty,then request a context switch
}
static void CreateU4TxFrameDelay(TickType_t xTimerPeriodInTicks )
{
xHandleTimerU4Tx = xTimerCreate("U4TxTimer",xTimerPeriodInTicks,pdFALSE,(void*)3,(TimerCallbackFunction_t)U4TxTimerCallback);
if (NULL==xHandleTimerU4Tx)printf("U4TxTimer Creating failed!");
}
static void vTaskU4TX_Handler(void *pvParameters)
{
UsartTxRxBuffer_t *tx_buffer;
while(1)
{
if (pdPASS==xQueueReceive(U4TxQueue, (uint8_t*)&tx_buffer, portMAX_DELAY))
{
xSemaphoreTake(DMA2C5MuxSem_Handle, 5689U);//5689ms Is The MAX TIME of DMA-UART-Tx,65536bytes*1000ms/11520(byte rate)=5688.888...
if (0!=tx_buffer->length)
{
/* Disable TX DMA */
DMA_Disable(DMA2_Channel5);
memcpy(DMA_UART4_TxBuf,tx_buffer->DatArea,tx_buffer->length);
DMA2_Channel5->CHNDATA_B.NDATA = tx_buffer->length;
/* Enable TX DMA */
DMA_Enable(DMA2_Channel5);
}
if (NULL!=tx_buffer)vPortFree((uint8_t*)tx_buffer);
}
}
}
void DMA2_Channel5_IRQHandler(void)
{
if (RESET != DMA_ReadIntFlag(DMA2_INT_FLAG_TC5))
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
DMA_ClearIntFlag(DMA2_INT_FLAG_TC5);
if (NULL!=xHandleTimerU4Tx)
{
xTimerResetFromISR(xHandleTimerU4Tx,&xHigherPriorityTaskWoken);
}
}
}
void UART4_DMA_Init(void)
{
DMA_Config_T dmaConfig;
/* Enable DMA Clock */
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA2);
/* TX DMA config */
dmaConfig.peripheralBaseAddr = UART4_DR_ADDRESS;
dmaConfig.memoryBaseAddr = (uint32_t)DMA_UART4_TxBuf;
dmaConfig.dir = DMA_DIR_PERIPHERAL_DST;
dmaConfig.bufferSize = 0;
dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_BYTE;
dmaConfig.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE;
dmaConfig.loopMode = DMA_MODE_NORMAL;
dmaConfig.priority = DMA_PRIORITY_HIGH;
dmaConfig.M2M = DMA_M2MEN_DISABLE;
/* Enable DMA channel */
DMA_Config(DMA2_Channel5, &dmaConfig);
/* Enable TX DMA */
DMA_Enable(DMA2_Channel5);
NVIC_EnableIRQRequest(DMA2_Channel5_IRQn, 3, 0);
DMA_EnableInterrupt(DMA2_Channel5, DMA_INT_TC);
/* RX DMA Configure */
dmaConfig.dir = DMA_DIR_PERIPHERAL_SRC;
dmaConfig.loopMode = DMA_MODE_CIRCULAR;
dmaConfig.bufferSize = sizeof(DMA_UART4_RxBuf);
dmaConfig.memoryBaseAddr = (uint32_t)DMA_UART4_RxBuf;
/* Enable DMA channel */
DMA_Config(DMA2_Channel3, &dmaConfig);
/* Enable RX DMA */
DMA_Enable(DMA2_Channel3);
// NVIC_EnableIRQRequest(DMA2_Channel3_IRQn, 1, 0);
// DMA_EnableInterrupt(DMA2_Channel3, DMA_INT_TC);
}
void BSP_UART4_Init(void)
{
GPIO_Config_T GPIO_ConfigStructure;
USART_Config_T USART_ConfigStruct;
RCM_EnableAPB2PeriphClock((RCM_APB2_PERIPH_T)(RCM_APB2_PERIPH_GPIOC));
RCM_EnableAPB1PeriphClock((RCM_APB1_PERIPH_T)(RCM_APB1_PERIPH_UART4));
/*Uart4 TX*/
GPIO_ConfigStructure.pin = GPIO_PIN_10;
GPIO_ConfigStructure.speed = GPIO_SPEED_50MHz;
GPIO_ConfigStructure.mode = GPIO_MODE_AF_PP;
GPIO_Config(GPIOC, &GPIO_ConfigStructure);
/*Uart4 RX*/
GPIO_ConfigStructure.pin = GPIO_PIN_11;
GPIO_ConfigStructure.mode = GPIO_MODE_IN_FLOATING;
GPIO_Config(GPIOC, &GPIO_ConfigStructure);
USART_ConfigStruct.baudRate = 115200;
USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
USART_ConfigStruct.mode = USART_MODE_TX_RX;
USART_ConfigStruct.parity = USART_PARITY_NONE;
USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;
USART_Config(UART4, &USART_ConfigStruct);
USART_Enable(UART4);
}
- 2023-12-21
-
发表了主题帖:
FreeRTOS中的互斥锁在中断中Give
新手第一次使用FreeRTOS的互斥锁,本想用它来指示串口发送DMA的占用情况,在DMA传输完成中断中Give串口发送DMA互斥量(xSemaphoreGiveFromISR)。结果系统始终无法正常运行起来。由于一次修改了多处代码一时定位不到问题点。只知道调试串口打印出“FreeRTOS assert "!( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMute...”的消息。网上找了一圈,发现大家都说FreeRTOS的互斥锁功能不完整,本来互斥量应该遵循谁上锁谁解锁的原则,结果FreeRTOS却没能实现这个功能,他的互斥锁上锁后所有人都可以解锁。于是我便坚定了中断中也可以解锁互斥量。但是一通折腾下来始终不能成功运行,最后无意中看到宏“xSemaphoreGiveFromISR”的使用前注释才发现了问题所在:
Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) must not be used with this macro.
原来虽然FreeRTOS不能实现谁上锁谁开锁这个功能,但是他还是稍微做了下弥补,那就是中断函数中不允许Give互斥量。