rtthread serial物理层驱动--基于LPC1778

RTT serial 设备的底层硬件驱动

一、需要用到的头文件

系统头文件

#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>

硬件相关头文件

#include "board.h"
#include "LPC177x_8x.h"
#include "lpc177x_8x_uart.h"
#include "lpc177x_8x_pinsel.h"

二、引脚配置

因为现在大部分的CPU的引脚功能是复用的,所以这一项必不可少。这里没有使用PIN设备,而使用的宏定义。当然,这部分的功能可以不在这里实现,在应用代码里通过PIN设备来配置。不过个人感觉没有必要。

#define pinConnectToTxduart0()   PINSEL_ConfigPin(0, 2, 1)
#define pinConnectToRxduart0()   PINSEL_ConfigPin(0, 3, 1)
...
#define pinConnectToTxduart4()   PINSEL_ConfigPin(5, 4, 4)
#define pinConnectToRxduart4()   PINSEL_ConfigPin(5, 3, 4)

#define configTxdPin(__num)      pinConnectToTxd##__num()
#define configRxdPin(__num)      pinConnectToRxd##__num()

用法如下:

configTxdPin(uart0);
configRxdPin(uart0); 

三、串口配置

这个结构体和各个芯片供应商提供的驱动有关,也可以自己写。

typedef struct {
  uint32_t Baud_rate;   		/**< UART baud rate */
  UART_PARITY_Type Parity;    	/**< Parity selection, should be:
							   - UART_PARITY_NONE: No parity
							   - UART_PARITY_ODD: Odd parity
							   - UART_PARITY_EVEN: Even parity
							   - UART_PARITY_SP_1: Forced "1" stick parity
							   - UART_PARITY_SP_0: Forced "0" stick parity
							   */
  UART_DATABIT_Type Databits;   /**< Number of data bits, should be:
							   - UART_DATABIT_5: UART 5 bit data mode
							   - UART_DATABIT_6: UART 6 bit data mode
							   - UART_DATABIT_7: UART 7 bit data mode
							   - UART_DATABIT_8: UART 8 bit data mode
							   */
  UART_STOPBIT_Type Stopbits;   /**< Number of stop bits, should be:
							   - UART_STOPBIT_1: UART 1 Stop Bits Select
							   - UART_STOPBIT_2: UART 2 Stop Bits Select
							   */
} UART_CFG_Type;

和芯片寄存器相关的用户自定义配置。用于指示当前对象所操作的目标硬件。

struct rt_uart_lpc
{
	LPC_UART_TypeDef * UART;
	IRQn_Type irq;
    UART_CFG_Type UART_ConfigStruct;
};

定义操作对象:
以下是驱动需要知道的内容,用户不关心。

struct rt_uart_lpc lpc_uart0 = 
{
    .UART = LPC_UART0,
    .irq = UART0_IRQn,
};
struct rt_serial_device uart0_device = 
{
    .ops = &uart_ops,
};

四、serial中需要的串口ops

static void uart_isr(struct rt_serial_device *serial) ;
rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t uart_control (struct rt_serial_device *serial, int cmd, void *arg);
static int uart_putc (struct rt_serial_device *serial, char c);
static int uart_getc (struct rt_serial_device *serial);
rt_size_t uart_dma_transmit (struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
const struct rt_uart_ops uart_ops = 
{
    uart_configure,
    uart_control,
    uart_putc,
    uart_getc,
    uart_dma_transmit,
};

下面关注以上几个函数如何实现。
中断函数入口

void UART0_IRQHandler(void)
{    
    /* enter interrupt */
    rt_interrupt_enter();

    uart_isr(&uart0_device);

    /* leave interrupt */
    rt_interrupt_leave();
}

串口中断使用的公共函数

static void uart_isr(struct rt_serial_device *serial) 
{
    struct rt_uart_lpc *uart = (struct rt_uart_lpc *) serial->parent.user_data;
    uint32_t    iir;

    RT_ASSERT(uart != RT_NULL);
    iir = UART_GetIntId(uart->UART);
    switch ( iir & 0x0E)
    {
        case UART_IIR_INTID_RDA:
            rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
            break;
        case UART_IIR_INTID_RLS:
            rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
            break;
        case UART_IIR_INTID_THRE:
            rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
            break;        
    }    
}

配置串口参数。

rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
    struct rt_uart_lpc *lpc_uart;    

    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);

    lpc_uart = (struct rt_uart_lpc *)serial->parent.user_data;

    lpc_uart->UART_ConfigStruct = default_uart_cfg;
    lpc_uart->UART_ConfigStruct.Baud_rate = cfg->baud_rate;  
    switch (cfg->data_bits)
    {
        case DATA_BITS_5:
            lpc_uart->UART_ConfigStruct.Databits  = UART_DATABIT_5;
        break;
        case DATA_BITS_6:
            lpc_uart->UART_ConfigStruct.Databits  = UART_DATABIT_6;
        break;
        case DATA_BITS_7:
            lpc_uart->UART_ConfigStruct.Databits  = UART_DATABIT_7;
        break;
        case DATA_BITS_8:
        default:
            lpc_uart->UART_ConfigStruct.Databits  = UART_DATABIT_8;
        break;
    }
    switch (cfg->stop_bits)
    {
        case STOP_BITS_1:
            lpc_uart->UART_ConfigStruct.Stopbits  = UART_STOPBIT_1;
        break;
        case STOP_BITS_2:
            lpc_uart->UART_ConfigStruct.Stopbits  = UART_STOPBIT_2;
        break;
        default:
            lpc_uart->UART_ConfigStruct.Stopbits  = UART_STOPBIT_1;
        break;
    }
  switch (cfg->parity)
  {
  case PARITY_NONE:
      lpc_uart->UART_ConfigStruct.Parity = UART_PARITY_NONE;
      break;
  case PARITY_ODD:
      lpc_uart->UART_ConfigStruct.Parity = UART_PARITY_ODD;
      break;
  case PARITY_EVEN:
      lpc_uart->UART_ConfigStruct.Parity = UART_PARITY_EVEN;
      break;
  default:
      lpc_uart->UART_ConfigStruct.Parity = UART_PARITY_NONE;
      break;
  }

  //if (HAL_UART_Init(&uart->UartHandle) != HAL_OK)
    UART_Init(lpc_uart->UART, &lpc_uart->UART_ConfigStruct);
    UART_TxCmd (lpc_uart->UART, ENABLE);
    return RT_EOK;    
}

控制串口收发模式:

static rt_err_t uart_control (struct rt_serial_device *serial, int cmd, void *arg)
{
    struct rt_uart_lpc *uart;  

    RT_ASSERT(serial != RT_NULL);
    uart = (struct rt_uart_lpc *)serial->parent.user_data;

    switch (cmd)
    {
        case RT_DEVICE_CTRL_CLR_INT:
            NVIC_DisableIRQ( uart->irq );
            UART_IntConfig( uart->UART, UART_INTCFG_THRE, DISABLE);
            UART_IntConfig( uart->UART, UART_INTCFG_RBR, DISABLE);
            break;
        case RT_SERIAL_RX_INT:
            /* enable rx irq */
            NVIC_EnableIRQ(uart->irq);
            /* enable interrupt */
            UART_IntConfig( uart->UART, UART_INTCFG_RBR, ENABLE);
            break;
        case RT_SERIAL_TX_INT:
            /* enable rx irq */
            NVIC_EnableIRQ(uart->irq);
            /* enable interrupt */
            UART_IntConfig( uart->UART, UART_INTCFG_THRE, ENABLE);
            break;
        case RT_DEVICE_CTRL_SET_INT:
            /* enable rx irq */
            NVIC_EnableIRQ(uart->irq);
            /* enable interrupt */
            UART_IntConfig( uart->UART, UART_INTCFG_RBR, ENABLE);
            break;
        case RT_DEVICE_CTRL_GET_INT:
            break;
    }
  return RT_EOK;
}

发送一个字节数据

static int uart_putc (struct rt_serial_device *serial, char c)
{    
    struct rt_uart_lpc *uart;    

    RT_ASSERT(serial != RT_NULL);

    uart = (struct rt_uart_lpc *)serial->parent.user_data;
    while (!(uart->UART->LSR & UART_LSR_THRE));
    
    UART_SendByte( uart->UART,c);
}

接收一个字节数据

static int uart_getc (struct rt_serial_device *serial)
{
    struct rt_uart_lpc *uart;    

    RT_ASSERT(serial != RT_NULL);
    uart = (struct rt_uart_lpc *)serial->parent.user_data;
    if (!(uart->UART->LSR & UART_LSR_RDR)) return -1;
    
    return uart->UART->RBR;    
}

串口注册

void rt_hw_uart_init(void)
{
    struct serial_configure cfg ;
    cfg.baud_rate = boundRateUart0;
    cfg.bit_order = BIT_ORDER_LSB;
    cfg.bufsz = 32;
    cfg.data_bits = DATA_BITS_8;
    cfg.invert = NRZ_NORMAL;
    cfg.parity = PARITY_NONE;
    cfg.stop_bits = STOP_BITS_1;
    
#ifdef RT_USING_UART0
    configTxdPin(uart0);
    configRxdPin(uart0);  
    cfg.baud_rate = boundRateUart0;  
    uart0_device.config = cfg;
    rt_hw_serial_register(&uart0_device,
                               "uart0",
                               RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                               &lpc_uart0); 
    uart_configure (&uart0_device, &cfg); 	//注册的时候配置的目的是图省事儿,不改变rt_hw_board_init()函数的顺序及代码的同时不影响shell的使用
#endif
}

参考了stm32f429-disco相关部分代码的编写

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值