打印
[uCOS/RTOS]

消息队列问题

[复制链接]
2529|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
w6850916|  楼主 | 2014-6-5 16:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 w6850916 于 2014-6-5 16:42 编辑

有个问题困扰了我两天了,问题是这样的,在STM32上移植了ucosii,让后用串口控制GSM模块,移植正常控制正常,也能接收发送短信,后来我想用消息队列来处理接收的短信,于是用了消息队列,现在遇到的问题是,在接收到第一条短信后压入消息堆栈,任务从消息堆栈里取出来是对的,但是从第二条消息开始,消息的第一个字节就出错了,我试了我能想到的各种办法都没有解决,前来求高人指点,或者来讨论下,真没思路了。相关代码如下:

typedef enum {
        TYPE_NONE = 0,
        TYPE_SMS_DATA,
        TYPE_RING,
        TYPE_RESET,
        TYPE_SEND_AT,
        TYPE_SEND_SMS,
        TYPE_SMS_COMING,
} GsmTaskMessageType;
typedef struct {
        GsmTaskMessageType type;
        void (*handlerFunc)(GsmTaskMessage *);
} MessageHandlerMap;

static const MessageHandlerMap __messageHandlerMaps[] = {
        { TYPE_SMS_DATA, __handleSMS },
        { TYPE_SMS_COMING, __handleReadyAcceptSMS},
        { TYPE_RING, __handleRING },
        { TYPE_NONE, NULL },
};


static __inline void __gmsReceiveSMSData(unsigned char data) {
        if (data == 0x0A) {
                buffer[bufferIndex++] = 0;
                if(strncmp("+CMGR:", buffer, 6) == 0){
                        isSMS = 2;
                } else if(isSMS == 2) {
                         GSMAutoReportMap fix ={NULL,TYPE_SMS_DATA};
                        GsmTaskMessage *message = __gsmCreateMessage(p->type, buffer, bufferIndex);
                        printf("bufferIndex %d\n",bufferIndex);
                        if (OS_NO_ERR != OSQPost(__Queue, message)) {
                                OSMemPut(SMSCommentBuf, message);
                                printf("E\n");
                        }

                        isSMS = 0;
                }
                bufferIndex = 0;
        } else if (data != 0x0D) {
                buffer[bufferIndex++] = data;
        }
}

void USART2_IRQHandler(void) {
        unsigned char data;

        if (USART_GetITStatus(USART2, USART_IT_RXNE) == RESET) {
                return;
        }
        data = USART_ReceiveData(USART2);
        USART_SendData(USART1, data);
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);

        if (isSMS) {
                __gmsReceiveSMSData(data);
                return;
        }

        if (data == 0x0A) {
                buffer[bufferIndex++] = 0;
                if (bufferIndex >= 2) {
                        const GSMAutoReportMap *p;
                        for (p = __gsmAutoReportMaps; p->prefix != NULL; ++p) {
                                if (strncmp(p->prefix, buffer, strlen(p->prefix)) == 0) {
                                        GsmTaskMessage *message = __gsmCreateMessage(p->type, buffer, bufferIndex);
                                        if (OS_NO_ERR != OSQPost(__Queue, message)) {
                                                OSMemPut(SMSCommentBuf, message);
                                        }

                                        break;
                                }
                        }
                        if (p->prefix == NULL) {
                                printf("Index=%d\n",bufferIndex);
                                ATCommandGotLineFromIsr(buffer, bufferIndex);
                        }
                }
                bufferIndex = 0;
        } else if (data != 0x0D) {
                buffer[bufferIndex++] = data;
                }
        }
}
GsmTaskMessage *__gsmCreateMessage(unsigned int type, const char *dat, int len) {
        GsmTaskMessage *message = OSMemGet(SMSCommentBuf, &err);
        if (message != NULL) {
                message->type = type;
                message->length = len;
                memcpy(&message[1], dat, len);
        }
        return message;
}



void App_TaskGu900d(void *p_arg) {   //GU900D调试进程
        char * alarmparameter;
        (void)p_arg;
        ATCommandRuntimeInit();
        __gsmInitHardware();
        __SmsRuntimeInit();
        while(1){
                printf("\r\n  GU900 OPEN  \r\n");
                if(Gu900dInit() == TRUE) break;
                Gu900dOff();
                OSTimeDlyHMSM(0,0,10,0);
        }
        OSTimeDlyHMSM(0,0,2,0);
        while(1){
                printf("\r\n  CHECK SIMCARD  \r\n");
                if(CheckSIM() == TRUE) break;
                OSTimeDlyHMSM(0,0,5,0);
        }

        for(;;) {
                GsmTaskMessage *message;
                printf("Gsm: loop again\n");
                message = OSQPend(__Queue, OS_TICKS_PER_SEC*60 , &err);               
                if(NULL != message){
                        const MessageHandlerMap *map = __messageHandlerMaps;
                        printf("type-> %x \n",message->type);

                        for (; map->type != TYPE_NONE; ++map) {
                                if (message->type == map->type) {
                                        printf("useful information \n");
                                        map->handlerFunc(message);
                                        break;
                                }
                        }
                        __gsmDestroyMessage(message);
                }
        }
}
标注蓝色的部分发送的消息到消息队列,任务读取每次都正确,但是红色部分只能是第一次正确,第二条开始就出错了,但都是第一个字节出错,有知道错在哪里的不?搞死我了都。








相关帖子

沙发
youimiss| | 2014-6-6 11:49 | 只看该作者
帮顶

使用特权

评论回复
板凳
w6850916|  楼主 | 2014-6-6 14:01 | 只看该作者
没人来讨论啊,别沉了

使用特权

评论回复
地板
w6850916|  楼主 | 2014-6-7 15:33 | 只看该作者
问题昨晚上解决了,其实发的代码没啥问题,问题原因是我在取出消息队列中的消息的时候,多free了一次,都是我没经验的结果啊!奇怪的是,为什么多free了一次以后,在下次读出的消息的前四个字节是上次多free的地址,找了点资料还是没有弄明白,好像是和arm内核有关,我用的是STM32F103芯片。如有知道的可以来讨论下。

使用特权

评论回复
5
仙帝将王| | 2014-6-9 18:02 | 只看该作者
请问楼主,你把蓝色的部分发送的消息到消息队列后,接着为什么就释放存放改消息的内存块了呢?这样下次你从消息队列中取出消息的时候可能会出错吧。可能情况是,在读取消息队列中的消息(一条指针,地址记为A)之前,其他任务得到了一个内存块,恰好地址也是A,那么就把这条消息修改了。

使用特权

评论回复
6
w6850916|  楼主 | 2014-6-11 17:10 | 只看该作者
仙帝将王 发表于 2014-6-9 18:02
请问楼主,你把蓝色的部分发送的消息到消息队列后,接着为什么就释放存放改消息的内存块了呢?这样下次你从 ...

你可能没看清,那个是如果放入消息堆栈不成功才释放的,错误了当然要把申请的内存释放了啊,如果正确压入消息队列中就不会释放。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

126

帖子

5

粉丝