fsmcu 发表于 2010-12-15 10:36:43

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

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

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

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

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

ffxz 发表于 2010-12-15 11:14:30

请给个串口接收代码吧

fsmcu 发表于 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, 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++;
                                        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;
        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 = *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);
                }       
}

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

mlt911213 发表于 2012-4-16 16:15:31

学习了!!
页: [1]
查看完整版本: 2440平台处理串口接收数据采用信号量方式会当机