Ответ:
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено #1075;#1086;#1096;#1072; 13 июня 2004 г. 13:11
В ответ на: Подскажите, СОМ-порт, сигнал RTS высталяется всегда, или только когда вкл. аппаратное управление? отправлено aljarkov 13 июня 2004 г. 11:04


/*
Copyright 2001, QNX Software Systems Ltd. All Rights Reserved

This source code has been published by QNX Software Systems Ltd. (QSSL).
However, any use, reproduction, modification, distribution or transfer of
this software, or any software which includes or is based upon any of this
code, is only permitted under the terms of the QNX Community License version
1.0 (see licensing.qnx.com for details) or as otherwise expressly authorized
by a written license agreement from QSSL. For more information, please email
licensing@qnx.com.
*/
#include "externs.h"

int tto(TTYDEV *ttydev, int action, int arg1)
{TTYBUF *bup = &ttydev->obuf;
DEV_8250 *dev = (DEV_8250 *)ttydev;
const uintptr_t *port = dev->port;
int status = 0;
unsigned char c;

switch(action)
{case TTO_STTY: ser_stty(dev); return(0); /* set baud rate, nbits, parity */
case TTO_CTRL: if(arg1 & _SERCTL_BRK_CHG) /* управление прм/передачей */
set_port(port[REG_LC], LCR_BREAK, arg1 &_SERCTL_BRK ? LCR_BREAK : 0);
if(arg1 & _SERCTL_DTR_CHG)
set_port(port[REG_MC], MCR_DTR, arg1 & _SERCTL_DTR ? MCR_DTR : 0);
if(arg1 & _SERCTL_RTS_CHG)
set_port(port[REG_MC], MCR_RTS, arg1 & _SERCTL_RTS ? MCR_RTS : 0);
return(0);
case TTO_LINESTATUS: return(((in8(port[REG_MS]) << 8) | in8(port[REG_MC])) & 0xf003);
case TTO_DATA: break;
default: return(0);
}

if(dev->tty.flags & (OHW_PAGED|OSW_PAGED))
{return(0);}
dev_lock(&dev->tty);
if(bup->cnt > 0) /* кольцевой буфер отправки не пуст */
{if( (in8(port[REG_LS]) & LSR_TXRDY) || ( dev->tx_fifo > 0 && arg1 == FIFO_XMIT_OVERRIDE) )
{// Get the next character to print from the output buffer
c = *bup->tail;
if(c == '\n' && ((dev->tty.c_oflag & (OPOST | ONLCR)) == (OPOST | ONLCR)) && ((dev->tty.flags & NL_INSERT) == 0))
{c = '\r'; atomic_set(&dev->tty.flags, NL_INSERT);}
else
{atomic_clr(&dev->tty.flags, NL_INSERT);
if(++bup->tail >= &bup->buff[bup->size])
bup->tail = &bup->buff[0];
--bup->cnt;
}
// Print the character
dev->tty.un.s.tx_tmr = 3; /* Timeout */
printf("devc-maxa> cmd= %hhd tx %02x\n",dev->ocmd, c);
if(dev->ocmd==0)
{switch(c)
{case 0x01: dev->tx_counter=1; dev->ocmd=c; out8(port[REG_TX], c); break;
case 0x02: dev->tx_counter=1; dev->ocmd=c; out8(port[REG_TX], c); break;
case 0x03: dev->tx_counter=1; dev->ocmd=c; dev->tx_crc=c; out8(port[REG_TX], c); break;
case 0x04: dev->tx_counter=1; dev->ocmd=c; dev->rx_crc=c; out8(port[REG_TX], c); break;
case 0x05: dev->tx_counter=1; dev->ocmd=c; out8(port[REG_TX], c); break;
default: out8(port[REG_TX], c); break;
}
}
else
{switch(dev->ocmd)
{case 0x01:
case 0x02: dev->tx_counter=0; dev->ocmd=0; out8(port[REG_TX], c); break;
case 0x03: dev->tx_crc+=c;
if(++dev->tx_counter == 10)
{out8(port[REG_TX], c);
printf("devc-maxa> cmd3 tx counter=%d\n", dev->tx_counter);
out8(port[REG_TX], 0x55);
dev->tx_crc+=0x55;
//dev->tx_crc= ~dev->tx_crc;
//dev->tx_crc+=0x01;
printf("devc-maxa> cmd3 write 0x55\n" );
out8(port[REG_TX], dev->tx_crc);
printf("devc-maxa> cmd3 t write crc=%hhx\n", dev->tx_crc);
break;
}
if(dev->tx_counter == 2) dev->tx_crc=0;
out8(port[REG_TX], c); break;
printf("devc-maxa> cmd3 tx counter=%d\n", dev->tx_counter);
case 0x04: dev->tx_crc+=c;
case 0x05: out8(port[REG_TX], c); break;
default: out8(port[REG_TX], c); dev->ocmd=0; dev->tx_counter=0; break;
}
}
out8(port[REG_MC], in8(port[REG_MC]) | 0x02);
}
dev_unlock(&dev->tty);
} else {
dev_unlock(&dev->tty);

// Check for notify conditions
if(dev->tty.notify[1].cnt < bup->size - bup->cnt) {
dev->tty.notify[1].cnt = (~0u) >> 1; // Disarm
atomic_set(&dev->tty.flags, EVENT_NOTIFY_OUTPUT);
status = 1;
}

// Is anyone waiting for the output buffer to drain?
if(dev->tty.waiting_drain && bup->cnt == 0) {
atomic_set(&dev->tty.flags, EVENT_DRAIN);
status = 1;
}
}

// If anyone is waiting to write, kick them when buffer drains to 1/4 full.
if(dev->tty.waiting_write && bup->cnt < bup->size/4) {
atomic_set(&dev->tty.flags, EVENT_WRITE);
return(1);
}

return(status);
}
/*===========================================================================*/
void ser_stty(DEV_8250 *dev)
{ unsigned lcr = 0;
const uintptr_t *port = dev->port;
unsigned value;

// Set Baud rate
value = (dev->tty.baud == 0) ? 0 : (dev->clk/(dev->tty.baud * dev->div));
printf("devc-maxa> div= %d\n ", value);
dev_lock(&dev->tty);
set_port(port[REG_LC], LCR_DLAB, LCR_DLAB); /* установка скорости обмена по rs232 */
set_port(port[REG_DL0], 0xff, value & 0xff); /* W Divisor Latch 0 */
set_port(port[REG_DL1], 0xff, value >> 8); /* W Divisor Latch 0 */
set_port(port[REG_LC], LCR_DLAB, 0); /* Бит доступа к регистру установки скорости=0 */
dev_unlock(&dev->tty);

// Set data bits
switch(dev->tty.c_cflag & CSIZE)
{case CS8: ++lcr;
case CS7: ++lcr;
case CS6: ++lcr;
}

// Set stop bits
if(dev->tty.c_cflag & CSTOPB)
lcr |= LCR_STB2;

// Set parity bits
if(dev->tty.c_cflag & PARENB)
lcr |= LCR_PEN;

if((dev->tty.c_cflag & PARODD) == 0)
lcr |= LCR_EPS;

set_port(port[REG_LC], 0xFF, lcr);

// turn on DTR, RTS
set_port(port[REG_MC], MCR_DTR|MCR_RTS, MCR_DTR|MCR_RTS);

// Extract the rx and tx fifo sizes
dev->rx_fifo = dev->tty.fifo & 0xf;
dev->tx_fifo = (dev->tty.fifo >> 4) & 0xf;

// Set RX fifo trigger level
switch(dev->rx_fifo)
{case 1: value = 0x01; break;
case 4: value = 0x41; break;
case 8: value = 0x81; break;
case 14: value = 0xC1; break;
default: value = 0x00; break;
}

if(value)
{//
// Try to enable 1/4/8/14-deep FIFO mode if a 16550
// NOTE: That this is NOT always desirable since it significantly
// affects recieved character timing, and does NOT
// significantly increase receive performance.
// (Keep in mind that the 16550 with FIFO disabled
// is still very useful, since it SHOULD buffer
// up to 16 received characters even when FIFO is off)
//
out8(port[REG_FC], value);
if((in8(port[REG_II]) & II_FIFO) == 0)
{// No FIFO, not an 16550 so reset FIFO
out8(port[REG_FC], 0x00);
}
}
}
/*===========================================================================*/
#if 0
void
ser_ctrl(DEV_8250 *dev, unsigned flags) {

if(flags & _SERCTL_BRK_CHG)
set_port(dev->port[REG_LC], LCR_BREAK, flags &_SERCTL_BRK ? LCR_BREAK : 0);

if(flags & _SERCTL_DTR_CHG)
set_port(dev->port[REG_MC], MCR_DTR, flags & _SERCTL_DTR ? MCR_DTR : 0);

if(flags & _SERCTL_RTS_CHG)
set_port(dev->port[REG_MC], MCR_RTS, flags & _SERCTL_RTS ? MCR_RTS : 0);
}
#endif

int drain_check(TTYDEV *ttydev, uintptr_t *count) {
TTYBUF *bup = &ttydev->obuf;
DEV_8250 *dev = (DEV_8250 *)ttydev;
const uintptr_t *port = dev->port;

// if the device has DRAINED, return 1
if (dev->tty.waiting_drain && (bup->cnt == 0) &&
(in8(port[REG_LS]) & LSR_TSRE)) return 1;

// if the device has not DRAINED, set a timer based on 50ms counts
// wait for the time it takes for one character to be transmitted
// out the shift register. We do this dynamically since the
// baud rate can change.
*count = ((IO_CHAR_DEFAULT_BITSIZE * 20) / ttydev->baud) + 1;

return 0;
}


Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru