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 mcan Controller Area Network (CAN) Example using MCAN
00032  *
00033  *  \section Purpose
00034  *
00035  *  The Controller Area Network (CAN) Example will help new users get familiar
00036  *  with the MCAN peripheral used in Atmel's Samv7 family of microcontrollers.
00037  *
00038  *  \section Requirements
00039  *
00040  *  This package can be used with SAMV71 Xplained Ultra board or SAME70 Xplained board.
00041  *
00042  *  \section Description
00043  *
00044  *  The demonstration program periodically transmits several different CAN
00045  *  messages.  The program enables CAN loopback mode so that the transmitted
00046  *  messages are reflected back as received messages as well.  LED #0 is toggled
00047  *  on a successful transmission of one of the messages & LED #1 is toggles on a
00048  *  successful reception of the same message.  Message transmission is stopped
00049  *  while SWITCH #0 is held depressed, which in turns means that both LED's
00050  *  should stop blinking.  Depressing SWITCH #1 alternates between standard CAN
00051  *  operation and CAN-FD operation with bit rate switching.
00052  *
00053  *  \section Usage
00054  *
00055  *  -# Build the program and download it inside the board.
00056  *     Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf
00057  *  -# On the computer, open and configure a terminal application
00058  *     (e.g. HyperTerminal on Microsoft Windows) with these settings:
00059  *    - 115200 baud rate
00060  *    - 8 bits of data
00061  *    - No parity
00062  *    - 1 stop bit
00063  *    - No flow control
00064  *  -# Start the application.
00065  *  -# LED(s) should start blinking on the board. In the terminal window, the
00066  *     following text should appear (values depend on the board and chip used):
00067  *     \code
00068  *      -- Controller Area Network (CAN) Example %s --\n\r", SOFTPACK_VERSION );
00069  *      -- xxxxxx-xx
00070  *      -- Compiled: xxx xx xxxx xx:xx:xx --
00071  *      -- LED0 toggles on CAN message reception
00072  *      -- LED1 toggles on CAN message transmission
00073  *      -- CAN message transmission stopped while SW0 is pushed
00074  *      -- SW1 pushes alternate between standard CAN and CAN-FD
00075  *     \endcode
00076  * -# Both LEDs should stop blinking while Button #0 is held depressed.
00077  *
00078  *  \section References
00079  *  - main.c
00080  *  - pio.h
00081  *  - pio_it.h
00082  *  - led.h
00083  *  - trace.h
00084  */
00085 
00086 /** \file
00087  *
00088  *  This file contains all the specific code for the CAN example.
00089  *
00090  */
00091 
00092 /*----------------------------------------------------------------------------
00093  *        Headers
00094  *----------------------------------------------------------------------------*/
00095 
00096 #include "board.h"
00097 
00098 #include <stdbool.h>
00099 #include <stdio.h>
00100 
00101 /*----------------------------------------------------------------------------
00102  *        Local definitions
00103  *----------------------------------------------------------------------------*/
00104 
00105 #define MSG_ID_0           0x555       // standard ID
00106 #define MSG_ID_0_DATA1     0x81        // 1 byte message
00107 #define MSG_ID_1           0x11111111  // extended ID
00108 #define MSG_ID_1_DATA1_4   0x55555555  // 8 byte message
00109 #define MSG_ID_1_DATA5_8   0x00FF00FF
00110 #define MSG_ID_2           0x444       // standard ID
00111 #define MSG_ID_2_MASK      0x7FC       // bits 0 & 1 are don't care
00112 #define TX_BUFFER_0        0
00113 #define TX_BUFFER_1        1
00114 #define RX_BUFFER_0        0
00115 #define RX_BUFFER_1        1
00116 #define FILTER_0           0
00117 #define FILTER_1           1
00118 
00119 #define BUTTON_NOT_PUSHED  1
00120 #define BUTTON_PUSHED      0
00121 
00122 #define CAN_STANDARD       0
00123 #define CAN_FD             1
00124 
00125 /*----------------------------------------------------------------------------
00126  *        Local variables
00127  *----------------------------------------------------------------------------*/
00128 
00129 static const Pin pushbutton[] = PINS_PUSHBUTTONS;
00130 
00131 volatile uint8_t tick = 0;
00132 
00133 uint32_t       txdCntr;
00134 uint32_t       rxdCntr;
00135 uint32_t       rxFifoCntr;
00136 uint32_t     * txMailbox0;
00137 uint32_t     * txMailbox1;
00138 Mailbox8Type   rxMailbox0;
00139 Mailbox8Type   rxMailbox1;
00140 Mailbox8Type   rxMailbox2;
00141 uint8_t        txData[8];
00142 
00143 /*----------------------------------------------------------------------------
00144  *        Local functions
00145  *----------------------------------------------------------------------------*/
00146 
00147 /* Handler for MCAN0, Line 0 */
00148 void MCAN0_Handler(void)
00149 {
00150 }
00151 
00152 /* Handler for MCAN0, Line 1 */
00153 void MCAN0_Line1_Handler(void)
00154 {
00155 }
00156 
00157 /* Handler for MCAN1, Line 0 */
00158 void MCAN1_Handler(void)
00159 {
00160 }
00161 
00162 /* Handler for MCAN1, Line 1 */
00163 void MCAN1_Line1_Handler(void)
00164 {
00165     if (MCAN_IsMessageStoredToRxDedBuffer(&mcan1Config)) {
00166         MCAN_ClearMessageStoredToRxBuffer(&mcan1Config);
00167         if (MCAN_IsNewDataInRxDedBuffer(&mcan1Config, RX_BUFFER_0)) {
00168             MCAN_GetRxDedBuffer(&mcan1Config, RX_BUFFER_0, (Mailbox64Type *)
00169                 &rxMailbox0);
00170         // verify data
00171             if (rxMailbox0.data[0] == MSG_ID_0_DATA1) {
00172                 // Toggle LED #0 To Indicate New Message Received in Interrupt
00173                 LED_Toggle(0);
00174                 rxdCntr++;
00175             }
00176         }
00177         if (MCAN_IsNewDataInRxDedBuffer(&mcan1Config, RX_BUFFER_1)) {
00178             MCAN_GetRxDedBuffer(&mcan1Config, RX_BUFFER_1, (Mailbox64Type *)
00179                 &rxMailbox1);
00180         rxdCntr++;
00181         }
00182     }
00183 }
00184 
00185 /**
00186  *  Interrupt handler for TC0 interrupt. Toggles the state of LED\#2.
00187  */
00188 void TC0_Handler(void)
00189 {
00190     volatile uint32_t dummy;
00191     /* Clear status bit to acknowledge interrupt */
00192     dummy = TC0->TC_CHANNEL[0].TC_SR;
00193     tick = 1;
00194 }
00195 
00196 /**
00197  *  Configure Timer Counter 0 to generate an interrupt every 250ms.
00198  */
00199 static void _ConfigureTc(void)
00200 {
00201     uint32_t div;
00202     uint32_t tcclks;
00203 
00204     /** Enable peripheral clock. */
00205     PMC_EnablePeripheral(ID_TC0);
00206     /** Configure TC for a 4Hz frequency and trigger on RC compare. */
00207     TC_FindMckDivisor(4, BOARD_MCK, &div, &tcclks, BOARD_MCK);
00208 
00209     TC_Configure(TC0, 0, tcclks | TC_CMR_CPCTRG);
00210     TC0->TC_CHANNEL[0].TC_RC = (BOARD_MCK / div) / 4;
00211 
00212     /* Configure and enable interrupt on RC compare */
00213     NVIC_ClearPendingIRQ(TC0_IRQn);
00214     NVIC_EnableIRQ(TC0_IRQn);
00215 
00216     TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS;
00217 
00218     /** Start the counter */
00219     TC_Start(TC0, 0);
00220 }
00221 
00222 /*----------------------------------------------------------------------------
00223  *        Exported functions
00224  *----------------------------------------------------------------------------*/
00225 /**
00226  *  \brief getting-started Application entry point.
00227  *
00228  *  \return Unused (ANSI-C compatibility).
00229  */
00230 extern int main(void)
00231 {
00232     uint32_t id_offset = 0;
00233     uint32_t fifo_entries;
00234     uint32_t button_state = BUTTON_PUSHED;
00235     uint32_t button_state2 = BUTTON_NOT_PUSHED;
00236     uint32_t can_mode = CAN_STANDARD;
00237 
00238     /* Disable watchdog */
00239     WDT_Disable(WDT);
00240 
00241     /* Output example information */
00242     printf("\n\r-- Controller Area Network (CAN) Example %s --\n\r",
00243             SOFTPACK_VERSION);
00244     printf("-- %s\n\r", BOARD_NAME);
00245     printf("-- Compiled: %s %s --\n\r\n\r", __DATE__, __TIME__);
00246     printf("-- LED0 toggles on CAN message reception\n\r");
00247     printf("-- LED1 toggles on CAN message transmission\n\r");
00248     printf("-- CAN message transmission stopped while SW0 is pushed\n\r");
00249     printf("-- SW1 pushes alternate between standard CAN and CAN-FD\n\r");
00250 
00251     SCB_EnableICache();
00252     SCB_EnableDCache();
00253 
00254     /* Configure systick for 1 ms. */
00255     TimeTick_Configure();
00256 
00257     /* Configure Board LED's */
00258     LED_Configure(0);
00259 #if 2 == LED_NUM
00260     LED_Configure(1);
00261 #endif
00262 
00263     /* Configure Timer/Counter for 250msec Tick */
00264     _ConfigureTc();
00265 
00266     /* Configure Board Push-buttons */
00267     // SW1 is a ERASE system function, switch it to port function
00268     MATRIX->CCFG_SYSIO |= (1u << 12);
00269     /* have to disable the pull down on PB12 for SW1 before the pull up can be
00270         enabled */
00271     PIOB->PIO_PPDDR = 1 << 12;
00272     PIO_Configure(pushbutton, PIO_LISTSIZE(pushbutton));
00273     /* Adjust pio denounce filter parameters, uses 10 Hz filter. */
00274     PIO_SetDebounceFilter(&pushbutton[0], 10);
00275 #if 2 == BUTTON_NUM
00276     PIO_SetDebounceFilter(&pushbutton[1], 10000);
00277 #endif
00278 
00279     SystemCoreClockUpdate();
00280 
00281     MCAN_Init(&mcan1Config);
00282 
00283     MCAN_InitFdBitRateSwitchEnable(&mcan1Config);
00284     MCAN_InitTxQueue(&mcan1Config);
00285     MCAN_InitLoopback(&mcan1Config);  // remove to disable loop back mode
00286     MCAN_Enable(&mcan1Config);
00287 
00288     MCAN_IEnableMessageStoredToRxDedBuffer(&mcan1Config, CAN_INTR_LINE_1);
00289 
00290     txMailbox0 = (uint32_t *)MCAN_ConfigTxDedBuffer(&mcan1Config, TX_BUFFER_0,
00291             MSG_ID_0, CAN_STD_ID, CAN_DLC_1);
00292     txMailbox1 = (uint32_t *)MCAN_ConfigTxDedBuffer(&mcan1Config, TX_BUFFER_1,
00293             MSG_ID_1, CAN_EXT_ID, CAN_DLC_8);
00294     MCAN_ConfigRxBufferFilter(&mcan1Config, RX_BUFFER_0, FILTER_0, MSG_ID_0,
00295             CAN_STD_ID);
00296     MCAN_ConfigRxBufferFilter(&mcan1Config, RX_BUFFER_1, FILTER_0, MSG_ID_1,
00297             CAN_EXT_ID);
00298     MCAN_ConfigRxClassicFilter(&mcan1Config, CAN_FIFO_0, FILTER_1, MSG_ID_2,
00299             CAN_STD_ID, MSG_ID_2_MASK);
00300 
00301     while (1) {
00302          if (tick) {
00303             tick = 0;
00304             if (PIO_Get(&pushbutton[0]) == BUTTON_NOT_PUSHED) {
00305                 if (button_state2 == BUTTON_NOT_PUSHED) {
00306                     /* periodically transmit messages while SW0 is not pushed */
00307                     // send standard ID from a dedicated buffer
00308                     *txMailbox0 = MSG_ID_0_DATA1;  // write data into CAN mailbox
00309                     MCAN_SendTxDedBuffer(&mcan1Config, TX_BUFFER_0);  // send data
00310                     txdCntr++;
00311                     // send extended ID from a dedicated buffer
00312                     *txMailbox1 = MSG_ID_1_DATA1_4;  // write data into CAN mailbox
00313                     *(txMailbox1 + 1) = MSG_ID_1_DATA5_8; // write data into CAN mailbox
00314                     MCAN_SendTxDedBuffer(&mcan1Config, TX_BUFFER_1); // send the data
00315                     txdCntr++;
00316                     // send from Tx Queue
00317                     MCAN_AddToTxFifoQ(&mcan1Config, MSG_ID_2 + id_offset, CAN_STD_ID,
00318                             CAN_DLC_1, &txData[0]);
00319                     txdCntr++;
00320                     // increment the offset so we send different ID's within the
00321                     // range defined by the mask
00322                     id_offset = (id_offset + 1) & (uint32_t) ~MSG_ID_2_MASK;
00323                     // update data being sent for next time
00324                     txData[0]++;
00325                     button_state2 = BUTTON_NOT_PUSHED;
00326                 }
00327             } else {
00328                 if (button_state2 == BUTTON_NOT_PUSHED)
00329                     button_state2 = BUTTON_PUSHED;
00330                 else
00331                     button_state2 = BUTTON_NOT_PUSHED;
00332             }
00333         }
00334         /* poll for TX'd message complete */
00335          if (MCAN_IsTxComplete(&mcan1Config)) {
00336             MCAN_ClearTxComplete(&mcan1Config);
00337             if (MCAN_IsBufferTxd(&mcan1Config, TX_BUFFER_0)) {
00338         #if 2 == LED_NUM
00339                 LED_Toggle(1);
00340         #endif
00341             }
00342         }
00343         /* Poll for new CAN messages in RX FIFO */
00344         do {
00345             fifo_entries = MCAN_GetRxFifoBuffer(&mcan1Config, CAN_FIFO_0,
00346                     (Mailbox64Type *) &rxMailbox2);
00347             if (fifo_entries > 0) rxdCntr++;
00348         } while (fifo_entries > 1);
00349 
00350         /* SW1 used to alternate between standard CAN and CAN-FD operation */
00351 #if 2 == BUTTON_NUM
00352         if (PIO_Get(&pushbutton[1]) == BUTTON_NOT_PUSHED) {
00353 #else
00354         if (1) {
00355 #endif
00356              button_state = BUTTON_NOT_PUSHED;
00357         } else {
00358             if (button_state == BUTTON_NOT_PUSHED ) {
00359                 // Switch on a NOT PUSHED to PUSHED edge
00360                 button_state = BUTTON_PUSHED;
00361                 if (can_mode == CAN_STANDARD) {
00362                     can_mode = CAN_FD;
00363                     MCAN_RequestFdBitRateSwitch( &mcan1Config );
00364                 } else {
00365                     can_mode = CAN_STANDARD;
00366                     MCAN_RequestIso11898_1( &mcan1Config );
00367                 }
00368             }
00369         }
00370 #ifdef POLLKEYBOARD
00371     /* poll for keyboard entry */
00372     if (DBG_IsRxReady()) {
00373         keyboard = DBG_GetChar();
00374         if (((char) keyboard == 'L' ) || ( (char) keyboard == 'l')) {
00375             if (loopback == 1) {
00376                 MCAN_LoopbackOff(&mcan1Config);
00377                 loopback = 0;
00378             } else {
00379                 MCAN_LoopbackOn(&mcan1Config);
00380                 loopback = 1;
00381             }
00382         }
00383     }
00384 #endif
00385     }
00386 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines