From 4166f31136a9626e1fc1d4f4624c48248be64aae Mon Sep 17 00:00:00 2001 From: Lizongdi <1210855344@qq.com> Date: Thu, 24 Sep 2026 16:25:25 +0800 Subject: [PATCH] =?UTF-8?q?ringbuffer=E5=AE=9E=E7=8E=B0=E8=87=AA=E6=97=8B?= =?UTF-8?q?=E9=94=81=EF=BC=88H7=E4=B8=8B=EF=BC=89=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=E5=A2=9E=E5=8A=A0=E5=AE=89=E5=85=A8=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RBcore/include/msg_center.h | 10 ++++ RBcore/msg_center.c | 72 +++++++++++++++++-------- library/common/include/common.h | 16 ++++++ library/ringbuffer/include/ringbuffer.h | 2 + library/ringbuffer/ringbuffer.c | 26 +++++++++ 5 files changed, 104 insertions(+), 22 deletions(-) diff --git a/RBcore/include/msg_center.h b/RBcore/include/msg_center.h index d67e9cf..0818522 100644 --- a/RBcore/include/msg_center.h +++ b/RBcore/include/msg_center.h @@ -109,6 +109,16 @@ int MsgCenter_Send(const Msg_t *pstMsg); */ int MsgCenter_SendTo(const char *pszDstName, uint32_t uiMsgID, const void *pData, uint32_t uiDataLen); +/** + * @brief 发送消息给指定模块(ISR安全版本,无mutex,关中断+自旋锁保护) + * @param pszDstName 目标模块名称 + * @param uiMsgID 消息ID + * @param pData 数据指针(可为NULL) + * @param uiDataLen 数据长度 + * @return 0成功,非0失败 + */ +int MsgCenter_SendFromISR(const char *pszDstName, uint32_t uiMsgID, const void *pData, uint32_t uiDataLen); + /** * @brief 处理当前模块的消息(在模块线程中调用) * @param uiModuleID 模块ID diff --git a/RBcore/msg_center.c b/RBcore/msg_center.c index 067882e..36b34c9 100644 --- a/RBcore/msg_center.c +++ b/RBcore/msg_center.c @@ -45,7 +45,6 @@ typedef struct { MsgModule_t stModule; rd_ringbuf_t *pstRingBuf; // 消息队列(ringbuffer) - rd_mutex_t stMutex; // 互斥锁(保护ringbuffer) rd_sem_t stSem; // 信号量(阻塞等待) } MsgModuleEntry_t; @@ -129,17 +128,9 @@ uint32_t MsgCenter_Register(const char *pszName, MsgHandler_t pfHandler) return 0; } - // 初始化互斥锁 - if (Rd_MutexInit(&g_astModules[uiIndex].stMutex) != RD_SUCCESS) - { - rd_RingbufferDestroy(g_astModules[uiIndex].pstRingBuf); - return 0; - } - // 初始化信号量(初始值为0,表示无消息) if (Rd_SemInit(&g_astModules[uiIndex].stSem, 0, 0) != RD_SUCCESS) { - Rd_MutexDestroy(&g_astModules[uiIndex].stMutex); rd_RingbufferDestroy(g_astModules[uiIndex].pstRingBuf); return 0; } @@ -194,14 +185,9 @@ int MsgCenter_Send(const Msg_t *pstMsg) return RD_FAILURE; } - // 加锁保护ringbuffer - Rd_MutexLock(&g_astModules[iDstIndex].stMutex, __func__, NULL); - - // 写入ringbuffer - int iRet = rd_RingbufferPut(g_astModules[iDstIndex].pstRingBuf, - (const char *)pstMsg, sizeof(Msg_t)); - - Rd_MutexUnlock(&g_astModules[iDstIndex].stMutex, __func__, NULL); + // MPSC安全写入(ringbuffer内部关中断+自旋锁) + int iRet = rd_RingbufferPutSafe(g_astModules[iDstIndex].pstRingBuf, + (const char *)pstMsg, sizeof(Msg_t)); if (iRet > 0) { @@ -256,6 +242,53 @@ int MsgCenter_SendTo(const char *pszDstName, uint32_t uiMsgID, const void *pData return MsgCenter_Send(&stMsg); } +int MsgCenter_SendFromISR(const char *pszDstName, uint32_t uiMsgID, const void *pData, uint32_t uiDataLen) +{ + if (NULL == pszDstName) + { + return RD_NULL; + } + + uint32_t uiDstModuleID = MsgCenter_FindModule(pszDstName); + if (0 == uiDstModuleID) + { + return RD_FAILURE; + } + + int iDstIndex = FIND_MODULE_INDEX(uiDstModuleID); + if (iDstIndex < 0 || NULL == g_astModules[iDstIndex].pstRingBuf) + { + return RD_FAILURE; + } + + Msg_t stMsg; + RD_MEMSET(&stMsg, 0, sizeof(Msg_t)); + stMsg.m_uiDstModule = uiDstModuleID; + stMsg.m_uiMsgID = uiMsgID; + + if (NULL != pData && uiDataLen > 0) + { + if (uiDataLen > MSG_CENTER_MAX_DATA_SIZE) + { + uiDataLen = MSG_CENTER_MAX_DATA_SIZE; + } + RD_MEMCPY(stMsg.m_aucData, pData, uiDataLen); + stMsg.m_uiDataLen = uiDataLen; + } + + // MPSC安全写入(ringbuffer内部关中断+自旋锁) + int iRet = rd_RingbufferPutSafe(g_astModules[iDstIndex].pstRingBuf, + (const char *)&stMsg, sizeof(Msg_t)); + if (iRet > 0) + { + // 信号量在CMSIS-RTOS2中自动识别ISR上下文 + Rd_SemPost(&g_astModules[iDstIndex].stSem, __func__, NULL); + return RD_SUCCESS; + } + + return RD_FAILURE; +} + /***************************************************************************** 函 数 名 : MsgCenter_ProcessOne 功能描述 : 从ringbuffer读取一条消息 @@ -266,14 +299,9 @@ int MsgCenter_SendTo(const char *pszDstName, uint32_t uiMsgID, const void *pData *****************************************************************************/ static int MsgCenter_ProcessOne(int iIndex, Msg_t *pstMsg) { - // 加锁保护ringbuffer - Rd_MutexLock(&g_astModules[iIndex].stMutex, __func__, NULL); - int iRet = rd_RingbufferGet(g_astModules[iIndex].pstRingBuf, (char *)pstMsg, sizeof(Msg_t)); - Rd_MutexUnlock(&g_astModules[iIndex].stMutex, __func__, NULL); - return (iRet > 0) ? 1 : 0; } diff --git a/library/common/include/common.h b/library/common/include/common.h index 30ee40a..5c5a9fd 100644 --- a/library/common/include/common.h +++ b/library/common/include/common.h @@ -41,6 +41,22 @@ #define ATOMIC_ORDER_RELEASE 0 #endif +/* 中断控制(CMSIS 标准接口,ISR 安全) */ +#if defined(__arm__) || defined(__aarch64__) + #include "../../../Drivers/CMSIS/Include/cmsis_compiler.h" + static inline uint32_t rd_irq_save(void) { + uint32_t primask = __get_PRIMASK(); + __disable_irq(); + return primask; + } + static inline void rd_irq_restore(uint32_t primask) { + __set_PRIMASK(primask); + } +#else + static inline uint32_t rd_irq_save(void) { return 0; } + static inline void rd_irq_restore(uint32_t primask) { (void)primask; } +#endif + /* 跨平台弱符号宏定义 */ #if defined(_MSC_VER) || defined(WIN32) /* Microsoft Visual C++ */ diff --git a/library/ringbuffer/include/ringbuffer.h b/library/ringbuffer/include/ringbuffer.h index 813bdba..612b496 100644 --- a/library/ringbuffer/include/ringbuffer.h +++ b/library/ringbuffer/include/ringbuffer.h @@ -74,6 +74,7 @@ struct TRingBuffer unsigned short m_sReadIndex; unsigned char m_bWriteMirror; unsigned short m_sWriteIndex; + unsigned char m_bWriteLock; /* 写入自旋锁(关中断+原子CAS,ISR安全) */ int m_iBufsize; char *m_pcBufPtr; }; @@ -120,6 +121,7 @@ extern void rd_RingbufferInit(rd_ringbuf_t *rb, char *pool, int size); extern int rd_RingbufferPeak(rd_ringbuf_t *rb, char **ptr); extern int rd_RingbufferPeekLinear(rd_ringbuf_t *rb, char *out, int length); extern int rd_RingbufferPut(rd_ringbuf_t *rb, const char *ptr, int length); +extern int rd_RingbufferPutSafe(rd_ringbuf_t *rb, const char *ptr, int length); extern int rd_RingbufferPutchar(rd_ringbuf_t *rb, const char ch); extern int rd_RingbufferPutcharForce(rd_ringbuf_t *rb, const char ch); extern int rd_RingbufferPutForce(rd_ringbuf_t *rb, const char *ptr, int length); diff --git a/library/ringbuffer/ringbuffer.c b/library/ringbuffer/ringbuffer.c index 46958ee..d4352d9 100644 --- a/library/ringbuffer/ringbuffer.c +++ b/library/ringbuffer/ringbuffer.c @@ -69,6 +69,7 @@ void rd_RingbufferInit(rd_ringbuf_t *rb, char *pool, int size) ATOMIC_STORE(&rb->m_sWriteIndex, 0, unsigned short, ATOMIC_ORDER_RELAXED); ATOMIC_STORE(&rb->m_bReadMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); ATOMIC_STORE(&rb->m_bWriteMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); + ATOMIC_STORE(&rb->m_bWriteLock, 0, unsigned char, ATOMIC_ORDER_RELAXED); rb->m_pcBufPtr = pool; rb->m_iBufsize = RD_ALIGN_DOWN(size, RD_ALIGN_SIZE); @@ -155,6 +156,30 @@ int rd_RingbufferPut(rd_ringbuf_t *rb, const char *ptr, int length) return length; } +/** + * @brief MPSC-safe Put: 关中断+原子自旋锁保护写入,可安全用于 ISR 和多线程并发写入。 + */ +int rd_RingbufferPutSafe(rd_ringbuf_t *rb, const char *ptr, int length) +{ + if (!rb || !ptr || length <= 0) return RD_INVALUE; + + /* 关中断(若已在 ISR 中则 primask=1,末尾不恢复开中断) */ + uint32_t primask = rd_irq_save(); + + /* 原子自旋锁 */ + while (ATOMIC_EXCH(&rb->m_bWriteLock, 1, unsigned char, ATOMIC_ORDER_ACQUIRE)) + { + /* 等待锁释放 */ + } + + int iRet = rd_RingbufferPut(rb, ptr, length); + + ATOMIC_STORE(&rb->m_bWriteLock, 0, unsigned char, ATOMIC_ORDER_RELEASE); + rd_irq_restore(primask); + + return iRet; +} + /** * @brief Put a block of data into the ring buffer. If the capacity of ring buffer is insufficient, it will overwrite the existing data in the ring buffer. * @@ -424,6 +449,7 @@ void rd_RingbufferReset(rd_ringbuf_t *rb) ATOMIC_STORE(&rb->m_sWriteIndex, 0, unsigned short, ATOMIC_ORDER_RELAXED); ATOMIC_STORE(&rb->m_bReadMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); ATOMIC_STORE(&rb->m_bWriteMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); + ATOMIC_STORE(&rb->m_bWriteLock, 0, unsigned char, ATOMIC_ORDER_RELAXED); } /**