| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448 |
- /*
- * Copyright (C) 2010 by Ulrich Prinz (uprinz2@netscape.net)
- * Copyright (C) 2010 by Rittal GmbH & Co. KG. All rights reserved.
- *
- * 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 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
- * COPYRIGHT OWNER 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/
- */
- /*
- * \verbatim
- * $Id: stm32_usart.c 5680 2014-04-30 08:20:00Z u_bonnes $
- * \endverbatim
- */
- #include <cfg/clock.h>
- #include <sys/atom.h>
- #include <sys/event.h>
- #include <sys/timer.h>
- #include <dev/irqreg.h>
- #include <dev/usart.h>
- #include <arch/cm3/stm/stm32_usart.h>
- #include <arch/cm3/stm/stm32_dma.h>
- #if defined(MCU_STM32F0) || defined(MCU_STM32F3)
- #define USARTN_RDR (USARTn->RDR)
- #define USARTN_TDR (USARTn->TDR)
- #define USARTN_ISR (USARTn->ISR)
- #define CLEAR_ERRS() USARTn->ICR = USART_ICR_PECF|USART_ICR_FECF|USART_ICR_NCF|USART_ICR_ORECF|\
- USART_ICR_IDLECF|USART_ICR_TCCF|USART_ICR_LBDCF|USART_ICR_CTSCF|USART_ICR_RTOCF|\
- USART_ICR_EOBCF|USART_ICR_CMCF|USART_ICR_WUCF
- #define TXE_SET CM3BBGET(USARTnBase, USART_TypeDef, ISR, _BI32(USART_ISR_TXE))
- #define CLEAR_TC() CM3BBSET(USARTnBase, USART_TypeDef, ICR, _BI32(USART_ICR_TCCF))
- #else
- #define USARTN_RDR (USARTn->DR)
- #define USARTN_TDR (USARTn->DR)
- #define USARTN_ISR (USARTn->SR)
- #define CLEAR_ERRS() (USARTn->SR)
- #define TXE_SET CM3BBGET(USARTnBase, USART_TypeDef, SR, _BI32(USART_SR_TXE))
- #define CLEAR_TC() CM3BBCLR(USARTnBase, USART_TypeDef, SR, _BI32(USART_SR_TC))
- #endif
- #if !defined(USART_ISR_ORE)
- #define USART_ISR_ORE USART_SR_ORE
- #endif
- #if !defined(USART_ISR_NE)
- #define USART_ISR_NE USART_SR_NE
- #endif
- #if !defined(USART_ISR_FE)
- #define USART_ISR_FE USART_SR_FE
- #endif
- #if !defined(USART_ISR_PE)
- #define USART_ISR_PE USART_SR_PE
- #endif
- #if !defined(USART_ISR_TC)
- #define USART_ISR_TC USART_SR_TC
- #endif
- #if !defined(USART_ISR_RXNE)
- #define USART_ISR_RXNE USART_SR_RXNE
- #endif
- #if !defined(USART_ISR_TXE)
- #define USART_ISR_TXE USART_SR_TXE
- #endif
- #if defined(UART_DMA_TXCHANNEL) || defined(UART_DMA_RXCHANNEL)
- #include <arch/cm3/stm/stm32_dma.h>
- #endif
- /* Some function renaming for IRQ handling on uarts
- * that do not have a separate IRQ instance but a
- * merged one with others like DBU on SYS-IRQ or
- * external uarts on GPIO-IRQs
- */
- #define NutUartIrqEnable() USARTn->CR1 |= (USART_CR1_TXEIE | USART_CR1_RXNEIE)
- #define NutUartIrqDisable() USARTn->CR1 &= ~(USART_CR1_TXEIE | USART_CR1_RXNEIE)
- /*!
- * \addtogroup xgNutArchArmStm32Us
- */
- /*@{*/
- #if defined(UART_XONXOFF_CONTROL)
- /* \brief ASCII code for software flow control, starts transmitter. */
- #define ASCII_XON 0x11
- /* \brief ASCII code for software flow control, stops transmitter. */
- #define ASCII_XOFF 0x13
- /* \brief XON transmit pending flag. */
- #define XON_PENDING 0x10
- /* \brief XOFF transmit pending flag. */
- #define XOFF_PENDING 0x20
- /* \brief XOFF sent flag. */
- #define XOFF_SENT 0x40
- /* \brief XOFF received flag. */
- #define XOFF_RCVD 0x80
- #endif
- /* USART default speed if not preset by nutconfig */
- #ifndef USART_INIT_BAUTRATE
- #define USART_INIT_BAUTRATE USART_INITSPEED
- #endif
- /*!
- * \brief Receiver error flags.
- */
- static uint16_t rx_errors;
- /*!
- * \brief Transmit address frame, if not zero.
- */
- static uint_fast8_t tx_aframe;
- #if defined(US_MODE_HWHANDSHAKE)
- /*!
- * \brief Enables RTS control if not equal zero.
- *
- * This variable exists only if the hardware configuration defines a
- * port bit to control the RTS signal.
- */
- static uint_fast8_t rts_control;
- /*!
- * \brief Enables CTS sense if not equal zero.
- *
- * This variable exists only if the hardware configuration defines a
- * port bit to sense the CTS signal.
- */
- // TODO: CTS Handling
- // static uint_fast8_t cts_sense;
- #endif
- #if defined(UART_XONXOFF_CONTROL)
- /*!
- * \brief Handles local software flow control.
- *
- * This variable exists only if the hardware configuration defines a
- * software flow control support.
- */
- static uint_fast8_t flow_control;
- #endif
- /*!
- * \brief Handles local half-duplex flow control.
- *
- */
- static uint_fast8_t hdpx_control;
- #ifdef USART_485_CTRL
- /*!
- * \brief Handles local echo for RS485.
- *
- */
- static uint_fast8_t rs485_control;
- #endif /* #ifdef USART_485_CTRL */
- #if defined(DE_GPIO_PORT) && defined(DE_GPIO_PIN)
- /*!
- * \brief Definition of RS485 DE switching functions.
- */
- #ifdef USART_4485DE_INV
- #define Rs485DE_L() GpioPinSetHigh(DE_GPIO_PORT, DE_GPIO_PIN)
- #define Rs485DE_H() GpioPinSetLow(DE_GPIO_PORT, DE_GPIO_PIN)
- #else
- #define Rs485DE_L() GpioPinSetLow(DE_GPIO_PORT, DE_GPIO_PIN)
- #define Rs485DE_H() GpioPinSetHigh(DE_GPIO_PORT, DE_GPIO_PIN)
- #endif
- #else
- #define Rs485DE_L()
- #define Rs485DE_H()
- #endif
- #if defined(NRE_GPIO_PORT) && defined(NRE_GPIO_PIN)
- /*!
- * \brief Definition of RS485 NRE switching functions.
- */
- // TODO: Figure out fastest way for switching signals
- //#define Rs485NRE_L() NRE_GPIO_BASE->BRR=_BV(NRE_GPIO_PIN)
- //#define Rs485NRE_H() NRE_GPIO_BASE->BSRR=_BV(NRE_GPIO_PIN)
- #ifdef USART_4485RE_INV
- #define Rs485NRE_L() GpioPinSetHigh(NRE_GPIO_PORT, NRE_GPIO_PIN)
- #define Rs485NRE_H() if( rs485_control == 0) \
- GpioPinSetLow(NRE_GPIO_PORT, NRE_GPIO_PIN)
- #else
- #define Rs485NRE_L() GpioPinSetLow(NRE_GPIO_PORT, NRE_GPIO_PIN)
- #define Rs485NRE_H() if( rs485_control == 0) \
- GpioPinSetHigh(NRE_GPIO_PORT, NRE_GPIO_PIN)
- #endif
- #else
- #define Rs485NRE_L()
- #define Rs485NRE_H()
- #endif
- #if defined(UART_DMA_TXCHANNEL) || defined(UART_DMA_RXCHANNEL)
- /*!
- * \brief Handles local DMA block read/write control.
- *
- */
- static uint_fast8_t block_control;
- #define BC_RD_EN 0x01
- #define BC_WR_EN 0x02
- #endif
- #if 0
- #ifdef UART_DMA_TXCHANNEL
- static void Stm32UsartDmaTxIrq(void* arg)
- {
- NutEventPost(arg);
- }
- #endif
- #ifdef UART_DMA_RXCHANNEL
- static void Stm32UsartDmaRxIrq(void* arg)
- {
- NutEventPost(arg);
- }
- #endif
- #endif
- /*
- * \brief USARTn transmitter ready interrupt handler.
- *
- * \param rbf Pointer to the transmitter ring buffer.
- */
- static void Stm32UsartTxReady(RINGBUF * rbf)
- {
- register uint8_t *cp = rbf->rbf_tail;
- #ifdef UART_DMA_TXCHANNEL
- if (block_control & BC_WR_EN) {
- /* Disable TX-Interrupt */
- CM3BBCLR(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TXEIE));
- /* Setup Transfer */
- DMA_Setup(UART_DMA_TXCHANNEL, UART_DR_PTR, rbf->rbf_blockptr, rbf->rbf_blockcnt,
- DMA_MINC);
- /* Enable TxComplete Interrupt */
- CM3BBSET(USARTnBase, USART_TypeDef, CR3, _BI32(USART_CR3_DMAT));
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TCIE));
- /* Get DMA running */
- DMA_Enable(UART_DMA_TXCHANNEL);
- /* Now wait for the DMA to finish */
- return;
- }
- #endif
- #if defined(UART_XONXOFF_CONTROL)
- /*
- * Process pending software flow controls first.
- */
- if (flow_control & (XON_PENDING | XOFF_PENDING)) {
- if (flow_control & XON_PENDING) {
- USARTN_TDR_=ASCII_XOFF;
- flow_control |= XOFF_SENT;
- } else {
- USARTN_TDR=ASCII_XON;
- flow_control &= ~XOFF_SENT;
- }
- flow_control &= ~(XON_PENDING | XOFF_PENDING);
- return;
- }
- if (flow_control & XOFF_RCVD) {
- /*
- * If XOFF has been received, we disable the transmit interrupts
- * and return without sending anything.
- */
- CM3BBCLR(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TXEIE));
- CLEAR_ERRS();
- return;
- }
- #endif
- /*
- * Check if we have more bytes to transmit.
- */
- if (rbf->rbf_cnt) {
- /*
- * If CTS has been disabled, we disable the transmit interrupts,
- * enable CTS interrupts and return without sending anything.
- */
- // TODO: CTS handling in here
- /* Start transmission of the next character. */
- USARTN_TDR=*cp;
- /* Decrement the number of available bytes in the buffer. */
- rbf->rbf_cnt--;
- /* Wrap around the buffer pointer if we reached its end. */
- if (++cp == rbf->rbf_last) {
- cp = rbf->rbf_start;
- }
- rbf->rbf_tail = cp;
- /* Send an event if we reached the low watermark. */
- if (!hdpx_control && (rbf->rbf_cnt == rbf->rbf_lwm)) {
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
- }
- }
- if ( rbf->rbf_cnt==0) {
- /*
- * Nothing left to transmit:
- */
- /* Enable transmit complete interrupt */
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TCIE));
- /* Disable transmit interrupts. */
- CM3BBCLR(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TXEIE));
- if( !hdpx_control) {
- /* if half-duplex post the waiting thread after all bits are out.
- * Otherwise he might read back his own echo */
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
- }
- }
- }
- /*
- * \brief USARTn receiver ready interrupt handler.
- *
- *
- * \param rbf Pointer to the receiver ring buffer.
- */
- static void Stm32UsartRxReady(RINGBUF * rbf)
- {
- register size_t cnt;
- register uint8_t ch;
- #ifdef UART_DMA_RXCHANNEL
- if (block_control & BC_RD_EN) {
- /* Disable TX-Interrupt */
- CM3BBCLR(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_RXNEIE));
- /* Setup Transfer */
- DMA_Setup(UART_DMA_RXCHANNEL, rbf->rbf_blockptr, UART_DR_PTR, rbf->rbf_blockcnt,
- DMA_MINC);
- /* Enable TxComplete Interrupt */
- CM3BBSET(USARTnBase, USART_TypeDef, CR3, _BI32(USART_CR3_DMAR));
- /* Get DMA running */
- DMA_Enable(UART_DMA_RXCHANNEL);
- /* Now wait for the DMA to finish */
- return;
- }
- #endif
- /*
- * We read the received character as early as possible to avoid overflows
- * caused by interrupt latency.
- */
- ch = USARTN_RDR;
- /* Collect receiver errors. */
- rx_errors |= USARTN_ISR & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE);
- #if defined(UART_XONXOFF_CONTROL)
- /*
- * Handle software handshake. We have to do this before checking the
- * buffer, because flow control must work in write-only mode, where
- * there is no receive buffer.
- */
- if (flow_control) {
- /* XOFF character disables transmit interrupts. */
- if (ch == ASCII_XOFF) {
- CM3BBCLR(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TE));
- flow_control |= XOFF_RCVD;
- return;
- }
- /* XON enables transmit interrupts. */
- else if (ch == ASCII_XON) {
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TE));
- flow_control &= ~XOFF_RCVD;
- return;
- }
- }
- #endif
- /*
- * Check buffer overflow.
- */
- cnt = rbf->rbf_cnt;
- if (cnt >= rbf->rbf_siz) {
- rx_errors |= USART_ISR_ORE;
- return;
- }
- /* Wake up waiting threads if this is the first byte in the buffer. */
- if (cnt++ == 0){
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_READ);
- }
- #if defined(UART_XONXOFF_CONTROL)
- /*
- * Check the high watermark for software handshake. If the number of
- * buffered bytes is equal or above this mark, then send XOFF.
- */
- else if (flow_control) {
- if(cnt >= rbf->rbf_hwm) {
- if((flow_control & XOFF_SENT) == 0) {
- if (CM3BBGET(USARTnBase, USART_TypeDef, SR, _BI32(USART_CR1_TE))) {
- USARTN_TDR= ASCII_XOFF;
- flow_control |= XOFF_SENT;
- flow_control &= ~XOFF_PENDING;
- } else {
- flow_control |= XOFF_PENDING;
- }
- }
- }
- }
- #endif
- #ifdef US_MODE_HWHANDSHAKE
- /*
- * Check the high watermark for hardware handshake. If the number of
- * buffered bytes is above this mark, then disable RTS.
- */
- else if (rts_control && cnt >= rbf->rbf_hwm) {
- CM3BBSET(USARTnBase, USART_TypeDef, CR3, _BI32(USART_CR3_RTSE));
- }
- #endif
- /*
- * Store the character and increment and the ring buffer pointer.
- */
- *rbf->rbf_head++ = ch;
- if (rbf->rbf_head == rbf->rbf_last) {
- rbf->rbf_head = rbf->rbf_start;
- }
- /* Update the ring buffer counter. */
- rbf->rbf_cnt = cnt;
- }
- /*
- * \brief USARTn transmitter empty interrupt handler.
- *
- * Used with half duplex communication to switch from tranmit to receive
- * mode after the last character has been transmitted.
- *
- * This routine exists only if the hardware configuration defines
- * RS485 control.
- *
- * \param arg Pointer to the transmitter ring buffer.
- */
- static void Stm32UsartTxComplete(RINGBUF * rbf)
- {
- /*
- * Check if half duplex mode has been enabled and if all characters
- * had been sent out.
- */
- #ifdef UART_DMA_TXCHANNEL
- if (block_control & BC_WR_EN) {
- /* Clear TX and TX-Complete interrupt */
- USARTn->CR1 &= ~(USART_CR1_TCIE|USART_CR1_TXEIE);
- /* Disable DMA transfer */
- CM3BBCLR(USARTnBase, USART_TypeDef, CR3, _BI32(USART_CR3_DMAT));
- if( hdpx_control) {
- /* In case of half-duplex, enable receiver again */
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_RE));
- }
- /* Reset Counter */
- rbf->rbf_blockcnt = 0;
- rbf->rbf_cnt = 0;
- /* Switch to receiver mode. */
- Rs485DE_L(); /* Disable Sender */
- Rs485NRE_L(); /* Enable Receiver */
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
- return;
- }
- #endif
- if( rbf->rbf_cnt == 0) {
- /* Clear TX and TX-Complete interrupt */
- USARTn->CR1 &= ~(USART_CR1_TCIE|USART_CR1_TXEIE);
- /* Switch to receiver mode. */
- Rs485DE_L(); /* Disable Sender */
- Rs485NRE_L(); /* Enable Receiver */
- /* Clear pending TX-Complete Status */
- CLEAR_TC();
- if( hdpx_control) {
- /* In case of half-duplex, enable receiver again */
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_RE));
- }
- /* Send an event to inform the upper level. */
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
- }
- }
- /*!
- * \brief USART interrupt handler.
- *
- * \param arg Pointer to the device specific control block.
- */
- static void Stm32UsartInterrupt(void *arg)
- {
- USARTDCB *dcb = (USARTDCB *) arg;
- uint32_t csr = USARTN_ISR;
- /* Test for byte received */
- if (csr & USART_ISR_RXNE) {
- Stm32UsartRxReady(&dcb->dcb_rx_rbf);
- }
- /* Test for next byte can be transmitted
- * At end of DMA_TX Transfer, both TC and TXE are set.
- * Do not reinitialize transfer in that case!
- */
- if ((csr & USART_ISR_TXE) && !CM3BBGET(USARTnBase, USART_TypeDef, CR3, _BI32(USART_CR3_DMAT))) {
- Stm32UsartTxReady(&dcb->dcb_tx_rbf);
- }
- /* Last byte has been sent completely. */
- if (csr & USART_ISR_TC) {
- Stm32UsartTxComplete(&dcb->dcb_tx_rbf);
- }
- }
- /*!
- * \brief Carefully enable USART hardware functions.
- *
- * Always enabale transmitter and receiver, even on read-only or
- * write-only mode. So we can support software flow control.
- */
- static void Stm32UsartEnable(void)
- {
- /* Enable UART, receiver and transmitter. */
- USARTn->CR1 |= USART_CR1_UE|USART_CR1_TE|USART_CR1_RE;
- /* Enable Usart Interrupts */
- NutUartIrqEnable();
- }
- /*!
- * \brief Carefully disable USART hardware functions.
- *
- * This routine is called before changing cruical settings like
- * baudrate, frame format etc.
- *
- * The previous version uses a 10ms delay to make sure, that any
- * incoming or outgoing character is processed. However, this time
- * depends on the baudrate.
- *
- * In fact we do not need to take care of incoming characters,
- * when changing such settings.
- *
- * For outgoing characters however, settings may be changed on
- * the fly and we should wait, until the last character transmitted
- * with the old settings has left the shift register. While TXRDY
- * is set when the holding register is empty, TXEMPTY is set when the
- * shift register is empty. The bad news is, that both are zero, if
- * the transmitter is disabled. We are not able to determine this
- * state. So we check TXRDY first and, if set, wait for any character
- * currently in the shift register.
- */
- static void Stm32UsartDisable(void)
- {
- /* Disable Usart Interrupts*/
- NutUartIrqDisable();
- /* Wait until all bits had been shifted out. */
- while(!TXE_SET);
- /* Disable USART. */
- USARTn->CR1 &= ~(USART_CR1_TE|USART_CR1_RE);
- }
- /*!
- * \brief Query the USART hardware for the selected speed.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return The currently selected baudrate.
- */
- static uint32_t Stm32UsartGetSpeed(void)
- {
- uint32_t clk, frac_div = USARTn->BRR;
- #if USARTclk == NUT_HWCLK_PCLK1
- clk = NutClockGet(NUT_HWCLK_PCLK1);
- #else
- clk = NutClockGet(NUT_HWCLK_PCLK2);
- #endif
- if (CM3BBGET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_OVER8)))
- {
- uint32_t frac = frac_div & 7;
- frac_div >>= 1;
- frac_div &= ~0x7;
- frac_div |= frac;
- }
- return clk / frac_div;
- }
- /*!
- * \brief Set the USART hardware bit rate.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \param rate Number of bits per second.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartSetSpeed(uint32_t rate)
- {
- uint32_t tmpreg = 0x00;
- uint32_t apbclock = 0x00;
- uint32_t integerdivider = 0x00;
- uint32_t fractionaldivider = 0x00;
- Stm32UsartDisable();
- #if USARTclk == NUT_HWCLK_PCLK1
- apbclock = NutClockGet(NUT_HWCLK_PCLK1);
- #else
- apbclock = NutClockGet(NUT_HWCLK_PCLK2);
- #endif
- /* Determine the integer part */
- if (CM3BBGET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_OVER8)))
- {
- /* In case Oversampling mode is 8 Samples */
- integerdivider = ((25 * apbclock) / (2 * rate));
- if (integerdivider > 200)
- {
- /* switch back to 16 Sample Oversampling when possible*/
- CM3BBCLR(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_OVER8));
- integerdivider = ((25 * apbclock) / (4 * rate));
- }
- }
- else
- {
- /* In case Oversampling mode is 16 Samples */
- integerdivider = ((25 * apbclock) / (4 * rate));
- if (integerdivider < 100)
- {
- /* switch back to 8 Sample Oversampling*/
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_OVER8));
- integerdivider = ((25 * apbclock) / (2 * rate));
- }
- }
- /* Cap rate to highest possible */
- if (integerdivider <100)
- integerdivider = 100;
- tmpreg = (integerdivider / 100) << 4;
- /* Determine the fractional part */
- fractionaldivider = integerdivider - (100 * (tmpreg >> 4));
- if (CM3BBGET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_OVER8)))
- {
- /* In case Oversampling mode is 8 Samples */
- tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
- }
- else
- {
- /* In case Oversampling mode is 16 Samples */
- tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
- }
- /* Write to USART BRR */
- USARTn->BRR = (uint16_t)tmpreg;
- Stm32UsartEnable();
- return 0;
- }
- /*!
- * \brief Query the USART hardware for the number of data bits.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return The number of data bits set.
- */
- static uint8_t Stm32UsartGetDataBits(void)
- {
- uint32_t val = USARTn->CR1 & USART_CR1_M;
- if (val) {
- val = 9;
- } else {
- val = 8;
- }
- return (uint8_t)val;
- }
- /*!
- * \brief Set the USART hardware to the number of data bits.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartSetDataBits(uint8_t bits)
- {
- int rc = 0;
- uint32_t val = USARTn->CR1;
- switch( bits) {
- case 8:
- val &= ~USART_CR1_M;
- break;
- case 9:
- val |= USART_CR1_M;
- break;
- default:
- return -1;
- }
- Stm32UsartDisable();
- USARTn->CR1=val;
- Stm32UsartEnable();
- /*
- * Verify the result.
- */
- if (Stm32UsartGetDataBits() != bits) rc = -1;
- return rc;
- }
- /*!
- * \brief Query the USART hardware for the parity mode.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return Parity mode, either 0 (disabled), 1 (odd), 2 (even) or 9 (multidrop).
- */
- static uint8_t Stm32UsartGetParity(void)
- {
- uint32_t val = USARTn->CR1 & (USART_CR1_PCE|USART_CR1_PS);
- if (val == (USART_CR1_PCE|USART_CR1_PS))
- val = 1;
- else if (val == USART_CR1_PCE)
- val = 2;
- else
- val = 0;
- return (uint8_t)val;
- }
- /*!
- * \brief Set the USART hardware to the specified parity mode.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \param mode 0 (disabled), 1 (odd) or 2 (even)
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartSetParity(uint8_t mode)
- {
- int rc = 0;
- uint32_t val = USARTn->CR1 & ~(USART_CR1_PCE|USART_CR1_PS);
- switch (mode) {
- case 0:
- break;
- case 1:
- val |= USART_CR1_PCE|USART_CR1_PS;
- break;
- case 2:
- val |= USART_CR1_PCE;
- break;
- default:
- return -1;
- break;
- }
- Stm32UsartDisable();
- USARTn->CR1=val;
- Stm32UsartEnable();
- /*
- * Verify the result.
- */
- if (Stm32UsartGetParity() != mode) rc = -1;
- return rc;
- }
- /*!
- * \brief Query the USART hardware for the number of stop bits.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return The number of stop bits set, either 1, 2 or 3 (1.5 bits).
- */
- static uint8_t Stm32UsartGetStopBits(void)
- {
- uint32_t val = USARTn->CR2 & USART_CR2_STOP;
- if (val == 0) {
- val = 1;
- }
- else if (val == USART_CR2_STOP_1) {
- val = 2;
- }
- else if (val == USART_CR2_STOP){
- val = 3;
- }
- return (uint8_t)val;
- }
- /*!
- * \brief Set the USART hardware to the number of stop bits.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- int Stm32UsartSetStopBits(uint8_t bits)
- {
- int rc = 0;
- uint32_t val = USARTn->CR2 & ~USART_CR2_STOP;
- switch(bits) {
- case 1:
- break;
- case 2:
- val |= USART_CR2_STOP_1;
- break;
- case 3:
- val |= USART_CR2_STOP;
- break;
- default:
- return -1;
- break;
- }
- Stm32UsartDisable();
- USARTn->CR2 = val;
- Stm32UsartEnable();
- /*
- * Verify the result.
- */
- if (Stm32UsartGetStopBits() != bits) rc = -1;
- return rc;
- }
- /*!
- * \brief Query the USART hardware status.
- *
- * \return Status flags.
- */
- static uint32_t Stm32UsartGetStatus(void)
- {
- uint32_t rc = 0;
- #if defined(US_MODE_HWHANDSHAKE)
- uint32_t csr = USARTN_ISR;
- #endif
- /*
- * Set receiver error flags.
- */
- if ((rx_errors & USART_ISR_FE) != 0) {
- rc |= UART_FRAMINGERROR;
- }
- if ((rx_errors & USART_ISR_ORE) != 0) {
- rc |= UART_OVERRUNERROR;
- }
- if ((rx_errors & USART_ISR_PE) != 0) {
- rc |= UART_PARITYERROR;
- }
- #if defined(UART_XONXOFF_CONTROL)
- /*
- * Determine software handshake status. The flow control status may
- * change during interrupt, but this doesn't really hurt us.
- */
- if (flow_control) {
- if (flow_control & XOFF_SENT) {
- rc |= UART_RXDISABLED;
- }
- if (flow_control & XOFF_RCVD) {
- rc |= UART_TXDISABLED;
- }
- }
- #endif
- /*
- * Determine hardware handshake control status.
- */
- #if defined(US_MODE_HWHANDSHAKE)
- // TODO: reflect RTS state
- #endif
- /*
- * Determine hardware handshake sense status.
- */
- #if defined(US_MODE_HWHANDSHAKE)
- // TODO: reflect CTS state
- #endif
- /*
- * If transmitter and receiver haven't been detected disabled by any
- * of the checks above, then they are probably enabled.
- */
- if ((rc & UART_RXDISABLED) == 0) {
- rc |= UART_RXENABLED;
- }
- if ((rc & UART_TXDISABLED) == 0) {
- rc |= UART_TXENABLED;
- }
- /*
- * Process multidrop setting.
- */
- if (tx_aframe) {
- rc |= UART_TXADDRFRAME;
- } else {
- rc |= UART_TXNORMFRAME;
- }
- return rc;
- }
- /*!
- * \brief Set the USART hardware status.
- *
- * \param flags Status flags.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartSetStatus(uint32_t flags)
- {
- int rc = 0;
- /*
- * Process software handshake control.
- */
- #if defined(UART_XONXOFF_CONTROL)
- if (flow_control) {
- /* Access to the flow control status must be atomic. */
- NutUartIrqDisable();
- /*
- * Enabling or disabling the receiver means to behave like
- * having sent a XON or XOFF character resp.
- */
- if (flags & UART_RXENABLED) {
- flow_control &= ~XOFF_SENT;
- } else if (flags & UART_RXDISABLED) {
- flow_control |= XOFF_SENT;
- }
- /*
- * Enabling or disabling the transmitter means to behave like
- * having received a XON or XOFF character resp.
- */
- if (flags & UART_TXENABLED) {
- flow_control &= ~XOFF_RCVD;
- } else if (flags & UART_TXDISABLED) {
- flow_control |= XOFF_RCVD;
- }
- NutUartIrqEnable();
- }
- #endif
- /*
- * Process multidrop setting.
- */
- if (flags & UART_TXADDRFRAME) {
- tx_aframe = 1;
- }
- if (flags & UART_TXNORMFRAME) {
- tx_aframe = 0;
- }
- /*
- * Clear USART receive errors.
- */
- if (flags & UART_ERRORS) {
- CLEAR_ERRS();
- USARTN_RDR;
- }
- /*
- * Verify the result.
- */
- if ((Stm32UsartGetStatus() & ~UART_ERRORS) != flags) rc = -1;
- return rc;
- }
- /*!
- * \brief Query the USART hardware for synchronous mode.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * Not implemented for the STM32 USART. Always returns 0.
- *
- * \return Or-ed combination of \ref UART_SYNC, \ref UART_MASTER,
- * \ref UART_NCLOCK and \ref UART_HIGHSPEED.
- */
- uint8_t Stm32UsartGetClockMode(void)
- {
- return 0;
- }
- /*!
- * \brief Set asynchronous or synchronous mode.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * Not implemented for the STM32 USART. Always returns -1.
- *
- * \param mode Must be an or-ed combination of USART_SYNC, USART_MASTER,
- * USART_NCLOCK and USART_HIGHSPEED.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartSetClockMode(uint8_t mode)
- {
- return -1;
- }
- /*!
- * \brief Query flow control mode.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return See UsartIOCtl().
- */
- static uint32_t Stm32UsartGetFlowControl(void)
- {
- uint32_t rc = 0;
- #if defined(UART_XONXOFF_CONTROL)
- if (flow_control) {
- rc |= USART_MF_XONXOFF;
- } else {
- rc &= ~USART_MF_XONXOFF;
- }
- #endif
- if( hdpx_control) {
- rc |= USART_MF_HALFDUPLEX;
- } else {
- rc &= ~USART_MF_HALFDUPLEX;
- }
- #if defined( USART_485_CTRL)
- if (rs485_control) {
- rc |= USART_MF_LOCALECHO;
- } else {
- rc &= ~USART_MF_LOCALECHO;
- }
- #endif
- #ifdef UART_DMA_RXCHANNEL
- if (block_control & BC_RD_EN)
- rc |= USART_MF_BLOCKREAD;
- else
- rc &= ~USART_MF_BLOCKREAD;
- #endif
- #ifdef UART_DMA_TXCHANNEL
- if (block_control & BC_WR_EN)
- rc |= USART_MF_BLOCKWRITE;
- else
- rc &= ~USART_MF_BLOCKWRITE;
- #endif
- if (USARTn->CR3 & USART_CR3_HDSEL)
- rc |= USART_MF_OWIHALFDUPLEX;
- else
- rc &= ~USART_MF_OWIHALFDUPLEX;
- return rc;
- }
- /*!
- * \brief Set flow control mode.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \param flags See UsartIOCtl().
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartSetFlowControl(uint32_t flags)
- {
- #if defined(UART_XONXOFF_CONTROL)
- NutUartIrqDisable();
- /*
- * Set software handshake mode.
- */
- if (flags & USART_MF_XONXOFF) {
- if(flow_control == 0) {
- flow_control = 1 | XOFF_SENT; /* force XON to be sent on next read */
- }
- } else {
- flow_control = 0;
- }
- NutUartIrqEnable();
- #endif
- /* Setup half-duplex mode */
- if (flags & USART_MF_HALFDUPLEX) {
- hdpx_control = 1;
- }
- else if( hdpx_control == 1) {
- hdpx_control = 0;
- }
- /* Setup half-duplex mode */
- if (flags & USART_MF_OWIHALFDUPLEX) {
- Stm32UsartDisable();
- USARTn->CR1 &= ~USART_CR1_UE;
- USARTn->CR3 |= USART_CR3_HDSEL;
- /* Set Alternate function, open drain, Pull up */
- #if defined(TX_GPIO_PORT)
- #if defined(__STM32F10x_H)
- CM3BBSET(TX_GPIO_PORT, GPIO_TypeDef, CRL, _BI32(GPIO_CRL_CNF0_0) + TX_GPIO_PIN * 4);
- #else
- CM3BBSET(TX_GPIO_PORT, GPIO_TypeDef, PUPDR, _BI32(GPIO_PUPDR_PUPDR0_0) + TX_GPIO_PIN * 2);
- #endif
- #endif
- Stm32UsartEnable();
- }
- else {
- Stm32UsartDisable();
- USARTn->CR1 &= ~USART_CR1_UE;
- USARTn->CR3 &= ~USART_CR3_HDSEL;
- /* Set Alternate function, push-pull */
- #if defined(TX_GPIO_PORT)
- #if defined(__STM32F10x_H)
- CM3BBCLR(TX_GPIO_PORT, GPIO_TypeDef, CRL, _BI32(GPIO_CRL_CNF0_0) + TX_GPIO_PIN * 4) ;
- #else
- CM3BBCLR(TX_GPIO_PORT, GPIO_TypeDef, PUPDR, _BI32(GPIO_PUPDR_PUPDR0_0) + TX_GPIO_PIN * 2);
- #endif
- #endif
- Stm32UsartEnable();
- }
- #if defined( USART_485_CTRL)
- /* Control local echo mode:
- * Established by keeping /RE low while DE high. */
- if (flags & USART_MF_LOCALECHO) {
- rs485_control = 1;
- Rs485NRE_L();
- }
- else if (rs485_control) {
- rs485_control = 0;
- }
- #endif
- #ifdef UART_DMA_RXCHANNEL
- /* Setup block mode */
- if( flags & USART_MF_BLOCKREAD) {
- block_control |= BC_RD_EN;
- }
- else {
- block_control &= ~BC_RD_EN;
- }
- #endif
- #ifdef UART_DMA_TXCHANNEL
- if( flags & USART_MF_BLOCKWRITE) {
- block_control |= BC_WR_EN;
- }
- else {
- block_control &= ~BC_WR_EN;
- }
- #endif
- /*
- * Verify the result.
- */
- if ((Stm32UsartGetFlowControl() & USART_MF_FLOWMASK) !=
- (flags & USART_MF_FLOWMASK)) {
- return -1;
- }
- return 0;
- }
- /*!
- * \brief Start the USART transmitter hardware.
- *
- * The upper level USART driver will call this function through the
- * USARTDCB jump table each time it added one or more bytes to the
- * transmit buffer.
- */
- static void Stm32UsartTxStart(void)
- {
- Rs485DE_H(); /* Enable Sender */
- Rs485NRE_H(); /* Disable Receiver */
- if( hdpx_control) {
- /* Disable Receiver if half-duplex */
- CM3BBCLR(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_RE));
- }
- /* Clear Transmit Complete flag */
- CLEAR_TC();
- /* Enable transmit interrupts. */
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_TXEIE));
- }
- /*!
- * \brief Start the USART receiver hardware.
- *
- * The upper level USART driver will call this function through the
- * USARTDCB jump table each time it removed enough bytes from the
- * receive buffer. Enough means, that the number of bytes left in
- * the buffer is below the low watermark.
- */
- static void Stm32UsartRxStart(void)
- {
- #if defined(UART_XONXOFF_CONTROL)
- /*
- * Do any required software flow control.
- */
- if (flow_control && (flow_control & XOFF_SENT) != 0) {
- NutUartIrqDisable();
- if (TXE_SET) {
- USARTN_TDR=ASCII_XON;
- flow_control &= ~XON_PENDING;
- } else {
- flow_control |= XON_PENDING;
- }
- flow_control &= ~(XOFF_SENT | XOFF_PENDING);
- NutUartIrqEnable();
- }
- #endif
- /* Enable receive interrupts. */
- CM3BBSET(USARTnBase, USART_TypeDef, CR1, _BI32(USART_CR1_RXNEIE));
- }
- /*
- * \brief Initialize the USART hardware driver.
- *
- * This function is called during device registration by the upper level
- * USART driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartInit(void)
- {
- uint32_t cr2 = 0;
- uint32_t cr3 = 0;
- /*
- * Register receive and transmit interrupts.
- */
- if (NutRegisterIrqHandler(&SigUSART, Stm32UsartInterrupt, &DcbUSART)) {
- return -1;
- }
- /* Enable UART clock and reset device
- * We rely on the same value for RCC_APBxENR_USARTxEN and RCC_APBxRSTR_USARTxRST*/
- StmUsartClkEnable(1);
- #if defined(USART_SWAP)
- #if defined(TX_GPIO_PORT)
- /* Configure USART Tx as alternate function input*/
- GpioPinConfigSet( TX_GPIO_PORT, TX_GPIO_PIN, GPIO_CFG_PERIPHAL);
- #endif
- #if defined(RX_GPIO_PORT)
- /* Configure USART Rx as alternate function push-pull*/
- GpioPinConfigSet( RX_GPIO_PORT, RX_GPIO_PIN, GPIO_CFG_OUTPUT|GPIO_CFG_PERIPHAL);
- #endif
- #else
- #if defined(TX_GPIO_PORT)
- /* Configure USART Tx as alternate function push-pull */
- GpioPinConfigSet( TX_GPIO_PORT, TX_GPIO_PIN, GPIO_CFG_OUTPUT|GPIO_CFG_PERIPHAL);
- #endif
- #if defined(RX_GPIO_PORT)
- /* Configure USART Rx as alternate function input*/
- GpioPinConfigSet( RX_GPIO_PORT, RX_GPIO_PIN, GPIO_CFG_PERIPHAL);
- #endif
- #endif
- #if defined(RTS_GPIO_PORT) && defined(RTS_GPIO_PIN)
- /* Configure USART RTS as alternate function push-pull */
- GpioPinConfigSet( RTS_GPIO_PORT, RTS_GPIO_PIN, GPIO_CFG_PERIPHAL);
- #endif
- #if defined(CTS_GPIO_PORT) && defined(CTS_GPIO_PIN)
- /* Configure USART CTS as input floating */
- GpioPinConfigSet( CTS_GPIO_PORT, CTS_GPIO_PIN, GPIO_CFG_PERIPHAL);
- #endif
- #if defined(DE_GPIO_PORT) && defined(DE_GPIO_PIN)
- /* Configure RS485 direction switching pin */
- GpioPinConfigSet( DE_GPIO_PORT, DE_GPIO_PIN, GPIO_CFG_OUTPUT);
- #endif
- #if defined(NRE_GPIO_PORT) && defined(NRE_GPIO_PIN)
- /* Configure RS485 direction switching pin */
- GpioPinConfigSet( NRE_GPIO_PORT, NRE_GPIO_PIN, GPIO_CFG_OUTPUT);
- #endif
- /* USART Related GPIO Init */
- #if defined (MCU_STM32F1)
- #ifdef STM_USART_REMAP_MASK
- AFIO->MAPR &= ~STM_USART_REMAP_MASK;
- AFIO->MAPR |= STM_USART_REMAP_VALUE;
- #endif
- #else
- #if defined(TX_GPIO_PORT)
- GPIO_PinAFConfig((GPIO_TypeDef*) TX_GPIO_PORT, TX_GPIO_PIN, STM_USART_REMAP);
- #endif
- #if defined(RX_GPIO_PORT)
- GPIO_PinAFConfig((GPIO_TypeDef*) RX_GPIO_PORT, RX_GPIO_PIN, STM_USART_REMAP);
- #endif
- #if defined(RTS_GPIO_PORT) && defined(RTS_GPIO_PIN)
- GPIO_PinAFConfig((GPIO_TypeDef*) RTS_GPIO_PORT, RTS_GPIO_PIN, STM_USART_REMAP);
- #endif
- #if defined(CTS_GPIO_PORT) && defined(CTS_GPIO_PIN)
- GPIO_PinAFConfig((GPIO_TypeDef*) CTS_GPIO_PORT, CTS_GPIO_PIN, STM_USART_REMAP);
- #endif
- #endif/*F1 */
- /*
- * USART Communication Init
- */
- /* Enable additional features.
- * Most CR2/CR3 bit can only be set with CR1_UE == 0
- * E.g. Stm32UsartSetSpeed() sets CR1_UE
- */
- #if defined(USART_TX_PIN_INV)
- cr2 |= USART_CR2_TXINV;
- #endif
- #if defined(USART_RX_PIN_INV)
- cr2 |= USART_CR2_RXINV;
- #endif
- #if defined(USART_SWAP)
- cr2 |= USART_CR2_SWAP;
- #endif
- USARTn->CR2 = cr2;
- #ifdef USART_HWFLOWCTRL
- /* Enable hardware handshake options */
- #if defined(RTS_GPIO_PORT) && defined(RTS_GPIO_PIN)
- cr3 |= USART_CR3_RTSE;
- #endif
- #if defined(CTS_GPIO_PORT) && defined(CTS_GPIO_PIN)
- cr3 |= USART_CR3_CTSE;
- #endif
- #endif
- #ifdef USART_MODE_IRDA
- cr3 |= USART_CR3_IREN;
- #endif
- #ifdef USART_HARDWARE_HDX
- cr3 |= USART_CR3_HDSEL;
- #endif
- USARTn->CR3 = cr3;
- /* USART configuration */
- Stm32UsartSetSpeed(USART_INIT_BAUTRATE);
- Stm32UsartSetDataBits(8);
- Stm32UsartSetStopBits(2);
- Stm32UsartSetParity(0);
- /* Disable transmitter interrupts as they will
- * be enabled by the TxStart routine */
- USARTn->CR1 &= ~(USART_CR1_TXEIE|USART_CR1_TCIE|USART_CR1_RXNEIE);
- /* Enable USART */
- USARTn->CR1 |= USART_CR1_UE|USART_CR1_TE|USART_CR1_RE;
- #if defined(UART_DMA_TXCHANNEL) || defined(UART_DMA_RXCHANNEL)
- DMA_Init();
- #endif
- NutIrqEnable(&SigUSART);
- return 0;
- }
- /*
- * \brief Deinitialize the USART hardware driver.
- *
- * This function is called during device deregistration by the upper
- * level USART driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int Stm32UsartDeinit(void)
- {
- /* Disable interrupts */
- NutIrqDisable(&SigUSART);
- USARTn->CR1 = 0;
- /* Deregister receive and transmit interrupts. */
- NutRegisterIrqHandler(&SigUSART, 0, 0);
- /* Reset UART. */
- StmUsartClkEnable(0);
- return 0;
- }
- /*@}*/
|