|
ARM 7 (at91sam7x) Драйвер для UART |
|
|
|
Oct 9 2012, 12:16
|
Группа: Участник
Сообщений: 12
Регистрация: 17-04-12
Пользователь №: 71 418

|
Приветствую, Благородные Доны и Донны. Занимаюсь программированием микроконтроллеров недавно. Написал драйвер для UART и надеюсь услышать критику и предложения. Может быть пригодится кому... Просто, кроме страшного атмеловского примера и нескольких весьма специфичных реализаций, внятного примера работы с Uart я не нашел... Не ругайте за отсутствие комментариев... Старался писать код максимально понятно... usart_ex.h CODE #ifndef USART_EX_H #define USART_EX_H //----------------------------------------------------------------------------- #include <board.h> //----------------------------------------------------------------------------- namespace usart { typedef unsigned int handle_type; typedef unsigned int id_type; typedef unsigned int mode_type; typedef unsigned int size_type; typedef unsigned int baudrate_type; typedef unsigned char error_type; typedef unsigned int sync_frequency_type; //--------------------------------------------------------------------------- enum { TX_BUFFER_SIZE = 128, RX_BUFFER_SIZE = 128 }; // доступные интерфейсы usart enum EUsartId { id0 = 0, id1 = 1, idCount, idInvalid = 0xFF }; // ошибки usart enum EUsartError { eOk = 0, eTxBufferOverflow = 1, eRxBufferOverflow = 2, eFrameError = AT91C_US_FRAME, eReceiveOverrun = AT91C_US_OVRE, eParityError = AT91C_US_PARE, eHardwareError = eFrameError | eReceiveOverrun | eParityError }; //--------------------------------------------------------------------------- void Init(void); handle_type Open(const id_type usartId, const mode_type mode, const baudrate_type baudRate, const sync_frequency_type masterClockFrequency = BOARD_MCK); bool IsError(const handle_type handle); error_type Error(const handle_type handle); bool IsInvalidHandle(const handle_type handle); bool IsDataAvailableForReading(const handle_type handle); void WaitForData(const handle_type handle); size_type Read(const handle_type handle, unsigned char* const data); size_type ReadBuffer(const handle_type handle, unsigned char* const buffer, const size_type bufferSize); void Write(const handle_type handle, const unsigned char data); void WriteBuffer(const handle_type handle, const unsigned char* const buffer, const size_type bufferSize); void Flush(const handle_type handle); void RFlush(const handle_type handle); void WFlush(const handle_type handle); void Close(handle_type* const handle); //--------------------------------------------------------------------------- } #endif
usart_ex.cpp CODE #include "usart_ex.h" #include "..\kernel\ring_buffer.h" #include <board.h> #include <pio/pio.h> #include <irq/irq.h> #include <pmc/pmc.h> #include <utility/assert.h> #include <utility/math.h> //-----------------------------------------------------------------------------
namespace usart { namespace tools { typedef void (*FIrqHandlerCPtr)(void);
struct CUsartInfo { unsigned int id_; AT91S_USART* usart_; FIrqHandlerCPtr irqHandler_; unsigned char txBuffer_[TX_BUFFER_SIZE]; unsigned char rxBuffer_[RX_BUFFER_SIZE]; struct kernel::ringb::CRingBuffer txRingBuffer_; struct kernel::ringb::CRingBuffer rxRingBuffer_; }; //--------------------------------------------------------------------------- static struct CUsartInfo usarts_[idCount]; static error_type usartErrors_[idCount]; static const Pin usartPins_[] = { BOARD_PIN_USART_RXD, BOARD_PIN_USART_TXD, BOARD_PIN_USART_CTS, BOARD_PIN_USART_RTS }; //---------------------------------------------------------------------------
inline void doIrqHandler(handle_type handle) { tools::CUsartInfo* const info = &tools::usarts_[handle]; unsigned int status = info->usart_->US_CSR; status &= info->usart_->US_IMR; if ((status & eHardwareError)) { usartErrors_[id0] |= (status & eHardwareError); info->usart_->US_IDR = AT91C_US_TXRDY | AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE; } if ((status & AT91C_US_TXRDY) == AT91C_US_TXRDY) { if (kernel::ringb::IsEmpty(&info->txRingBuffer_)) { info->usart_->US_IDR = AT91C_US_TXRDY; } else { unsigned char writedToken(0); kernel::ringb::Read(&info->txRingBuffer_, writedToken); info->usart_->US_THR = writedToken; } } if ((status & AT91C_US_RXRDY) == AT91C_US_RXRDY) { if (kernel::ringb::IsFull(&info->rxRingBuffer_)) { volatile const unsigned int rhr = info->usart_->US_RHR; usartErrors_[id0] |= eRxBufferOverflow; return; } kernel::ringb::Write(&info->rxRingBuffer_, info->usart_->US_RHR); } }
void IrqHandler0(void) { doIrqHandler(id0); } void IrqHandler1(void) { doIrqHandler(id1); } } //---------------------------------------------------------------------------
void Init(void) { PIO_Configure(tools::usartPins_, PIO_LISTSIZE(tools::usartPins_));
tools::usarts_[id0].usart_ = AT91C_BASE_US0; tools::usarts_[id0].id_ = AT91C_ID_US0; tools::usarts_[id0].irqHandler_ = tools::IrqHandler0;
tools::usarts_[id1].usart_ = AT91C_BASE_US1; tools::usarts_[id1].id_ = AT91C_ID_US1; tools::usarts_[id1].irqHandler_ = tools::IrqHandler1; for (unsigned char i(0); i < idCount; ++i) { kernel::ringb::Init(&tools::usarts_[i].txRingBuffer_, tools::usarts_[i].txBuffer_, TX_BUFFER_SIZE); kernel::ringb::Init(&tools::usarts_[i].rxRingBuffer_, tools::usarts_[i].rxBuffer_, RX_BUFFER_SIZE); tools::usartErrors_[i] = eOk; } } //--------------------------------------------------------------------------- handle_type Open(const id_type usartId, const mode_type mode, const baudrate_type baudRate, const sync_frequency_type masterClockFrequency) { SANITY_CHECK(usartId < idCount && baudRate && ((mode & AT91C_US_USMODE_ISO7816_0) != AT91C_US_USMODE_ISO7816_0) && ((mode & AT91C_US_USMODE_ISO7816_1) != AT91C_US_USMODE_ISO7816_1) && ((mode & AT91C_US_USMODE_IRDA) != AT91C_US_USMODE_IRDA)); tools::CUsartInfo* const info = &tools::usarts_[usartId];
kernel::ringb::Clear(&info->txRingBuffer_); kernel::ringb::Clear(&info->rxRingBuffer_); tools::usartErrors_[usartId] = eOk; PMC_EnablePeripheral(info->id_);
info->usart_->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA; info->usart_->US_MR = mode; if ((info->usart_->US_MR & AT91C_US_SYNC)) { info->usart_->US_BRGR = masterClockFrequency / baudRate; } else { const unsigned char freqSemplingMode = (info->usart_->US_MR & AT91C_US_OVER) ? 1 : 2; info->usart_->US_BRGR = masterClockFrequency / (8 * freqSemplingMode * baudRate); }
info->usart_->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE; info->usart_->US_CR = AT91C_US_RXEN | AT91C_US_TXEN ;
IRQ_ConfigureIT(info->id_, 0, info->irqHandler_); IRQ_EnableIT(info->id_); return usartId; } //--------------------------------------------------------------------------- bool IsError(const handle_type handle) { SANITY_CHECK(!IsInvalidHandle(handle)); return tools::usartErrors_[handle] != eOk; } //--------------------------------------------------------------------------- error_type Error(const handle_type handle) { SANITY_CHECK(!IsInvalidHandle(handle)); return tools::usartErrors_[handle]; } //--------------------------------------------------------------------------- bool IsInvalidHandle(const handle_type handle) { return handle >= idCount; } //--------------------------------------------------------------------------- bool IsDataAvailableForReading(const handle_type handle) { SANITY_CHECK(!IsInvalidHandle(handle)); return !kernel::ringb::IsEmpty(&tools::usarts_[handle].rxRingBuffer_); } //--------------------------------------------------------------------------- void WaitForData(const handle_type handle) { SANITY_CHECK(!IsInvalidHandle(handle));
while (!IsDataAvailableForReading(handle)) { continue; } } //--------------------------------------------------------------------------- size_type Read(const handle_type handle, unsigned char* const data) { SANITY_CHECK(!IsInvalidHandle(handle) && data); tools::CUsartInfo* const info = &tools::usarts_[handle]; if (!kernel::ringb::IsEmpty(&info->rxRingBuffer_)) { return kernel::ringb::Read(&info->rxRingBuffer_, *data); } return 0; } //--------------------------------------------------------------------------- size_type ReadBuffer(const handle_type handle, unsigned char* const buffer, const size_type bufferSize) { SANITY_CHECK(!IsInvalidHandle(handle) && buffer && bufferSize > 0);
tools::CUsartInfo* const info = &tools::usarts_[handle]; if (!kernel::ringb::IsEmpty(&info->rxRingBuffer_)) { return kernel::ringb::ReadBuffer(&info->rxRingBuffer_, buffer, min(bufferSize, kernel::ringb::Size(&info->rxRingBuffer_))); } return 0; } //--------------------------------------------------------------------------- void Write(const handle_type handle, const unsigned char data) { SANITY_CHECK(!IsInvalidHandle(handle));
tools::CUsartInfo* const info = &tools::usarts_[handle];
if (kernel::ringb::IsFull(&info->txRingBuffer_)) { tools::usartErrors_[handle] |= eTxBufferOverflow; return; } const bool isEnableInterrupt = kernel::ringb::IsEmpty(&info->txRingBuffer_); kernel::ringb::Write(&info->txRingBuffer_, data); if (isEnableInterrupt) { info->usart_->US_IER = AT91C_US_TXRDY; } } //--------------------------------------------------------------------------- void WriteBuffer(const handle_type handle, const unsigned char* const buffer, const size_type bufferSize) { SANITY_CHECK(!IsInvalidHandle(handle));
if (!bufferSize) { return; } tools::CUsartInfo* const info = &tools::usarts_[handle];
if (kernel::ringb::IsFull(&info->txRingBuffer_) || bufferSize > kernel::ringb::Capacity(&info->txRingBuffer_) - kernel::ringb::Size(&info->txRingBuffer_)) { tools::usartErrors_[handle] |= eTxBufferOverflow; return; } const bool isEnableInterrupt = kernel::ringb::IsEmpty(&info->txRingBuffer_); kernel::ringb::WriteBuffer(&info->txRingBuffer_, buffer, bufferSize); if (isEnableInterrupt) { info->usart_->US_IER = AT91C_US_TXRDY; }
} //--------------------------------------------------------------------------- void Flush(const handle_type handle) { SANITY_CHECK(!IsInvalidHandle(handle)); tools::CUsartInfo* const info = &tools::usarts_[handle]; info->usart_->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE; info->usart_->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA; } //--------------------------------------------------------------------------- void RFlush(const handle_type handle) { SANITY_CHECK(!IsInvalidHandle(handle)); tools::CUsartInfo* const info = &tools::usarts_[handle]; info->usart_->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE; info->usart_->US_CR = AT91C_US_RSTTX | AT91C_US_RSTSTA; } //--------------------------------------------------------------------------- void WFlush(const handle_type handle) { SANITY_CHECK(!IsInvalidHandle(handle)); tools::CUsartInfo* const info = &tools::usarts_[handle]; info->usart_->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE; info->usart_->US_CR = AT91C_US_RSTTX | AT91C_US_RSTSTA; } //--------------------------------------------------------------------------- void Close(handle_type* const handle) { SANITY_CHECK(!IsInvalidHandle(*handle)); tools::CUsartInfo* const info = &tools::usarts_[*handle]; info->usart_->US_CR = AT91C_US_RXDIS | AT91C_US_TXDIS; IRQ_DisableIT(info->id_); PMC_DisablePeripheral(info->id_); *handle = idInvalid; } //--------------------------------------------------------------------------- }
ring_buffer.h CODE #ifndef RING_BUFFER_H #define RING_BUFFER_H //-----------------------------------------------------------------------------
namespace kernel { namespace ringb { struct CRingBuffer { typedef unsigned short size_type; typedef unsigned char value_type;
size_type readOffset_; size_type writeOffset_; size_type shadowOffset_; value_type *data_; size_type lastDataIndex_; }; //----------------------------------------------------------------------------- const struct CRingBuffer Create(CRingBuffer::value_type* const data, CRingBuffer::size_type capacity);
void Init(CRingBuffer* const rb, CRingBuffer::value_type* const data, CRingBuffer::size_type capacity);
CRingBuffer::size_type Read(CRingBuffer* const rb, CRingBuffer::value_type& value);
CRingBuffer::size_type ReadBuffer(CRingBuffer* const rb, CRingBuffer::value_type* const buffer, CRingBuffer::size_type bufferSize);
CRingBuffer::size_type Write(CRingBuffer* const rb, CRingBuffer::value_type value);
CRingBuffer::size_type WriteBuffer(CRingBuffer* const rb, const CRingBuffer::value_type* const buffer, CRingBuffer::size_type bufferSize); void Clear(CRingBuffer* const rb); CRingBuffer::size_type Capacity(CRingBuffer* const rb);
CRingBuffer::size_type Size(CRingBuffer* const rb); bool IsEmpty(CRingBuffer* const rb);
bool IsFull(CRingBuffer* const rb); void InitShadowRead(CRingBuffer* const rb);
CRingBuffer::size_type ShadowRead(CRingBuffer* const rb, CRingBuffer::value_type& value);
CRingBuffer::size_type ShadowReadBuffer(CRingBuffer* const rb, CRingBuffer::value_type* const buffer, CRingBuffer::size_type bufferSize); void ApplyShadowRead(CRingBuffer* const rb); bool IsShadowEmpty(CRingBuffer* const rb); } }
#endif //---------------------------------------------------------------------------
ring_buffer.cpp CODE #include "ring_buffer.h" #include <utility/assert.h> #include <string.h> //---------------------------------------------------------------------------
namespace kernel { namespace ringb { namespace tools { static inline CRingBuffer::size_type IncOffset(CRingBuffer::size_type offset, CRingBuffer::size_type lastDataIndex) { return (offset < lastDataIndex) ? offset + 1 : 0; } //--------------------------------------------------------------------------- static inline bool IsEmpty(CRingBuffer* const rb, CRingBuffer::size_type& offset) { SANITY_CHECK(rb); return offset == rb->writeOffset_; } //---------------------------------------------------------------------------
static inline CRingBuffer::size_type Read(CRingBuffer* const rb, CRingBuffer::size_type& offset, CRingBuffer::value_type& value) { SANITY_CHECK(rb); if (IsEmpty(rb, offset)) { return 0; } value = rb->data_[offset]; offset = tools::IncOffset(offset, rb->lastDataIndex_); return 1; } //---------------------------------------------------------------------------
static inline CRingBuffer::size_type ReadBuffer(CRingBuffer* const rb, CRingBuffer::size_type& offset, CRingBuffer::value_type* const buffer, CRingBuffer::size_type bufferSize) { if (IsEmpty(rb, offset)) { return 0; } if (rb->writeOffset_ > offset) { const CRingBuffer::size_type rbSize = rb->writeOffset_ - offset; const CRingBuffer::size_type readCount = (bufferSize > rbSize) ? rbSize : bufferSize; memcpy(buffer, rb->data_ + offset, readCount); offset += readCount; return readCount; } const CRingBuffer::size_type toEndCount = Capacity(rb) - offset; if (bufferSize > toEndCount) { memcpy(buffer, rb->data_ + offset, toEndCount); bufferSize -= toEndCount; const CRingBuffer::size_type readCount = (bufferSize > rb->writeOffset_) ? rb->writeOffset_ : bufferSize; memcpy(buffer + toEndCount, rb->data_, readCount); offset = readCount; return toEndCount + readCount; } memcpy(buffer, rb->data_ + offset, bufferSize); offset += bufferSize; return bufferSize; } } //--------------------------------------------------------------------------- const struct CRingBuffer CreateRingBuffer(CRingBuffer::value_type* const data, CRingBuffer::size_type capacity) { SANITY_CHECK(data && capacity); struct CRingBuffer result = { 0, 0, 0, data, capacity - 1 }; return result; } //---------------------------------------------------------------------------
void Init(CRingBuffer* const rb, CRingBuffer::value_type* const data, CRingBuffer::size_type capacity) { SANITY_CHECK(rb && data && capacity); rb->readOffset_ = 0; rb->writeOffset_ = 0; rb->shadowOffset_ = 0; rb->data_ = data; rb->lastDataIndex_ = capacity - 1; } //--------------------------------------------------------------------------- CRingBuffer::size_type Read(CRingBuffer* const rb, CRingBuffer::value_type& value) { SANITY_CHECK(rb); return tools::Read(rb, rb->readOffset_, value); } //---------------------------------------------------------------------------
CRingBuffer::size_type ReadBuffer(CRingBuffer* const rb, CRingBuffer::value_type* const buffer, CRingBuffer::size_type bufferSize) { SANITY_CHECK(rb); return tools::ReadBuffer(rb, rb->readOffset_, buffer, bufferSize); } //---------------------------------------------------------------------------
CRingBuffer::size_type Write(CRingBuffer* const rb, CRingBuffer::value_type value) { SANITY_CHECK(rb); if (IsFull(rb)) { return 0; } rb->data_[rb->writeOffset_] = value; rb->writeOffset_ = tools::IncOffset(rb->writeOffset_, rb->lastDataIndex_); return 1; } //---------------------------------------------------------------------------
CRingBuffer::size_type WriteBuffer(CRingBuffer* const rb, const CRingBuffer::value_type* const buffer, CRingBuffer::size_type bufferSize) { SANITY_CHECK(rb && buffer && bufferSize); if (IsFull(rb)) { return 0; } if (rb->writeOffset_ < rb->readOffset_) { const CRingBuffer::size_type toReadCount(rb->readOffset_ - rb->writeOffset_); const CRingBuffer::size_type writeCount = (toReadCount > bufferSize) ? bufferSize : toReadCount; memcpy(rb->data_ + rb->writeOffset_, buffer, writeCount); rb->writeOffset_ += writeCount; return writeCount; } const CRingBuffer::size_type toEndCount = Capacity(rb) - rb->writeOffset_; if (bufferSize > toEndCount) { memcpy(rb->data_ + rb->writeOffset_, buffer, toEndCount); bufferSize -= toEndCount;
const CRingBuffer::size_type writeCount = (bufferSize > rb->readOffset_) ? rb->readOffset_ : bufferSize;
memcpy(rb->data_, buffer + toEndCount, writeCount); rb->writeOffset_ = writeCount; return toEndCount + writeCount; } memcpy(rb->data_ + rb->writeOffset_, buffer, bufferSize); rb->writeOffset_ += bufferSize; return bufferSize; } //--------------------------------------------------------------------------- void Clear(CRingBuffer* const rb) { SANITY_CHECK(rb); rb->writeOffset_ = rb->readOffset_; } //--------------------------------------------------------------------------- CRingBuffer::size_type Capacity(CRingBuffer* const rb) { SANITY_CHECK(rb); return rb->lastDataIndex_ + 1; } //---------------------------------------------------------------------------
CRingBuffer::size_type Size(CRingBuffer* const rb) { SANITY_CHECK(rb); return (rb->readOffset_ > rb->writeOffset_) ? Capacity(rb) - rb->readOffset_ + rb->writeOffset_ : rb->writeOffset_ - rb->readOffset_ ; } //--------------------------------------------------------------------------- bool IsEmpty(CRingBuffer* const rb) { return tools::IsEmpty(rb, rb->readOffset_); } //---------------------------------------------------------------------------
bool IsFull(CRingBuffer* const rb) { SANITY_CHECK(rb); int cc = tools::IncOffset(rb->writeOffset_, rb->lastDataIndex_); return tools::IncOffset(rb->writeOffset_, rb->lastDataIndex_) == rb->readOffset_; } //--------------------------------------------------------------------------- void InitShadowRead(CRingBuffer* const rb) { SANITY_CHECK(rb); rb->shadowOffset_ = rb->readOffset_; } //---------------------------------------------------------------------------
CRingBuffer::size_type ShadowRead(CRingBuffer* const rb, CRingBuffer::value_type& value) { SANITY_CHECK(rb); return tools::Read(rb, rb->shadowOffset_, value); } //---------------------------------------------------------------------------
CRingBuffer::size_type ShadowReadBuffer(CRingBuffer* const rb, CRingBuffer::value_type* const buffer, CRingBuffer::size_type bufferSize) { SANITY_CHECK(rb); return tools::ReadBuffer(rb, rb->shadowOffset_, buffer, bufferSize); } //--------------------------------------------------------------------------- void ApplyShadowRead(CRingBuffer* const rb) { SANITY_CHECK(rb); rb->readOffset_ = rb->shadowOffset_; } //---------------------------------------------------------------------------
bool IsShadowEmpty(CRingBuffer* const rb) { return tools::IsEmpty(rb, rb->shadowOffset_); } //--------------------------------------------------------------------------- } }
пример использования: CODE int main(void) { usart::Init(); usart::handle_type usartHandle = usart::Open(usart::id0, AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT | AT91C_US_CHMODE_NORMAL, 115200);
unsigned char data(0); unsigned char data1(0); unsigned char wbuf[10] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA }; unsigned char rbuf[10] = { 0 }; int rCount = 0; while (1) { // usart::Write(usartHandle, 0xFF); // usart::WaitForData(usartHandle); // usart::Read(usartHandle, &data); rCount = 0; for (unsigned int i(0); i < 10; ++i) rbuf[i] = 0; usart::WriteBuffer(usartHandle, wbuf, 10); if (usart::IsError(usartHandle)) { usart::Flush(usartHandle); } usart::WaitForData(usartHandle); if (usart::IsError(usartHandle)) { usart::Flush(usartHandle); } while (rCount < 10) { usart::WaitForData(usartHandle); if (usart::IsError(usartHandle)) { usart::Flush(usartHandle); } rCount+= usart::ReadBuffer(usartHandle, rbuf + rCount, 10 - rCount); if (usart::IsError(usartHandle)) { usart::Flush(usartHandle); } } } }
|
|
|
|
|
 |
Ответов
|
Oct 10 2012, 07:08
|
Группа: Участник
Сообщений: 12
Регистрация: 17-04-12
Пользователь №: 71 418

|
Цитата(aaarrr @ Oct 9 2012, 18:06)  Учитывая отсутствие буферизации в атмеловских UART'ах, драйвер без PDC имеет очень ограниченную область применения. Здравствуйте. Спасибо за ответ. Наверное, Вы правы. В случае использования PDC мне непонятны следующие... Я хочу передать буфер через uart. В атмеловском примере это выглядит так: CODE unsigned char USART_WriteBuffer( AT91S_USART *usart, void *buffer, unsigned int size) { // Check if the first PDC bank is free if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
usart->US_TPR = (unsigned int) buffer; usart->US_TCR = size; usart->US_PTCR = AT91C_PDC_TXTEN;
return 1; } // Check if the second PDC bank is free else if (usart->US_TNCR == 0) {
usart->US_TNPR = (unsigned int) buffer; usart->US_TNCR = size;
return 1; } else {
return 0; } } Неудобно здесь то, имхо, что функция сразу возвращает управление, т.е. если я передаю буфер размером в сто байт и скорость uart относительно маленькая, то в случае, если, после возвращения из функции я поменяю, скажем, 85 байт, то этот 85-ый байт (допустим, он еще не успел передаться) поменяется и в отправляемом сейчас буфере, что не здорово. Предположим, я в функции write буду ждать, пока не окончится передача буфера и только потом верну управление. В этом случае получается не задействован регистр-указатель следующей передачи US_TNPR, что, наверное, не хорошо. Еще вариант, что я копирую переданный буфер в свой и передаю pdc уже свой буфер, тогда pdc используется в "полном объеме" но тратится время на работу с промежуточным буфером.... Цитата(aaarrr @ Oct 9 2012, 18:06)  И зачем "тушить свет" при Parity или Framing error? Если происходит Parity или Framing error у меня почему-то начинает беспрерывно вызываться прерывание по этой ошибке. Как указать, что эта ошибка обработана, я не нашел. Если Вы мне подскажете, я буду Вам благодарен...
|
|
|
|
|
Oct 10 2012, 07:50
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Parkan @ Oct 10 2012, 11:08)  Еще вариант, что я копирую переданный буфер в свой и передаю pdc уже свой буфер, тогда pdc используется в "полном объеме" но тратится время на работу с промежуточным буфером.... Совершенно верно, использование PDC ведет к разрастанию буферизации. В случае UART это не очень критично, так как периферия по определению медленная. Зато у процессора появляется возможность "отвлечься" на некоторое время. Цитата(Parkan @ Oct 10 2012, 11:08)  Если происходит Parity или Framing error у меня почему-то начинает беспрерывно вызываться прерывание по этой ошибке. Как указать, что эта ошибка обработана, я не нашел. Если Вы мне подскажете, я буду Вам благодарен... Насколько я помню, ошибки сбрасываются по RSTSTA. Другое дело, что информативность того же Framing error в большинстве случаев близка к нулю - приложению эта информация может пригодиться разве что для статистики.
|
|
|
|
Сообщений в этой теме
Parkan ARM 7 (at91sam7x) Драйвер для UART Oct 9 2012, 12:16  RabidRabbit Цитата(Parkan @ Oct 10 2012, 11:08) Если ... Oct 10 2012, 07:50 Parkan Еще вопрос по PDC
В каждом канале PDC есть:
-регис... Oct 10 2012, 07:51 RabidRabbit Цитата(Parkan @ Oct 10 2012, 11:51) Тепер... Oct 10 2012, 07:56 aaarrr Цитата(Parkan @ Oct 10 2012, 11:51) Предп... Oct 10 2012, 07:56  Parkan Цитата(aaarrr @ Oct 10 2012, 11:56) Слома... Oct 10 2012, 09:08 Parkan И еще вопрос. Данные в uart можно передавать испол... Oct 10 2012, 08:06 RabidRabbit Цитата(Parkan @ Oct 10 2012, 12:06) И еще... Oct 10 2012, 08:12  Parkan Цитата(RabidRabbit @ Oct 10 2012, 12:12) ... Oct 10 2012, 08:44   RabidRabbit Цитата(Parkan @ Oct 10 2012, 12:44) Посмо... Oct 10 2012, 08:59    Parkan Цитата(RabidRabbit @ Oct 10 2012, 12:59) ... Oct 10 2012, 09:29     aaarrr Цитата(Parkan @ Oct 10 2012, 13:29) Разве... Oct 10 2012, 09:34     RabidRabbit Цитата(Parkan @ Oct 10 2012, 13:29) Ага, ... Oct 10 2012, 09:40 aaarrr Алгоритм передачи очень простой:
1. При появлении ... Oct 10 2012, 09:14 Parkan RabidRabbit, aaarrr спасибо Oct 10 2012, 09:50 Parkan RE: ARM 7 (at91sam7x) Драйвер для UART Oct 12 2012, 13:28 aaarrr 1. Сделайте буферы большого размера и используйте ... Oct 12 2012, 14:34 Parkan Цитата(aaarrr @ Oct 12 2012, 18:34) 1. Сд... Oct 13 2012, 13:01  aaarrr Цитата(Parkan @ Oct 13 2012, 17:01) 2)Я н... Oct 13 2012, 14:13
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|