wuyage

MQX之UART使用

0
阅读(2537)

串口最常用的两个功能就是查询方式发送数据和中断方式接收数据。
在MQX该如何实现呢?
以FRDM_K64f +Freescale_MQX_4_1_FRDMK64F 为例来说明。
实现的功能是:
1)UART0 用作printf
2)UART1 实现查询发送和中断接收
中断接收的过程我采用的方法是:在MQX uart驱动的基础上增加callback函数,在callback函数中通过lwsem手段通知另外一个读串口数据的任务

UART1使用的是PTC3和PTC4,开发板上的接口如下:
这里写图片描述

实现步骤如下:
1)user_config.h 中

#define BSPCFG_ENABLE_TTYB 1 // wenxue 0->1 #define BSPCFG_ENABLE_ITTYB 1 // wenxue 0->1

2)在 serinprv.h 中增加一个回调函数
先声明

typedef void (_CODE_PTR_ UART_NOTIFICATION_FPTR)(void *); // wenxue 2015-10-12

在io_serial_int_device_struct 这个结构中加入

/* UART Notification Callback wenxue 2015-10-12 */ UART_NOTIFICATION_FPTR DEV_RX_TX_CALLBACK;

3)serl_int_kuart.c 中的_kuart_int_rx_tx_isr 函数中加入回调函数的调用

if (stat & UART_S1_RDRF_MASK) { // reading 'D' register performs also cleanup of 'S1' c = sci_ptr->D; if (!_io_serial_int_addc(int_io_dev_ptr, c)) { sci_info_ptr->RX_DROPPED_INPUT++; } sci_info_ptr->RX_CHARS++; /* call UART CALL Back function if installed wenxue 2015-10-12*/ if(int_io_dev_ptr->DEV_RX_TX_CALLBACK != NULL) int_io_dev_ptr->DEV_RX_TX_CALLBACK(int_io_dev_ptr); }

4)serl_int.c和serial.h 增加ioctl 安装回调函数的支持
_io_serial_int_ioctl 中

/* add IO_IOCTL_SERIAL_SET_RXTX_CALLBACK wenxue 2015-10-12 */ case IO_IOCTL_SERIAL_SET_RXTX_CALLBACK: int_io_dev_ptr->DEV_RX_TX_CALLBACK = (UART_NOTIFICATION_FPTR)param_ptr; break;
#define IO_IOCTL_SERIAL_SET_RXTX_CALLBACK _IO(IO_TYPE_SERIAL, 0x1F)

以上修改完成后,重新编译bsp工程

5)在原hello 工程中做修改,完成应用程序

/*HEADER********************************************************************** * * Copyright 2008 Freescale Semiconductor, Inc. * Copyright 1989-2008 ARC International * * This software is owned or controlled by Freescale Semiconductor. * Use of this software is governed by the Freescale MQX RTOS License * distributed with this Material. * See the MQX_RTOS_LICENSE file distributed for more details. * * Brief License Summary: * This software is provided in source form for you to use free of charge, * but it is not open source software. You are allowed to use this software * but you cannot redistribute it or derivative works of it in source form. * The software may be used only in connection with a product containing * a Freescale microprocessor, microcontroller, or digital signal processor. * See license agreement file for full license terms including other * restrictions. ***************************************************************************** * * Comments: * * This file contains the source for the hello example program. * * *END************************************************************************/ #include #include #include #if ! BSPCFG_ENABLE_IO_SUBSYSTEM #error This application requires BSPCFG_ENABLE_IO_SUBSYSTEM defined non-zero in user_config.h. Please recompile BSP with this option. #endif #ifndef BSP_DEFAULT_IO_CHANNEL_DEFINED #error This application requires BSP_DEFAULT_IO_CHANNEL to be not NULL. Please set corresponding BSPCFG_ENABLE_TTYx to non-zero in user_config.h and recompile BSP with this option. #endif /* Task IDs */ #define HELLO_TASK 5 #define READ_TASK 6 extern void hello_task(uint32_t); extern void read_task(uint32_t initial_data); MQX_FILE_PTR uart1_int_dev = NULL; void uart1_rx_callback(void *param); LWSEM_STRUCT uart1_frame_received; // wenxue const TASK_TEMPLATE_STRUCT MQX_template_list[] = { /* Task Index, Function, Stack, Priority, Name, Attributes, Param, Time Slice */ { HELLO_TASK, hello_task, 1500, 8, "hello", MQX_AUTO_START_TASK, 0, 0 }, { READ_TASK, read_task, 1000, 8, "read", MQX_AUTO_START_TASK, 0, 0 }, // added by wenxue { 0 } }; /*TASK*----------------------------------------------------- * * Task Name : hello_task * Comments : * This task prints " Hello World " * *END*-----------------------------------------------------*/ void hello_task ( uint32_t initial_data ) { (void)initial_data; /* disable 'unused variable' warning */ uint32_t result; MQX_FILE_PTR uart1_dev = NULL; int buad = 115200; char data_buffer[]="I Love Beijing\r\n"; printf("Hello World\n"); // uart0 uart1_dev=fopen( "ttyb:", NULL); if( uart1_dev == NULL ) { /* device could noFt be opened */ _task_block(); } /* Set baud as 115200 */ result = ioctl(uart1_dev,IO_IOCTL_SERIAL_SET_BAUD,&buad); if( result == IO_ERROR_INVALID_IOCTL_CMD ) { /* ioctl not supported, use newer MQX version */ _task_block(); } /* send data to uart */ write( uart1_dev, data_buffer, strlen(data_buffer)); /* wait for transfer complete flag */ result = ioctl( uart1_dev, IO_IOCTL_SERIAL_WAIT_FOR_TC, NULL ); if( result == IO_ERROR_INVALID_IOCTL_CMD ) { /* ioctl not supported, use newer MQX version */ _task_block(); } fclose(uart1_dev); // uart1_int_dev=fopen( "ittyb:", NULL); uart1_int_dev=fopen( "ittyb:", (char const *) IO_SERIAL_NON_BLOCKING); if( uart1_dev == NULL ) { /* device could not be opened */ _task_block(); } result = ioctl( uart1_int_dev, IO_IOCTL_SERIAL_SET_RXTX_CALLBACK, (void*)uart1_rx_callback ); if( result == IO_ERROR_INVALID_IOCTL_CMD ) { /* ioctl not supported, use newer MQX version */ _task_block(); } /* Create the lightweight semaphores */ result = _lwsem_create(&uart1_frame_received, 0); if (result != MQX_OK) { printf("\nCreating read_sem failed: 0x%X", result); _task_block(); } /* Has already called _int_install_isr(sci_init_ptr->RX_TX_VECTOR, _kuart_int_rx_tx_isr, int_io_dev_ptr); wenxue*/ //_int_install_isr(INT_UART1_RX_TX, UART1_RX_ISR,NULL); _task_block(); } void uart1_rx_callback(void *param) { _lwsem_post(&uart1_frame_received); } /*TASK*-------------------------------------------------------- * * Task Name : read_task * Comments : This task used to read uart data * *END*--------------------------------------------------------*/ void read_task ( uint32_t initial_data ) { uint32_t bytesRead; int num=0; char data_buffer[100]; printf("\n read task created: 0x%lX", initial_data); while (TRUE) { if (_lwsem_wait(&uart1_frame_received) != MQX_OK) { printf("\n_lwsem_wait failed"); _task_block(); } /* read data */ bytesRead= fread(data_buffer, 1, 20, uart1_int_dev); /* write data */ fwrite(data_buffer,1,bytesRead,uart1_int_dev); } } /* EOF */

另外需要说明的是:

uart1_int_dev=fopen( "ittyb:", NULL);打开方式是默认的blocking 方式

bytesRead= fread(data_buffer, 1, 20, uart1_int_dev);如果通过fread 读取多字节数据,如果串口没有接收到20字节数据,那么会阻塞在这里,直到读取20字节完成才往下执行。

也可以uart1_int_dev=fopen( “ittyb:”, (char const *) IO_SERIAL_NON_BLOCKING); 以Non blocking方式打开,这时fread可以立刻返回。此时任务的执行过程是:每次接收到1个字节数据,进中断,释放信号量,read task 等到信号量然后通过fread读出,最后fwrite发送出去。所以尽管fread的参数是20,但其实每次都是读到1字节。

实验现象是:
UART1 先输出 I Love Beijing
在UART1 接收到一串字符后,通过UART1再输出。


Baidu
map