serial_transport_samD21j18a.c
Go to the documentation of this file.
00001 
00009 /*
00010 * Copyright (c) 2010 ThingMagic, Inc.
00011 *
00012 * Permission is hereby granted, free of charge, to any person obtaining a copy
00013 * of this software and associated documentation files (the "Software"), to deal
00014 * in the Software without restriction, including without limitation the rights
00015 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00016 * copies of the Software, and to permit persons to whom the Software is
00017 * furnished to do so, subject to the following conditions:
00018 *
00019 * The above copyright notice and this permission notice shall be included in
00020 * all copies or substantial portions of the Software.
00021 *
00022 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00025 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00028 * THE SOFTWARE.
00029 */
00030 
00031 #include "tm_reader.h"
00032 #include <asf.h>
00033 #include <stdio.h>
00034 
00035 /*** MAX_RX_BUFFER_LENGTH Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
00036 #define MAX_RX_BUFFER_LENGTH   256
00037 #define RBUFLEN ((uint32_t)((rbuf.head < rbuf.tail) ? ((MAX_RX_BUFFER_LENGTH- rbuf.tail)+rbuf.head):(rbuf.head - rbuf.tail)))
00038 
00039 /*
00040 *Circular Buffer Structure
00041 */
00042 typedef struct buf_st {
00043         volatile uint32_t head;                      /* Next In Index  */
00044         uint32_t tail;                               /* Next Out Index */
00045         volatile char buffer [MAX_RX_BUFFER_LENGTH]; /* Buffer         */
00046 }circBuf_t;
00047 
00048 struct usart_config config_usart;
00049 static uint8_t s_open_flag =1;
00050 struct usart_module usart_instance;
00051 circBuf_t rbuf;
00052 
00053 void sercom4Handler(void);
00054 void configure_usart(void);
00055 
00062 void sercom4Handler(void)
00063 {
00064   /* Temporary variables */
00065   uint16_t interrupt_status;
00066   uint8_t receiveByte;
00067   uint8_t error_code;
00068 
00069   /* Get device instance from the look-up table */
00070   struct usart_module *module = &usart_instance;
00071 
00072   /* Pointer to the hardware module instance */
00073   SercomUsart *const usart_hw = &(usart_instance.hw->USART);
00074 
00075   /* Wait for the synchronization to complete */
00076   _usart_wait_for_sync(module);
00077 
00078   /* Read and mask interrupt flag register */
00079   interrupt_status = usart_hw->INTFLAG.reg;
00080   interrupt_status &= usart_hw->INTENSET.reg;
00081 
00082   /*Disable DATA READY interrupt if it is enabled */
00083   usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
00084 
00085 
00086   if(interrupt_status & SERCOM_USART_INTFLAG_RXC)
00087   {
00088         /* Read out the status code and mask away all but the 3 LSBs*/
00089         error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
00090 
00091         /* Check if an error has occurred during the receiving */
00092         if (error_code)
00093         {
00094           /* Check which error occurred */
00095           if (error_code & SERCOM_USART_STATUS_FERR) 
00096           {
00097             /* Clear flag by writing a 1 to it */
00098                 usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;                
00099           } 
00100           if (error_code & SERCOM_USART_STATUS_BUFOVF)
00101           {
00102         /* Clear flag by writing a 1 to it */
00103                 usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;      
00104           } 
00105           if (error_code & SERCOM_USART_STATUS_PERR)
00106           {
00107                 /* Clear flag by writing a 1 to it */
00108                 usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR;        
00109           }
00110 #ifdef FEATURE_USART_LIN_SLAVE
00111           if (error_code & SERCOM_USART_STATUS_ISF)
00112       {
00113                 /* Clear flag by writing 1 to it */
00114                 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_ISF;                
00115           }
00116 #endif
00117 #ifdef FEATURE_USART_COLLISION_DECTION
00118           if (error_code & SERCOM_USART_STATUS_COLL) 
00119           {
00120             /* Clear flag by writing 1 to it */
00121                 usart_hw->STATUS.reg |= SERCOM_USART_STATUS_COLL;               
00122           }
00123 #endif
00124         }
00125         else
00126         {
00127           uint32_t next;
00128           receiveByte = usart_hw->DATA.reg;
00129           next= rbuf.head + 1;
00130           next &= (MAX_RX_BUFFER_LENGTH-1);
00131 
00132           if (next != rbuf.tail)
00133           {
00134                 rbuf.buffer[rbuf.head] = receiveByte;
00135                 rbuf.head = next;
00136           }
00137         }
00138   }
00139   else
00140   {
00141         /* This should not happen. Disable Receive Complete interrupt. */
00142         usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
00143   }
00144 }
00145 
00146 void
00147 configure_usart()
00148 {
00149   usart_get_config_defaults(&config_usart);
00150   config_usart.baudrate    = 115200;
00151   config_usart.mux_setting = EXT1_UART_SERCOM_MUX_SETTING;
00152   config_usart.pinmux_pad0 = EXT1_UART_SERCOM_PINMUX_PAD0;
00153   config_usart.pinmux_pad1 = EXT1_UART_SERCOM_PINMUX_PAD1;
00154   config_usart.pinmux_pad2 = EXT1_UART_SERCOM_PINMUX_PAD2;
00155   config_usart.pinmux_pad3 = EXT1_UART_SERCOM_PINMUX_PAD3;
00156 
00157   /* Initialize the Rx circular buffer structure */
00158   rbuf.head = 0;
00159   rbuf.tail = 0;
00160   for(uint32_t i = 0; i< MAX_RX_BUFFER_LENGTH; i++)
00161   {
00162         rbuf.buffer[i] = 0;
00163   }
00164   while (usart_init(&usart_instance, EXT1_UART_MODULE, &config_usart) != STATUS_OK);
00165   usart_enable(&usart_instance);
00166 }
00167 
00168 /****************************************************************/
00169 
00170 /* Stub implementation of serial transport layer routines. */
00171 static TMR_Status
00172 s_open(TMR_SR_SerialTransport *this)
00173 {
00174   /* This routine should open the serial connection */
00175   if(s_open_flag)
00176   {
00177         system_init();
00178         configure_usart();
00179         /* Enable the RX Complete Interrupt */
00180         usart_instance.hw->USART.INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
00181         system_interrupt_enable_global();
00182   }
00183   s_open_flag=0;
00184   return TMR_SUCCESS;
00185 }
00186 
00187 static TMR_Status
00188 s_sendBytes(TMR_SR_SerialTransport *this, uint32_t length,
00189 uint8_t* message, const uint32_t timeoutMs)
00190 {
00191   /* This routine should send length bytes, pointed to by message on
00192   * the serial connection. If the transmission does not complete in
00193   * timeoutMs milliseconds, it should return TMR_ERROR_TIMEOUT.
00194   */
00195   uint32_t i = 0;
00196   for (i = 0; i<length; i++)
00197   {
00198         usart_serial_putchar(&usart_instance, message[i]);
00199   }
00200   return TMR_SUCCESS;
00201 }
00202 
00203 static TMR_Status
00204 s_receiveBytes(TMR_SR_SerialTransport *this, uint32_t length,
00205 uint32_t* messageLength, uint8_t* message, const uint32_t timeoutMs)
00206 {
00207   /* This routine should receive exactly length bytes on the serial
00208   * connection and store them into the memory pointed to by
00209   * message. If the required number of bytes are note received in
00210   * timeoutMs milliseconds, it should return TMR_ERROR_TIMEOUT.
00211   */
00212   uint32_t index = 0;
00213 
00214   while (index < length )
00215   {
00216     uint32_t next;
00217     /*If no data in circular buffer then wait for data*/
00218         while ((rbuf.head == rbuf.tail));
00219     if (rbuf.head != rbuf.tail)
00220     {   
00221           message[index] = rbuf.buffer[rbuf.tail];
00222       next = rbuf.tail + 1;
00223           next &= (MAX_RX_BUFFER_LENGTH-1);
00224           rbuf.tail = next;
00225     }   
00226         index++;
00227   }
00228   return TMR_SUCCESS;
00229 }
00230 
00231 static TMR_Status
00232 s_setBaudRate(TMR_SR_SerialTransport *this, uint32_t rate)
00233 {
00234   /* This routine should change the baud rate of the serial connection
00235   * to the specified rate, or return TMR_ERROR_INVALID if the rate is
00236   * not supported.
00237   */
00238   usart_disable(&usart_instance);
00239   usart_get_config_defaults(&config_usart);
00240   config_usart.baudrate    = rate;
00241   config_usart.mux_setting = EXT1_UART_SERCOM_MUX_SETTING;
00242   config_usart.pinmux_pad0 = EXT1_UART_SERCOM_PINMUX_PAD0;
00243   config_usart.pinmux_pad1 = EXT1_UART_SERCOM_PINMUX_PAD1;
00244   config_usart.pinmux_pad2 = EXT1_UART_SERCOM_PINMUX_PAD2;
00245   config_usart.pinmux_pad3 = EXT1_UART_SERCOM_PINMUX_PAD3;
00246   
00247   while (usart_init(&usart_instance, EXT1_UART_MODULE, &config_usart) != STATUS_OK);
00248   usart_enable(&usart_instance);
00249         
00250   return TMR_SUCCESS;
00251 }
00252 
00253 static TMR_Status
00254 s_shutdown(TMR_SR_SerialTransport *this)
00255 {
00256   /* This routine should close the serial connection and release any
00257   * acquired resources.
00258   */
00259   usart_disable(&usart_instance);
00260   return TMR_SUCCESS;
00261 }
00262 
00263 static TMR_Status
00264 s_flush(TMR_SR_SerialTransport *this)
00265 {
00266   /* This routine should empty any input or output buffers in the
00267   * communication channel. If there are no such buffers, it may do
00268   * nothing.
00269   */
00270   return TMR_SUCCESS;
00271 }
00272 
00280 TMR_Status
00281 TMR_SR_SerialTransportNativeInit(TMR_SR_SerialTransport *transport,
00282 TMR_SR_SerialPortNativeContext *context,
00283 const char *device)
00284 {
00285   /* Each of the callback functions will be passed the transport
00286   * pointer, and they can use the "cookie" member of the transport
00287   * structure to store the information specific to the transport,
00288   * such as a file handle or the memory address of the FIFO.
00289   */
00290   transport->cookie = context;
00291   transport->open = s_open;
00292   transport->sendBytes = s_sendBytes;
00293   transport->receiveBytes = s_receiveBytes;
00294   transport->setBaudRate = s_setBaudRate;
00295   transport->shutdown = s_shutdown;
00296   transport->flush = s_flush;
00297 
00298   #if TMR_MAX_SERIAL_DEVICE_NAME_LENGTH > 0
00299   if (strlen(device) + 1 > TMR_MAX_SERIAL_DEVICE_NAME_LENGTH)
00300   {
00301     return TMR_ERROR_INVALID;
00302   }
00303   strcpy(context->devicename, device);
00304   return TMR_SUCCESS;
00305   #else
00306   /* No space to store the device name, so open it now */
00307   return s_open(transport);
00308   #endif
00309 }


thingmagic_rfid
Author(s): Brian Bingham
autogenerated on Thu May 16 2019 03:01:24