搜索
bottom↓
回复: 3

2440平台处理串口接收数据采用信号量方式会当机

[复制链接]

出0入0汤圆

发表于 2010-12-15 10:36:43 | 显示全部楼层 |阅读模式
2440硬件平台,采用0.4.0beta版本,串口中断接收数据,完成后调用rt_sem_release通知任务处理,处理任务调用rt_sem_take等到信号量后开始处理数据,测试运行,不稳定,有时几分钟,有时半个钟,ARM就出现undefined异常,R14(LR)0x300003b4,看编译后的map文件,rt_hw_context_switch_to             0x300003ac   ARM Code      24  context_rvds.o(.text),说明此时代码运行在这个函数里面出现了异常,

再做一实验:不采用信号量方式通知处理任务,而是处理任务直接延时tick,然后读接收buffer里面的数据做处理,测试运行了1个晚上都没有发现上面这种异常现象,

分析:串口使用信号量的手法和finsh写的手法一摸一样,于是猜想可能finsh那边也会出同样问题,再做一次验证:采用串口调试助手:200ms时间间隔自动发送list_mem()命令,测试发现15分钟左右就出现了上面这种内核切换线程异常

哪位有2440的硬件平台,帮忙测试看看,看是否有这样的现象?

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2010-12-15 11:14:30 | 显示全部楼层
请给个串口接收代码吧

出0入0汤圆

 楼主| 发表于 2010-12-15 12:26:29 | 显示全部楼层
初始化中:
{
//创建接收数据的信号量
modem.rxdsem = rt_sem_create("modem_sem", 0, RT_IPC_FLAG_FIFO);

rt_device_set_rx_indicate(modem.device, _modem_rxind);
}

rt_err_t _modem_rxind(rt_device_t dev, rt_size_t size)
{
        rt_sem_release(modem.rxdsem);

        return RT_EOK;
}

//处理线程
static void _modem_rxd_thread_entry(void* parameter)
{
       rt_device_open(modem.device, RT_DEVICE_OFLAG_RDWR);

        while (1)
                {
                if (rt_sem_take(modem.rxdsem, RT_WAITING_FOREVER) != RT_EOK) continue;
               
                /*read rx ind data*/
                readcnt = rt_device_read(modem.device, 0, &buff[okindex], rxbuff_maxsize - okindex);
                okindex += readcnt;

                   //下面是处理数据过程。。。。

                  
                   okindex = 0;
                   }
}

读串口buffer里面的数据
static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
        rt_uint8_t* ptr;
        struct serial_device* serial = (struct serial_device*)dev;

        RT_ASSERT(dev != RT_NULL);

        ptr = (rt_uint8_t*)buffer + pos;

        if (dev->flag & RT_DEVICE_FLAG_INT_RX)
                {
                /* interrupt mode Rx */
                        while (size)
                        {
                                /* interrupt receive */
                                rt_base_t level;

                                /* disable interrupt */
                                level = rt_hw_interrupt_disable();
                                if (serial->rxd.read_index != serial->rxd.save_index)
                                {
                                        *ptr = serial->rxd.rx_buffer[serial->rxd.read_index];

                                        serial->rxd.read_index++;
                                        if (serial->rxd.read_index == RT_UART_BUFFER_SIZE)
                                                serial->rxd.read_index = 0;
                                }
                                else
                                {
                                        /* no data in rx buffer */

                                        /* enable interrupt */
                                        rt_hw_interrupt_enable(level);
                                        break;
                                }

                                /* enable interrupt */
                                rt_hw_interrupt_enable(level);

                                ptr ++; size --;
                        }
                }
        else
                {
                /* polling mode */
                /* not support right now */
                RT_ASSERT(0);
                }

        return (rt_uint32_t)ptr - ((rt_uint32_t)buffer + pos);
}

串口中断调用的函数
static void _rt_serial_handle_rxd(struct serial_device* serial)
{
        rt_uint8_t Buffer[UART_FIFO_SIZE];
        rt_uint8_t BufferCount;
        rt_uint8_t* pBuf;
        rt_uint8_t freebuffer;
        rt_uint8_t receive_size;

        if (serial == RT_NULL)
                return;

        pBuf = Buffer;               
        receive_size = 0;                       
        BufferCount = Uart_ReadBytesfromFIFO(serial->uart.Port, Buffer);
        if (serial->rxd.read_index <= serial->rxd.save_index)
                {freebuffer = RT_UART_BUFFER_SIZE - (serial->rxd.save_index - serial->rxd.read_index) - 1;}
        else
                {freebuffer = serial->rxd.read_index - serial->rxd.save_index - 1;}
        if (freebuffer == 0)
                receive_size = RT_UART_BUFFER_SIZE - 1;
        while (freebuffer && BufferCount)
                {
                serial->rxd.rx_buffer[serial->rxd.save_index++] = *pBuf++;
                if (serial->rxd.save_index == RT_UART_BUFFER_SIZE)
                        serial->rxd.save_index = 0;
                receive_size++;
                freebuffer--;
                BufferCount--;
                }

        /* invoke callback */
        if (serial->parent.rx_indicate != RT_NULL)
                {
                 serial->parent.rx_indicate(&serial->parent, receive_size);
                }       
}

还请帮忙验证一下,看问题出在哪里

出0入0汤圆

发表于 2012-4-16 16:15:31 | 显示全部楼层
学习了!!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 01:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表