/*
* Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
* SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* For additional information see http://www.ethernut.de/
*
*/
/*
* $Log: uartavr.c,v $
* Revision 1.4 2006/10/08 16:48:08 haraldkipp
* Documentation fixed
*
* Revision 1.3 2005/10/16 23:21:33 hwmaier
* Fixed compilation issue regards U2X macro with Imagecraft
*
* Revision 1.2 2005/10/07 22:01:27 hwmaier
* Obsolete dcb_baudSelect removed. Support for double speed (U2X) added (using same method as in usartavr.c).
*
* Revision 1.1 2005/07/26 18:02:40 haraldkipp
* Moved from dev.
*
* Revision 1.9 2005/07/14 09:12:20 freckle
* Rewrote CS in UartAvrInput
*
* Revision 1.8 2005/01/24 21:12:05 freckle
* renamed NutEventPostFromIRQ into NutEventPostFromIrq
*
* Revision 1.7 2005/01/21 16:49:46 freckle
* Seperated calls to NutEventPostAsync between Threads and IRQs
*
* Revision 1.6 2004/12/16 08:40:35 haraldkipp
* Late increment fixes ICCAVR bug.
*
* Revision 1.5 2004/05/24 20:15:50 drsung
* Added function UartAvrSize to return number of chars in input buffer.
*
* Revision 1.4 2004/03/18 14:01:07 haraldkipp
* Deprecated header file replaced
*
* Revision 1.3 2004/03/18 10:09:27 haraldkipp
* Removed deprecated raw I/O
*
* Revision 1.2 2003/07/20 18:28:10 haraldkipp
* Explain how to disable timeout.
*
* Revision 1.1.1.1 2003/05/09 14:40:55 haraldkipp
* Initial using 3.2.1
*
* Revision 1.21 2003/05/06 18:35:06 harald
* Avoid duplicate initialization
*
* Revision 1.20 2003/04/21 16:26:01 harald
* Use predefined eof
*
* Revision 1.19 2003/03/31 14:53:08 harald
* Prepare release 3.1
*
*/
#include <string.h>
#include <sys/atom.h>
#include <sys/heap.h>
#include <sys/event.h>
#include <sys/timer.h>
#include <sys/device.h>
#include <dev/irqreg.h>
#include <dev/uartavr.h>
#include <fcntl.h>
/*
* Not nice because stdio already defined them. But in order to save memory,
* we do the whole buffering and including stdio here would be more weird.
*/
#ifndef _IOFBF
#define _IOFBF 0x00
#define _IOLBF 0x01
#define _IONBF 0x02
#endif
/*
* Handle AVR UART transmit complete.
*/
static void TxComplete(void *arg)
{
NUTDEVICE *dev = (NUTDEVICE *) arg;
IFSTREAM *ifs = dev->dev_icb;
UARTDCB *dcb;
if (ifs->if_tx_idx != ifs->if_wr_idx) {
#ifdef UDR1
if (dev->dev_base)
UDR1 = ifs->if_tx_buf[ifs->if_tx_idx];
else
#endif
outp(ifs->if_tx_buf[ifs->if_tx_idx], UDR);
ifs->if_tx_idx++;
} else {
ifs->if_tx_act = 0;
dcb = dev->dev_dcb;
NutEventPostFromIrq(&dcb->dcb_tx_rdy);
}
}
/*
* Handle AVR UART receive complete.
*
* Note, that this function modifies the receive index in
* interrupt context. This requires, that any non atomic
* access of this index requires interrupts being disabled.
* Thanks to Mike Cornelius, who pointed this out.
*/
static void RxComplete(void *arg)
{
NUTDEVICE *dev = (NUTDEVICE *) arg;
IFSTREAM *ifs = dev->dev_icb;
UARTDCB *dcb;
#ifdef UDR1
if (dev->dev_base)
ifs->if_rx_buf[ifs->if_rx_idx] = inp(UDR1);
else
#endif
ifs->if_rx_buf[ifs->if_rx_idx] = inp(UDR);
if (ifs->if_rd_idx == ifs->if_rx_idx) {
dcb = dev->dev_dcb;
NutEventPostFromIrq(&dcb->dcb_rx_rdy);
}
/* Late increment fixes ICCAVR bug on volatile variables. */
ifs->if_rx_idx++;
}
int UartAvrInput(NUTDEVICE * dev)
{
int rc = 0;
int empty;
IFSTREAM *ifs = dev->dev_icb;
UARTDCB *dcb = dev->dev_dcb;
NutEnterCritical();
empty = ifs->if_rd_idx == ifs->if_rx_idx;
NutExitCritical();
if (empty) {
/*
* Changing if into a while loop fixes a serious bug:
* Previous receiver events without any waiting thread
* set the event handle to the signaled state. So the
* wait returns immediately. Unfortunately the calling
* routines rely on a filled buffer when we return 0.
* Thanks to Mike Cornelius, who found this bug.
*
* MR (2005-07-14): Reduced critical sections
*/
do {
rc = NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout);
NutEnterCritical();
empty = ifs->if_rd_idx == ifs->if_rx_idx;
NutExitCritical();
} while (rc == 0 && empty);
}
return rc;
}
int UartAvrOutput(NUTDEVICE * dev)
{
IFSTREAM *ifs = dev->dev_icb;
if (ifs->if_tx_act == 0 && ifs->if_tx_idx != ifs->if_wr_idx) {
ifs->if_tx_act = 1;
#ifdef UDR1
if (dev->dev_base)
UDR1 = ifs->if_tx_buf[ifs->if_tx_idx];
else
#endif
outp(ifs->if_tx_buf[ifs->if_tx_idx], UDR);
ifs->if_tx_idx++;
}
return 0;
}
int UartAvrFlush(NUTDEVICE * dev)
{
IFSTREAM *ifs = dev->dev_icb;
UARTDCB *dcb = dev->dev_dcb;
/*
* Start any pending output.
*/
if (UartAvrOutput(dev))
return -1;
/*
* Wait until output buffer empty.
*/
NutEnterCritical();
while (ifs->if_tx_idx != ifs->if_wr_idx)
NutEventWait(&dcb->dcb_tx_rdy, 100);
NutExitCritical();
return 0;
}
/*
*
* \param dev Indicates the UART device.
*
* \return 0 on success, -1 otherwise.
*/
static int UartAvrGetStatus(NUTDEVICE * dev, u_long * status)
{
IFSTREAM *ifs = dev->dev_icb;
u_char us;
*status = 0;
#ifdef UDR1
if (dev->dev_base)
us = inp(UCSR1A);
else
#endif
us = inp(USR);
if (us & FE)
*status |= UART_FRAMINGERROR;
if (us & DOR)
*status |= UART_OVERRUNERROR;
if (ifs->if_tx_idx == ifs->if_wr_idx)
*status |= UART_TXBUFFEREMPTY;
if (ifs->if_rd_idx == ifs->if_rx_idx)
*status |= UART_RXBUFFEREMPTY;
return 0;
}
/*
* Carefully enable UART functions.
*/
static void UartAvrEnable(u_short base)
{
NutEnterCritical();
#ifdef UCSR1B
if (base)
UCSR1B = BV(RXCIE) | BV(TXCIE) | BV(RXEN) | BV(TXEN);
else
#endif
UCR = BV(RXCIE) | BV(TXCIE) | BV(RXEN) | BV(TXEN);
NutExitCritical();
}
/*
* Carefully disable UART functions.
*/
static void UartAvrDisable(u_short base)
{
/*
uart.rar_ATMEGA128 UART
版权申诉
37 浏览量
2022-09-23
08:40:43
上传
评论
收藏 5KB RAR 举报
林当时
- 粉丝: 100
- 资源: 1万+
最新资源
- 1961ee27df03bd4595d28e24b00dde4e_744c805f7e4fb4d40fa3f695bfbab035_8(1).c
- mediapipe-0.9.0.1-cp37-cp37m-win-amd64.whl.zip
- windows注册表编辑工具
- mediapipe-0.9.0.1-cp37-cp37m-win-amd64.whl.zip
- 校园通行码预约管理系统20240522075502
- 车类型数据集6250张VOC+YOLO格式.zip
- The PyTorch implementation of STGCN.STGCN-main.zip
- 092300108.cpp
- 车类型数据集6000张VOC+YOLO格式.zip
- for daily read
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈