本帖最后由 jorya_txj 于 2014-1-5 20:18 编辑
很多时候,用户发送具体消息的时候,也需要发送一个消息长度。比如在网卡中断中接收到了一包数据,发送消息给外面任务的时候,也需要告诉外面的任务消息的长度是多少。使用之前的queue模块做需要一点小技巧,但是使用queue_size模块做的话,显的很直接,直接可以发送出去。 带有消息长度的消息机制有一种很有用的用法。假设有一个串口接收中断来了,接收数据的话可以采用信号量+fifo 或者queue+块内存分配去做,但是这两种多多少少有些缺点。信号量+fifo的方式处理的话,fifo内部是关了cpu全局中断去操作的,如果数据量比较大的话,这个会严重影响实时性。queue +block内存区分配的话,如果中断接收每次来的数据都不同的话,会严重浪费内存。 有没有经济实用的不关中断,又节约内存的方式操作呢。答案是肯定的。当串口接收中断来的时候,用户需要自己维护一个简单的fifo缓冲区,但是这个缓冲区不需要关中断,写到头了重新回到头去写就好。当接收到数据填好缓冲区的时候,把缓冲区的这次数据起始地址以及数据长度通过raw_queue_size_end_post 发送出去。同时外面有一个任务调用raw_queue_size_receive接收数据。具体的示例如下: staticRAW_U32 recv_temp_buffer[12]; (1) staticRAW_U32 *uart_p; (2) staticRAW_U32 uart_data_length (3) void uart_int_recevie_handle(void) { RAW_U32 length_temp; RAW_U32 uart_recv_length; RAW_U8 *p_temp; uart_recv_length = 读串口数据的长度 length_temp = uart_recv_length; if (raw_queue_size_full_check()) { /*do something thing and return*/ return; } /*if isr receive data is faster than task data process, just ignore the data*/ if (uart_data_length >= (12 * 4)) { /*do something thing and return*/ return; } if ((uart_p + (uart_recv_length >> 2))> = (recv_temp_buffer + 12)) { uart_p = recv_temp_buffer; } p_temp = (RAW_U8 *)uart_p; while (length_temp--) { *p_temp++ = 串口数据; } queue_size_end_post(queue_size, uart_p, uart_recv_length); if(uart_recv_length & 3) { uart_data_length += 4u - (uart_recv_length& 3u)+ uart_recv_length; uart_p = uart_p + (uart_recv_length>> 2) + 1; } else { uart_p = uart_p + (uart_recv_length>> 2) uart_data_length += uart_recv_length; } } RAW_U32process_buffer[10]; void task_uart_receive() { RAW_U8 receive_size; void * msg_ptr; while (1) { raw_queue_size_receive(&q_size,RAW_WAIT_FOREVER, &msg_ptr, &receive_size); raw_memcpy(process_buffer,msg_ptr, receive_size); RAW_CPU_DISABLE(); if(receive_size & 3) { uart_data_length = uart_data_length - (4u- (receive_size & 3u) + receive_size); } else { uart_data_length -= receive_size; } RAW_CPU_ENABLE();
/*processsreceived data, processed time must be smaller than interrupt frequecy*/ } } (1)处用户自己维护了一个缓冲区,缓冲区的数据长度是48个字节。 (2)处代码的uart_p用来记录缓冲区的写位置。 (3)处代码维护一个长度,如果长度超过了缓冲区的长度就丢弃数据,返回,保证不会去覆盖缓冲区的数据。 以上的操作避免了临界区的缓冲区的操作,又节省了内存开销。而且数据执行效率上比起fifo也要高,因为少了一次copy动作。
|