📄 halpxa27xserialp.nc
字号:
/* $Id: HalPXA27xSerialP.nc,v 1.5 2008/06/11 00:42:13 razvanm Exp $ */
/*
* Copyright (c) 2005 Arched Rock Corporation
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 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.
*
* Neither the name of the Arched Rock Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE ARCHED
* ROCK OR ITS 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.
*/
/*
* Intel Open Source License
*
* Copyright (c) 2002 Intel Corporation
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE INTEL OR ITS
* 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.
*
*
*/
/**
* Implements the UartByte, UartStream and HalPXA27xSerialPacket interface
* for a PXA27x UART.
*
*
* @param defaultRate Default baud rate for the serial port.
*
*
* @author Phil Buonadonna
*/
#include "pxa27x_serial.h"
generic module HalPXA27xSerialP(uint32_t defaultRate)
{
provides {
interface Init;
interface StdControl;
interface UartByte;
interface UartStream;
interface HalPXA27xSerialPacket;
interface HalPXA27xSerialCntl;
}
uses {
interface Init as UARTInit;
interface HplPXA27xUART as UART;
interface HplPXA27xDMAChnl as RxDMA;
interface HplPXA27xDMAChnl as TxDMA;
interface HplPXA27xDMAInfo as UARTRxDMAInfo;
interface HplPXA27xDMAInfo as UARTTxDMAInfo;
}
}
implementation
{
uint8_t *txCurrentBuf, *rxCurrentBuf;
uint32_t txCurrentLen, rxCurrentLen, rxCurrentIdx;
uint32_t gulFCRShadow;
bool gbUsingUartStreamSendIF = FALSE;
bool gbUsingUartStreamRcvIF = FALSE;
bool gbRcvByteEvtEnabled = TRUE;
command error_t Init.init() {
error_t error = SUCCESS;
atomic {
call UARTInit.init();
txCurrentBuf = rxCurrentBuf = NULL;
gbUsingUartStreamSendIF = FALSE;
gbUsingUartStreamRcvIF = FALSE;
gbRcvByteEvtEnabled = TRUE;
gulFCRShadow = (FCR_TRFIFOE | FCR_ITL(0)); // FIFO Mode, 1 byte Rx threshold
}
call TxDMA.setMap(call UARTTxDMAInfo.getMapIndex());
call RxDMA.setMap(call UARTRxDMAInfo.getMapIndex());
call TxDMA.setDALGNbit(TRUE);
call RxDMA.setDALGNbit(TRUE);
error = call HalPXA27xSerialCntl.configPort(defaultRate,8,NONE,1,FALSE);
atomic {call UART.setFCR(gulFCRShadow);}
return error;
}
command error_t StdControl.start() {
atomic {
call UART.setIER(IER_UUE | IER_RAVIE);
}
return SUCCESS;
}
command error_t StdControl.stop() {
atomic {
call UART.setIER(0);
}
return SUCCESS;
}
async command error_t UartByte.send(uint8_t data) {
atomic call UART.setTHR(data);
while ((call UART.getLSR() & LSR_TEMT) == 0);
return SUCCESS;
}
async command error_t UartByte.receive( uint8_t *data, uint8_t timeout) {
error_t error = FAIL;
uint8_t t;
for (t = 0; t < timeout; t++) {
if (call UART.getLSR() & LSR_DR) {
*data = call UART.getRBR();
error = SUCCESS;
break;
}
}
return error;
}
async command error_t UartStream.send( uint8_t* buf, uint16_t len ) {
error_t error;
atomic gbUsingUartStreamSendIF = TRUE;
error = call HalPXA27xSerialPacket.send(buf,len);
if (error) {
atomic gbUsingUartStreamSendIF = FALSE;
}
return error;
}
async command error_t UartStream.enableReceiveInterrupt() {
error_t error = SUCCESS;
atomic {
if (rxCurrentBuf == NULL) {
call UART.setIER(call UART.getIER() | IER_RAVIE);
}
gbRcvByteEvtEnabled = TRUE;
}
return SUCCESS;
}
async command error_t UartStream.disableReceiveInterrupt() {
atomic {
// Check to make sure a short stream/packet call isn't in progress
if ((rxCurrentBuf == NULL) || (rxCurrentLen >= 8)) {
call UART.setIER(call UART.getIER() & ~IER_RAVIE);
}
gbRcvByteEvtEnabled = FALSE;
}
return SUCCESS;
}
async command error_t UartStream.receive( uint8_t* buf, uint16_t len ) {
error_t error;
atomic gbUsingUartStreamRcvIF = TRUE;
error = call HalPXA27xSerialPacket.receive(buf,len,0);
if (error) {
atomic gbUsingUartStreamRcvIF = FALSE;
}
return error;
}
async command error_t HalPXA27xSerialPacket.send(uint8_t *buf, uint16_t len) {
uint32_t txAddr;
uint32_t DMAFlags;
error_t error = SUCCESS;
atomic {
if (txCurrentBuf == NULL) {
txCurrentBuf = buf;
txCurrentLen = len;
}
else {
error = FAIL;
}
}
if (error)
return error;
if (len < 8) {
uint16_t i;
// Use PIO. Invariant: FIFO is empty
atomic {
gulFCRShadow |= FCR_TIL;
call UART.setFCR(gulFCRShadow);
}
for (i = 0;i < len;i++) {
call UART.setTHR(buf[i]);
}
atomic call UART.setIER(call UART.getIER() | IER_TIE);
}
else {
// Use DMA
DMAFlags = (DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | DCMD_ENDIRQEN
| DCMD_LEN(len) );
txAddr = (uint32_t) buf;
DMAFlags |= DCMD_INCSRCADDR;
call TxDMA.setDCSR(DCSR_NODESCFETCH);
call TxDMA.setDSADR(txAddr);
call TxDMA.setDTADR(call UARTTxDMAInfo.getAddr());
call TxDMA.setDCMD(DMAFlags);
atomic {
call UART.setIER(call UART.getIER() | IER_DMAE);
}
call TxDMA.setDCSR(DCSR_RUN | DCSR_NODESCFETCH);
}
return error;
}
async command error_t HalPXA27xSerialPacket.receive(uint8_t *buf, uint16_t len,
uint16_t timeout) {
uint32_t rxAddr;
uint32_t DMAFlags;
error_t error = SUCCESS;
atomic {
if (rxCurrentBuf == NULL) {
rxCurrentBuf = buf;
rxCurrentLen = len;
rxCurrentIdx = 0;
}
else {
error = FAIL;
}
}
if (error)
return error;
if (len < 8) {
// Use PIO. Invariant: FIFO is empty
atomic {
gulFCRShadow = ((gulFCRShadow & ~(FCR_ITL(3))) | FCR_ITL(0));
call UART.setFCR(gulFCRShadow);
call UART.setIER(call UART.getIER() | IER_RAVIE);
}
}
else {
// Use DMA
DMAFlags = (DCMD_FLOWSRC | DCMD_BURST8 | DCMD_WIDTH1 | DCMD_ENDIRQEN
| DCMD_LEN(len) );
rxAddr = (uint32_t) buf;
DMAFlags |= DCMD_INCTRGADDR;
call RxDMA.setDCSR(DCSR_NODESCFETCH);
call RxDMA.setDTADR(rxAddr);
call RxDMA.setDSADR(call UARTRxDMAInfo.getAddr());
call RxDMA.setDCMD(DMAFlags);
atomic {
gulFCRShadow = ((gulFCRShadow & ~(FCR_ITL(3))) | FCR_ITL(1));
call UART.setFCR(gulFCRShadow);
call UART.setIER((call UART.getIER() & ~IER_RAVIE) | IER_DMAE);
}
call RxDMA.setDCSR(DCSR_RUN | DCSR_NODESCFETCH);
}
return error;
}
void DispatchStreamRcvSignal() {
uint8_t *pBuf = rxCurrentBuf;
uint16_t len = rxCurrentLen;
rxCurrentBuf = NULL;
if (gbUsingUartStreamRcvIF) {
gbUsingUartStreamRcvIF = FALSE;
signal UartStream.receiveDone(pBuf, len, SUCCESS);
}
else {
pBuf = signal HalPXA27xSerialPacket.receiveDone(pBuf, len, SUCCESS);
if (pBuf) {
call HalPXA27xSerialPacket.receive(pBuf,len,0);
}
}
return;
}
void DispatchStreamSendSignal() {
uint8_t *pBuf = txCurrentBuf;
uint16_t len = txCurrentLen;
txCurrentBuf = NULL;
if (gbUsingUartStreamSendIF) {
gbUsingUartStreamSendIF = FALSE;
signal UartStream.sendDone(pBuf, len, SUCCESS);
}
else {
pBuf = signal HalPXA27xSerialPacket.sendDone(pBuf, len, SUCCESS);
if (pBuf) {
call HalPXA27xSerialPacket.send(pBuf,len);
}
}
return;
}
async event void RxDMA.interruptDMA() {
call RxDMA.setDCMD(0);
call RxDMA.setDCSR(DCSR_EORINT | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERRINTR);
DispatchStreamRcvSignal();
if (gbRcvByteEvtEnabled)
call UART.setIER(call UART.getIER() | IER_RAVIE);
return;
}
async event void TxDMA.interruptDMA() {
call TxDMA.setDCMD(0);
call TxDMA.setDCSR(DCSR_EORINT | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERRINTR);
DispatchStreamSendSignal();
return;
}
async command error_t HalPXA27xSerialCntl.configPort(uint32_t baudrate,
uint8_t databits,
uart_parity_t parity,
uint8_t stopbits,
bool flow_cntl) {
uint32_t uiDivisor;
uint32_t valLCR = 0;
uint32_t valMCR = MCR_OUT2;
uiDivisor = 921600/baudrate;
// Check for invalid baud rate divisor value.
// XXX - Eventually could use '0' to imply auto rate detection
if ((uiDivisor & 0xFFFF0000) || (uiDivisor == 0)) {
return EINVAL;
}
if ((databits > 8 || databits < 5)) {
return EINVAL;
}
valLCR |= LCR_WLS((databits-5));
switch (parity) {
case EVEN:
valLCR |= LCR_EPS;
// Fall through to enable
case ODD:
valLCR |= LCR_PEN;
break;
case NONE:
break;
default:
return EINVAL;
break;
}
if ((stopbits > 2) || (stopbits < 1)) {
return EINVAL;
}
else if (stopbits == 2) {
valLCR |= LCR_STB;
}
if (flow_cntl) {
valMCR |= MCR_AFE;
}
atomic {
call UART.setDLL((uiDivisor & 0xFF));
call UART.setDLH(((uiDivisor >> 8) & 0xFF));
call UART.setLCR(valLCR);
call UART.setMCR(valMCR);
}
return SUCCESS;
}
async command error_t HalPXA27xSerialCntl.flushPort() {
atomic {
call UART.setFCR(gulFCRShadow | FCR_RESETTF | FCR_RESETRF);
}
return SUCCESS;
}
async event void UART.interruptUART() {
uint8_t error, intSource;
uint8_t ucByte;
intSource = call UART.getIIR();
intSource &= IIR_IID_MASK;
intSource = intSource >> 1;
switch (intSource) {
case 0: // MODEM STATUS
break;
case 1: // TRANSMIT FIFO
call UART.setIER(call UART.getIER() & ~IER_TIE);
DispatchStreamSendSignal();
break;
case 2: // RECEIVE FIFO data available
while (call UART.getLSR() & LSR_DR) {
ucByte = call UART.getRBR();
if (rxCurrentBuf != NULL) {
rxCurrentBuf[rxCurrentIdx] = ucByte;
rxCurrentIdx++;
if (rxCurrentIdx >= rxCurrentLen)
DispatchStreamRcvSignal();
}
else if (gbRcvByteEvtEnabled) {
signal UartStream.receivedByte(ucByte);
}
}
break;
case 3: // ERROR
error = call UART.getLSR();
break;
default:
break;
}
return;
}
default async event void UartStream.sendDone( uint8_t* buf, uint16_t len, error_t error ) {
return;
}
default async event void UartStream.receivedByte(uint8_t data) {
return;
}
default async event void UartStream.receiveDone( uint8_t* buf, uint16_t len, error_t error ) {
return;
}
default async event uint8_t* HalPXA27xSerialPacket.sendDone(uint8_t *buf,
uint16_t len,
uart_status_t status) {
return NULL;
}
default async event uint8_t* HalPXA27xSerialPacket.receiveDone(uint8_t *buf,
uint16_t len,
uart_status_t status) {
return NULL;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -