SAMV71 Xplained Ultra Software Package 1.5

main.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /**
00031  *  \page usart_rs485 USART RS485 example with DMA
00032  *
00033  *  This example demonstrates the RS485 mode provided by the USART peripherals on
00034  *  SAMV7 Microcontrollers.
00035  *
00036  *  \section Requirements
00037  *
00038  *  This package can be used with SAMV71 Xplained Ultra board or SAME70 Xplained board.
00039  *  Before running, make sure to connect two boards with RS485 lines. The rs485
00040  *  adapt board (ADM3485ARZ) for this purpose.
00041  *  Match each paired pins of two boards respectively with A to A,
00042  *  B to B and FGND to FGND(the central pin of J3).
00043  *  this part is connect with EK and ADM3485ARZ
00044  *   - <b>Board 1                             Board 2</b>
00045  *   -  TXD0(EXT1 pin14) <->DI            TXD0(EXT1 pin14) <->DI
00046  *   -  RXD0(EXT1 pin13) <->RO            RXD0(EXT1 pin13) <->RO
00047  *   -  RTS0(EXT1 pin5 ) <->DE            RTS0(EXT1 pin5 ) <->DE
00048  *   -  CTS0(EXT1 pin6 ) <->RE            CTS0(EXT1 pin6 ) <->RE
00049  *   -  3.3v                                   3.3v
00050  *   -  GND                                    GND
00051  *  this part is connect with 2 ADM3485ARZ
00052  *      A              <-------------------->  A
00053  *      B              <-------------------->  B
00054  *      PGND           <-------------------->  PGND
00055  *
00056  *  \section Description
00057  *
00058  *  This example connects two boards through RS485 interface. One board acts
00059  *  as the transmitter and the other one as the receiver. It is determined by
00060  *  the sequence the two applications started.
00061  *
00062  * \section Usage
00063  *
00064  *  -# Build the program and download it inside the board.
00065  *  Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf
00066  *  -# Connect a serial cable to the DBGU port on the evaluation kit.
00067  *  -# On the computer, open and configure a terminal application for each board (e.g.
00068  *     HyperTerminal on Microsoft Windows) with these settings:
00069  *        - 115200 baud rate
00070  *        - 8 bits of data
00071  *        - No parity
00072  *        - 1 stop bit
00073  *        - No flow control
00074  *  -# Start application from two boards in sequence. Make sure the second board
00075  *     should NOT be started unless the first board had run to wait for the
00076  *     synchronizing character. The output message in later section would
00077  *     describe this.
00078  *
00079  *  -# In the terminal  window, the
00080  *     following text should appear (values depend on the board and chip used):
00081  *     \code
00082  *     -- USART RS485 Mode Example xxx --
00083  *     -- SAMxxxxx-xx
00084  *     -- Compiled: xxx xx xxxx xx:xx:xx --
00085  *     \endcode
00086  *
00087  *  \section References
00088  *  - usart_rs485/main.c
00089  *  - pio.h
00090  *  - usart.h
00091  */
00092 
00093 /** \file
00094  *
00095  *  This file contains all the specific code for the usart_rs485 example.
00096  */
00097 
00098 /*----------------------------------------------------------------------------
00099  *        Headers
00100  *----------------------------------------------------------------------------*/
00101 
00102 #include "board.h"
00103 
00104 #include <stdbool.h>
00105 #include <stdio.h>
00106 #include <string.h>
00107 
00108 /*----------------------------------------------------------------------------
00109  *        Local definitions
00110  *----------------------------------------------------------------------------*/
00111 
00112 /** size of the receive buffer used by the DMA, in bytes.*/
00113 #define BUFFER_SIZE     1000
00114 
00115 /** baud rate */
00116 #define BAUDRATE_RS485  256000
00117 
00118 /** Register base for USART */
00119 #define USART           USART0
00120 #define ID_USART        ID_USART0
00121 
00122 /*----------------------------------------------------------------------------
00123  *        Local variables
00124  *----------------------------------------------------------------------------*/
00125 /** Global DMA driver for all transfer */
00126 static sXdmad dmad;
00127 
00128 static uint32_t usartDmaRxChannel;
00129 static uint32_t usartDmaTxChannel;
00130 
00131 /** RE for RS485 */
00132 #define PIN_USART0_CTS_IOR {PIO_PB2C_CTS0, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
00133 
00134 /**  Pins to configure for the application.*/
00135 const Pin pins[] = {PIN_USART0_RXD, PIN_USART0_TXD, PIN_USART0_CTS_IOR, PIN_USART0_RTS};
00136 
00137 /** Transmit buffer. */
00138 char palette[BUFFER_SIZE]=
00139  "**************************************************************************\n\r\
00140  *  This application gives an example of how to use USART in RS485 mode.\n\r\
00141  *  The USART features the RS485 mode to enable line driver control.\n\r\
00142  *  While operating in RS485 mode, the USART behaves as though in asynchronous \n\r\
00143  *  or synchronous mode and configuration of all the parameters is possible \n\r\
00144  *  \n\r\
00145  *  The difference is that the RTS pin is driven high when the transmitter\n\r\
00146  *  is operating. The behavior of the RTS pin is controlled by the TXEMPTY bit.\n\r\
00147  *  \n\r\
00148  **************************************************************************\n\r\
00149  ";
00150 
00151 /** Transmit buffer. */
00152 COMPILER_ALIGNED(32) static char Buffer[BUFFER_SIZE];
00153 
00154 /** buffer for receiving */
00155 COMPILER_ALIGNED(32) static char pRecvBufferUSART[BUFFER_SIZE];
00156 
00157 /** reception done*/
00158 static volatile uint8_t recvDone = 0;
00159 
00160 /** sending done*/
00161 static volatile uint8_t transDone = 0;
00162 
00163 /*----------------------------------------------------------------------------
00164  *        Local functions
00165  *----------------------------------------------------------------------------*/
00166 
00167 /**
00168  * \brief Configures USART in rs485 mode
00169  */
00170 static void _ConfigureUsart(void)
00171 {
00172     uint32_t mode = US_MR_USART_MODE_RS485 | US_MR_USCLKS_MCK
00173                     | US_MR_CHRL_8_BIT | US_MR_PAR_NO | US_MR_NBSTOP_1_BIT
00174                     | US_MR_CHMODE_NORMAL;
00175 
00176     /* Enable the peripheral clock in the PMC */
00177     PMC_EnablePeripheral(ID_USART);
00178 
00179     /* Configure the USART in the desired mode @USART_SPI_CLK bauds*/
00180     USART_Configure(USART, mode, BAUDRATE_RS485, BOARD_MCK);
00181 
00182     /* Enable receiver & transmitter */
00183     USART_SetTransmitterEnabled(USART, 1);
00184     USART_SetReceiverEnabled(USART, 1);
00185 }
00186 
00187 /**
00188  * ISR for DMA interrupt
00189  */
00190 void XDMAC_Handler(void)
00191 {
00192     XDMAD_Handler(&dmad);
00193 }
00194 
00195 /**
00196  *  \brief Callback function for DMA receiving.
00197  */
00198 static void _DmaRxCallback(uint32_t channel, void* pArg)
00199 {
00200     channel = channel;
00201     pArg = pArg;
00202     SCB_InvalidateDCache_by_Addr((uint32_t*)pRecvBufferUSART, BUFFER_SIZE - 1);
00203     recvDone = 1;
00204 }
00205 
00206 /**
00207  *  \brief Callback function for DMA transmitting.
00208  */
00209 static void _DmaTxCallback(uint32_t channel, void* pArg)
00210 {
00211     channel = channel;
00212     pArg = pArg;
00213     transDone = 1;
00214 }
00215 
00216 /**
00217  *  \brief Start USART sending data.
00218  */
00219 static void _DmaUsartTx(void)
00220 {
00221     sXdmadCfg xdmadCfg;
00222 
00223     xdmadCfg.mbr_ubc = BUFFER_SIZE;
00224     xdmadCfg.mbr_sa = (uint32_t)Buffer;
00225     xdmadCfg.mbr_da = (uint32_t)&USART->US_THR;
00226     xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00227                     XDMAC_CC_MBSIZE_SINGLE |
00228                     XDMAC_CC_DSYNC_MEM2PER |
00229                     XDMAC_CC_CSIZE_CHK_1 |
00230                     XDMAC_CC_DWIDTH_BYTE |
00231                     XDMAC_CC_SIF_AHB_IF1 |
00232                     XDMAC_CC_DIF_AHB_IF1 |
00233                     XDMAC_CC_SAM_INCREMENTED_AM |
00234                     XDMAC_CC_DAM_FIXED_AM |
00235                     XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_USART, XDMAD_TRANSFER_TX));
00236 
00237     xdmadCfg.mbr_bc = 0;
00238     xdmadCfg.mbr_ds = 0;
00239     xdmadCfg.mbr_sus = 0;
00240     xdmadCfg.mbr_dus = 0;
00241     XDMAD_ConfigureTransfer(&dmad, usartDmaTxChannel, &xdmadCfg, 0, 0,
00242                             XDMAC_CIE_BIE |
00243                             XDMAC_CIE_DIE |
00244                             XDMAC_CIE_FIE |
00245                             XDMAC_CIE_RBIE |
00246                             XDMAC_CIE_WBIE |
00247                             XDMAC_CIE_ROIE);
00248     SCB_CleanDCache_by_Addr((uint32_t*)Buffer, BUFFER_SIZE);
00249     XDMAD_StartTransfer(&dmad, usartDmaTxChannel);
00250 }
00251 
00252 /**
00253  *  \brief Start USART waiting data.
00254  */
00255 static void _DmaUsartRx(void)
00256 {
00257     uint32_t status;
00258 
00259     /* Read USART status */
00260     status = USART->US_CSR;
00261     if ((status & US_CSR_RXRDY) == US_CSR_RXRDY)
00262         status = USART->US_RHR; /* clear the US_CSR_RXRDY*/
00263 
00264     sXdmadCfg xdmadCfg;
00265     xdmadCfg.mbr_ubc = BUFFER_SIZE;
00266     xdmadCfg.mbr_sa = (uint32_t)&USART->US_RHR;
00267     xdmadCfg.mbr_da = (uint32_t)pRecvBufferUSART;
00268     xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00269                        XDMAC_CC_MBSIZE_SINGLE |
00270                        XDMAC_CC_DSYNC_PER2MEM |
00271                        XDMAC_CC_CSIZE_CHK_1 |
00272                        XDMAC_CC_DWIDTH_BYTE |
00273                        XDMAC_CC_SIF_AHB_IF1 |
00274                        XDMAC_CC_DIF_AHB_IF1 |
00275                        XDMAC_CC_SAM_FIXED_AM |
00276                        XDMAC_CC_DAM_INCREMENTED_AM |
00277                        XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber( ID_USART, XDMAD_TRANSFER_RX));
00278 
00279     xdmadCfg.mbr_bc = 0;
00280     xdmadCfg.mbr_ds = 0;
00281     xdmadCfg.mbr_sus = 0;
00282     xdmadCfg.mbr_dus = 0;
00283     XDMAD_ConfigureTransfer(&dmad, usartDmaRxChannel, &xdmadCfg, 0, 0,
00284                             XDMAC_CIE_BIE |
00285                             XDMAC_CIE_DIE |
00286                             XDMAC_CIE_FIE |
00287                             XDMAC_CIE_RBIE |
00288                             XDMAC_CIE_WBIE |
00289                             XDMAC_CIE_ROIE);
00290     XDMAD_StartTransfer( &dmad, usartDmaRxChannel);
00291 }
00292 
00293 
00294 /*
00295  *  \brief DMA driver configuration
00296  */
00297 static void _ConfigureDma(void)
00298 {
00299     /* Driver initialize */
00300     XDMAD_Initialize(&dmad, 0);
00301 
00302     /* Allocate XDMA channels for USART */
00303     usartDmaTxChannel = XDMAD_AllocateChannel(&dmad, XDMAD_TRANSFER_MEMORY, ID_USART);
00304     usartDmaRxChannel = XDMAD_AllocateChannel(&dmad, ID_USART, XDMAD_TRANSFER_MEMORY);
00305     if (usartDmaTxChannel == XDMAD_ALLOC_FAILED ||
00306         usartDmaRxChannel == XDMAD_ALLOC_FAILED ) {
00307         printf("XDMA channel allocat failed!\n\r");
00308         while (1);
00309     }
00310 
00311     /* Set RX callback */
00312     XDMAD_SetCallback(&dmad, usartDmaRxChannel,(XdmadTransferCallback)_DmaRxCallback, 0);
00313     /* Set TX callback */
00314     XDMAD_SetCallback(&dmad, usartDmaTxChannel,(XdmadTransferCallback)_DmaTxCallback, 0);
00315     XDMAD_PrepareChannel(&dmad, usartDmaRxChannel );
00316     XDMAD_PrepareChannel(&dmad, usartDmaTxChannel);
00317 }
00318 
00319 /**
00320  * \brief Display menu.
00321  */
00322 static void _DisplayMenu(void)
00323 {
00324     printf("Menu :\n\r");
00325     printf("------\n\r");
00326     printf(" - t: Transmit pattern to RS485\n\r");
00327     printf(" - r: Receive data from RS485 \n\r");
00328     printf(" - m: Display menu \n\r");
00329 }
00330 
00331 /**
00332  * \brief Dump buffer to DBGU
00333  *
00334  */
00335 static void _DumpInfo(char *buf, uint32_t size)
00336 {
00337     uint32_t i = 0;
00338 
00339     while ((i < size) && (buf[i] != 0))
00340         printf("%c", buf[i++]);
00341 }
00342 
00343 /*----------------------------------------------------------------------------
00344  *        Exported functions
00345  *----------------------------------------------------------------------------*/
00346 /**
00347  *  \brief Application entry point.
00348  *
00349  *  \return Unused (ANSI-C compatibility).
00350  */
00351 extern int main(void)
00352 {
00353     uint8_t ucKey;
00354 
00355     /* Disable watchdog */
00356     WDT_Disable(WDT);
00357 
00358     SCB_EnableICache();
00359     SCB_EnableDCache();
00360 
00361     /* Output example information */
00362     printf("-- USART RS485 Example %s --\n\r", SOFTPACK_VERSION);
00363     printf("-- %s\n\r", BOARD_NAME);
00364     printf("-- Compiled: %s %s  With %s--\n\r", __DATE__, __TIME__, COMPILER_NAME);
00365 
00366     /* Configure pins*/
00367     PIO_Configure(pins, PIO_LISTSIZE(pins));
00368 
00369     /* Display menu */
00370     _DisplayMenu();
00371 
00372     /* Configure DMA with IRQ */
00373     _ConfigureDma();
00374 
00375     memcpy(Buffer, palette, BUFFER_SIZE);
00376 
00377     /* configure USART in RS485 mode*/
00378     _ConfigureUsart();
00379 
00380     NVIC_EnableIRQ(XDMAC_IRQn);
00381 
00382     while (1) {
00383         ucKey = DBG_GetChar();
00384         switch (ucKey) {
00385         case 't':
00386         case 'T':
00387             printf("-I- RS485 Transmitting ... \n\r");
00388             _DmaUsartTx();
00389             while (!transDone);
00390             printf("-I- RS485 Transmitting completed \n\r");
00391             transDone = 0;
00392             break;
00393 
00394         case 'r':
00395         case 'R':
00396             printf("-I- RS485 receiving ... \n\r");
00397             recvDone = 0;
00398             _DmaUsartRx();
00399             while (!recvDone);
00400             /* successfully received */
00401             _DumpInfo(pRecvBufferUSART, BUFFER_SIZE);
00402             printf("-I- RS485 Receiving completed \n\r");
00403             memset(pRecvBufferUSART, 0, sizeof(pRecvBufferUSART));
00404             break;
00405 
00406         case 'm':
00407         case 'M':
00408             _DisplayMenu();
00409             break;
00410         }
00411     }
00412 }
00413 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines