rt-thread-official/bsp/simulator/drivers/serial.c

219 lines
6.0 KiB
C
Raw Normal View History

2013-01-08 22:40:58 +08:00
/*
* File : serial.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013 RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-02-05 Bernard first version
* 2009-10-25 Bernard fix rt_serial_read bug when there is no data
* in the buffer.
* 2010-03-29 Bernard cleanup code.
* 2013-02-7 prife rewrite for simulator
*/
2013-01-08 22:40:58 +08:00
#include <rthw.h>
#include "serial.h"
#include <stdio.h>
2013-01-22 16:57:47 +08:00
#if 0
2013-01-08 22:40:58 +08:00
static FILE *fp = RT_NULL;
2013-01-22 16:57:47 +08:00
#endif
2013-01-08 22:40:58 +08:00
/*@{*/
int seial_save_byte(unsigned char ch, struct serial_device * serial)
{
/* save on rx buffer */
rt_base_t level;
struct rt_device * dev = RT_DEVICE(serial);
/* disable interrupt */
//<2F><>ʱ<EFBFBD>ر<EFBFBD><D8B1>жϣ<D0B6><CFA3><EFBFBD>ΪҪ<CEAA><D2AA><EFBFBD><EFBFBD>uart<72><74><EFBFBD>ݽṹ
level = rt_hw_interrupt_disable();
/* save character */
serial->serial_rx.rx_buffer[serial->serial_rx.save_index] = ch;
serial->serial_rx.save_index ++;
//<2F><><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>save_index<65>Ƿ<EFBFBD><C7B7>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><CEB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊһ<CEAA><D2BB><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>
if (serial->serial_rx.save_index >= SERIAL_RX_BUFFER_SIZE)
serial->serial_rx.save_index = 0;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>save_index׷<78><D7B7><EFBFBD><EFBFBD>read_index<65><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>read_index<65><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ɵ<EFBFBD><C9B5><EFBFBD><EFBFBD><EFBFBD>
/* if the next position is read index, discard this 'read char' */
if (serial->serial_rx.save_index == serial->serial_rx.read_index)
{
serial->serial_rx.read_index ++;
if (serial->serial_rx.read_index >= SERIAL_RX_BUFFER_SIZE)
serial->serial_rx.read_index = 0;
}
/* enable interrupt */
//uart<72><74><EFBFBD>ݽṹ<DDBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ж<EFBFBD>
rt_hw_interrupt_enable(level);
/* invoke callback */
if (dev->rx_indicate != RT_NULL)
{
rt_size_t rx_length;
/* get rx length */
rx_length = serial->serial_rx.read_index > serial->serial_rx.save_index ?
SERIAL_RX_BUFFER_SIZE - serial->serial_rx.read_index + serial->serial_rx.save_index :
serial->serial_rx.save_index - serial->serial_rx.read_index;
dev->rx_indicate(dev, rx_length);
}
return 0;
}
2013-01-08 22:40:58 +08:00
/* RT-Thread Device Interface */
/**
* This function initializes serial
*/
static rt_err_t rt_serial_init(rt_device_t dev)
{
struct serial_device * serial = SERIAL_DEVICE(dev);
2013-01-08 22:40:58 +08:00
if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
{
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
rt_memset(serial->serial_rx.rx_buffer, 0,
sizeof(serial->serial_rx.rx_buffer));
serial->serial_rx.read_index = 0;
serial->serial_rx.save_index = 0;
2013-01-08 22:40:58 +08:00
}
dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
}
return RT_EOK;
}
static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t rt_serial_close(rt_device_t dev)
{
return RT_EOK;
}
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;
rt_err_t err_code;
struct serial_device * serial = SERIAL_DEVICE(dev);
2013-01-08 22:40:58 +08:00
ptr = buffer;
err_code = RT_EOK;
if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{
/* interrupt mode Rx */
while (size)
{
rt_base_t level;
/* disable interrupt */
level = rt_hw_interrupt_disable();
if (serial->serial_rx.read_index != serial->serial_rx.save_index)
2013-01-08 22:40:58 +08:00
{
/* read a character */
*ptr++ = serial->serial_rx.rx_buffer[serial->serial_rx.read_index];
2013-01-08 22:40:58 +08:00
size--;
/* move to next position */
serial->serial_rx.read_index ++;
if (serial->serial_rx.read_index >= SERIAL_RX_BUFFER_SIZE)
serial->serial_rx.read_index = 0;
2013-01-08 22:40:58 +08:00
}
else
{
/* set error code */
err_code = -RT_EEMPTY;
/* enable interrupt */
rt_hw_interrupt_enable(level);
break;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
}
}
/* set error code */
rt_set_errno(err_code);
return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
}
static rt_size_t rt_serial_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
int level;
2013-01-22 16:57:47 +08:00
#if 0
2013-01-08 22:40:58 +08:00
if (fp == NULL)
fp = fopen("log.txt", "wb+");
if (fp != NULL)
fwrite(buffer, size, 1, fp);
2013-01-22 16:57:47 +08:00
#endif
2013-01-08 22:40:58 +08:00
level = rt_hw_interrupt_disable();
2013-01-08 22:40:58 +08:00
printf("%s", (char *)buffer);
2013-01-22 16:57:47 +08:00
fflush(stdout);
rt_hw_interrupt_enable(level);
2013-01-08 22:40:58 +08:00
return size;
}
static rt_err_t rt_serial_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
RT_ASSERT(dev != RT_NULL);
switch (cmd)
{
case RT_DEVICE_CTRL_SUSPEND:
/* suspend device */
dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
break;
case RT_DEVICE_CTRL_RESUME:
/* resume device */
dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
break;
}
return RT_EOK;
}
/*
* serial register
*/
rt_err_t rt_hw_serial_register(rt_device_t device, const char *name, rt_uint32_t flag)
2013-01-08 22:40:58 +08:00
{
RT_ASSERT(device != RT_NULL);
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->init = rt_serial_init;
device->open = rt_serial_open;
device->close = rt_serial_close;
device->read = rt_serial_read;
device->write = rt_serial_write;
device->control = rt_serial_control;
device->user_data = RT_NULL;
/* register a character device */
return rt_device_register(device, name, (rt_uint16_t)(RT_DEVICE_FLAG_RDWR | flag));
}
rt_err_t rt_hw_serial_init(struct serial_device * serial, char * name)
2013-01-08 22:40:58 +08:00
{
return rt_hw_serial_register(RT_DEVICE(serial), name,
2013-01-08 22:40:58 +08:00
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM);
}