Go to the documentation of this file.00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "tm_reader.h"
00032 #include <asf.h>
00033 #include <stdio.h>
00034
00035
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
00041
00042 typedef struct buf_st {
00043 volatile uint32_t head;
00044 uint32_t tail;
00045 volatile char buffer [MAX_RX_BUFFER_LENGTH];
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
00065 uint16_t interrupt_status;
00066 uint8_t receiveByte;
00067 uint8_t error_code;
00068
00069
00070 struct usart_module *module = &usart_instance;
00071
00072
00073 SercomUsart *const usart_hw = &(usart_instance.hw->USART);
00074
00075
00076 _usart_wait_for_sync(module);
00077
00078
00079 interrupt_status = usart_hw->INTFLAG.reg;
00080 interrupt_status &= usart_hw->INTENSET.reg;
00081
00082
00083 usart_hw->INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
00084
00085
00086 if(interrupt_status & SERCOM_USART_INTFLAG_RXC)
00087 {
00088
00089 error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
00090
00091
00092 if (error_code)
00093 {
00094
00095 if (error_code & SERCOM_USART_STATUS_FERR)
00096 {
00097
00098 usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;
00099 }
00100 if (error_code & SERCOM_USART_STATUS_BUFOVF)
00101 {
00102
00103 usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;
00104 }
00105 if (error_code & SERCOM_USART_STATUS_PERR)
00106 {
00107
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
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
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
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
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
00171 static TMR_Status
00172 s_open(TMR_SR_SerialTransport *this)
00173 {
00174
00175 if(s_open_flag)
00176 {
00177 system_init();
00178 configure_usart();
00179
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
00192
00193
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
00208
00209
00210
00211
00212 uint32_t index = 0;
00213
00214 while (index < length )
00215 {
00216 uint32_t next;
00217
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
00235
00236
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
00257
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
00267
00268
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
00286
00287
00288
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
00307 return s_open(transport);
00308 #endif
00309 }