Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2006-2015 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 5 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16 #include <string.h>
kadonotakashi 0:8fdf9a60065b 17 #include "mbed_assert.h"
kadonotakashi 0:8fdf9a60065b 18 #include "cmsis.h"
kadonotakashi 0:8fdf9a60065b 19 #include "serial_api.h"
kadonotakashi 0:8fdf9a60065b 20 #include "pinmap.h"
kadonotakashi 0:8fdf9a60065b 21 #include "PeripheralPins.h"
kadonotakashi 0:8fdf9a60065b 22 #include "usart.h"
kadonotakashi 0:8fdf9a60065b 23 #include "pinmap_function.h"
kadonotakashi 0:8fdf9a60065b 24
kadonotakashi 0:8fdf9a60065b 25 #define USART_TX_INDEX 0
kadonotakashi 0:8fdf9a60065b 26 #define USART_RX_INDEX 1
kadonotakashi 0:8fdf9a60065b 27 #define USART_RXFLOW_INDEX 2
kadonotakashi 0:8fdf9a60065b 28 #define USART_TXFLOW_INDEX 3
kadonotakashi 0:8fdf9a60065b 29
kadonotakashi 0:8fdf9a60065b 30
kadonotakashi 0:8fdf9a60065b 31 #if DEVICE_SERIAL_ASYNCH
kadonotakashi 0:8fdf9a60065b 32 #define pUSART_S(obj) obj->serial.usart
kadonotakashi 0:8fdf9a60065b 33 #define pSERIAL_S(obj) ((struct serial_s*)&(obj->serial))
kadonotakashi 0:8fdf9a60065b 34 #else
kadonotakashi 0:8fdf9a60065b 35 #define pUSART_S(obj) obj->usart
kadonotakashi 0:8fdf9a60065b 36 #define pSERIAL_S(obj) ((struct serial_s*)obj)
kadonotakashi 0:8fdf9a60065b 37 #endif
kadonotakashi 0:8fdf9a60065b 38 #define _USART(obj) pUSART_S(obj)->USART
kadonotakashi 0:8fdf9a60065b 39 #define USART_NUM 6
kadonotakashi 0:8fdf9a60065b 40 #define SUPPRESS_WARNING(a) (void)a
kadonotakashi 0:8fdf9a60065b 41
kadonotakashi 0:8fdf9a60065b 42 uint8_t serial_get_index(serial_t *obj);
kadonotakashi 0:8fdf9a60065b 43 IRQn_Type get_serial_irq_num (serial_t *obj);
kadonotakashi 0:8fdf9a60065b 44 uint32_t get_serial_vector (serial_t *obj);
kadonotakashi 0:8fdf9a60065b 45 void uart0_irq(void);
kadonotakashi 0:8fdf9a60065b 46 void uart1_irq(void);
kadonotakashi 0:8fdf9a60065b 47 void uart2_irq(void);
kadonotakashi 0:8fdf9a60065b 48 void uart3_irq(void);
kadonotakashi 0:8fdf9a60065b 49 void uart4_irq(void);
kadonotakashi 0:8fdf9a60065b 50 void uart5_irq(void);
kadonotakashi 0:8fdf9a60065b 51
kadonotakashi 0:8fdf9a60065b 52 static uint32_t serial_irq_ids[USART_NUM] = {0};
kadonotakashi 0:8fdf9a60065b 53 static uart_irq_handler irq_handler;
kadonotakashi 0:8fdf9a60065b 54
kadonotakashi 0:8fdf9a60065b 55 int stdio_uart_inited = 0;
kadonotakashi 0:8fdf9a60065b 56 serial_t stdio_uart;
kadonotakashi 0:8fdf9a60065b 57
kadonotakashi 0:8fdf9a60065b 58 extern uint8_t g_sys_init;
kadonotakashi 0:8fdf9a60065b 59
kadonotakashi 0:8fdf9a60065b 60 static inline void usart_syncing(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 61 {
kadonotakashi 0:8fdf9a60065b 62 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 63 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 64 #ifdef FEATURE_USART_SYNC_SCHEME_V2
kadonotakashi 0:8fdf9a60065b 65 while(_USART(obj).SYNCBUSY.reg);
kadonotakashi 0:8fdf9a60065b 66 #else
kadonotakashi 0:8fdf9a60065b 67 while(_USART(obj).SYNCBUSY.reg & SERCOM_USART_STATUS_SYNCBUSY);
kadonotakashi 0:8fdf9a60065b 68 #endif
kadonotakashi 0:8fdf9a60065b 69 }
kadonotakashi 0:8fdf9a60065b 70
kadonotakashi 0:8fdf9a60065b 71 static inline void enable_usart(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 72 {
kadonotakashi 0:8fdf9a60065b 73 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 74 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 75
kadonotakashi 0:8fdf9a60065b 76 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 77 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 78
kadonotakashi 0:8fdf9a60065b 79 /* Enable USART module */
kadonotakashi 0:8fdf9a60065b 80 _USART(obj).CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
kadonotakashi 0:8fdf9a60065b 81 }
kadonotakashi 0:8fdf9a60065b 82
kadonotakashi 0:8fdf9a60065b 83 static inline void disable_usart(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 84 {
kadonotakashi 0:8fdf9a60065b 85 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 86 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 87
kadonotakashi 0:8fdf9a60065b 88 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 89 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 90
kadonotakashi 0:8fdf9a60065b 91 /* Disable USART module */
kadonotakashi 0:8fdf9a60065b 92 _USART(obj).CTRLA.reg &= ~SERCOM_USART_CTRLA_ENABLE;
kadonotakashi 0:8fdf9a60065b 93 }
kadonotakashi 0:8fdf9a60065b 94
kadonotakashi 0:8fdf9a60065b 95 static inline void reset_usart(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 96 {
kadonotakashi 0:8fdf9a60065b 97 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 98 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 99
kadonotakashi 0:8fdf9a60065b 100 disable_usart(obj);
kadonotakashi 0:8fdf9a60065b 101
kadonotakashi 0:8fdf9a60065b 102 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 103 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 104
kadonotakashi 0:8fdf9a60065b 105 /* Reset module */
kadonotakashi 0:8fdf9a60065b 106 _USART(obj).CTRLA.reg = SERCOM_USART_CTRLA_SWRST;
kadonotakashi 0:8fdf9a60065b 107 SUPPRESS_WARNING(reset_usart);
kadonotakashi 0:8fdf9a60065b 108 }
kadonotakashi 0:8fdf9a60065b 109
kadonotakashi 0:8fdf9a60065b 110 uint32_t serial_find_mux_settings (serial_t *obj)
kadonotakashi 0:8fdf9a60065b 111 {
kadonotakashi 0:8fdf9a60065b 112 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 113 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 114 uint32_t mux_setting = 0;
kadonotakashi 0:8fdf9a60065b 115 uint32_t pinpad[4] = {0};
kadonotakashi 0:8fdf9a60065b 116 uint8_t i = 0;
kadonotakashi 0:8fdf9a60065b 117 uint32_t sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[0], pSERIAL_S(obj)->pins[1]);
kadonotakashi 0:8fdf9a60065b 118
kadonotakashi 0:8fdf9a60065b 119 for (i = 0; i < 4 ; i++) {
kadonotakashi 0:8fdf9a60065b 120 pinpad[i] = pinmap_pad_sercom(pSERIAL_S(obj)->pins[i], sercom_index);
kadonotakashi 0:8fdf9a60065b 121 }
kadonotakashi 0:8fdf9a60065b 122
kadonotakashi 0:8fdf9a60065b 123 switch(pinpad[USART_RX_INDEX]) {
kadonotakashi 0:8fdf9a60065b 124 case 0:
kadonotakashi 0:8fdf9a60065b 125 mux_setting |= SERCOM_USART_CTRLA_RXPO(0);
kadonotakashi 0:8fdf9a60065b 126 break;
kadonotakashi 0:8fdf9a60065b 127 case 1:
kadonotakashi 0:8fdf9a60065b 128 mux_setting |= SERCOM_USART_CTRLA_RXPO(1);
kadonotakashi 0:8fdf9a60065b 129 break;
kadonotakashi 0:8fdf9a60065b 130 case 2:
kadonotakashi 0:8fdf9a60065b 131 mux_setting |= SERCOM_USART_CTRLA_RXPO(2);
kadonotakashi 0:8fdf9a60065b 132 break;
kadonotakashi 0:8fdf9a60065b 133 case 3:
kadonotakashi 0:8fdf9a60065b 134 mux_setting |= SERCOM_USART_CTRLA_RXPO(3);
kadonotakashi 0:8fdf9a60065b 135 break;
kadonotakashi 0:8fdf9a60065b 136 }
kadonotakashi 0:8fdf9a60065b 137
kadonotakashi 0:8fdf9a60065b 138 if ((pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] == NC) && (pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] == NC)) {
kadonotakashi 0:8fdf9a60065b 139 if (pinpad[USART_TX_INDEX] == 0) {
kadonotakashi 0:8fdf9a60065b 140 mux_setting |= SERCOM_USART_CTRLA_TXPO(0);
kadonotakashi 0:8fdf9a60065b 141 } else if(pinpad[USART_TX_INDEX] == 2) {
kadonotakashi 0:8fdf9a60065b 142 mux_setting |= SERCOM_USART_CTRLA_TXPO(1);
kadonotakashi 0:8fdf9a60065b 143 } else {
kadonotakashi 0:8fdf9a60065b 144 }
kadonotakashi 0:8fdf9a60065b 145 } else { // for hardware flow control and uart // expecting the tx in pad 0, rts in pad2 and cts in pad 3
kadonotakashi 0:8fdf9a60065b 146 if((pinpad[USART_TX_INDEX] == 0) && (pinpad[USART_RXFLOW_INDEX]/*rts pin*/ == 2) && (pinpad[USART_TXFLOW_INDEX] /*cts pin*/ == 3)) {
kadonotakashi 0:8fdf9a60065b 147 mux_setting |= SERCOM_USART_CTRLA_TXPO(2);
kadonotakashi 0:8fdf9a60065b 148 }
kadonotakashi 0:8fdf9a60065b 149 }
kadonotakashi 0:8fdf9a60065b 150 return mux_setting;
kadonotakashi 0:8fdf9a60065b 151 }
kadonotakashi 0:8fdf9a60065b 152
kadonotakashi 0:8fdf9a60065b 153 static enum status_code usart_set_config_default(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 154 {
kadonotakashi 0:8fdf9a60065b 155 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 156 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 157 /* Index for generic clock */
kadonotakashi 0:8fdf9a60065b 158 uint32_t sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj));
kadonotakashi 0:8fdf9a60065b 159 uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 160
kadonotakashi 0:8fdf9a60065b 161 /* Cache new register values to minimize the number of register writes */
kadonotakashi 0:8fdf9a60065b 162 uint32_t ctrla = 0;
kadonotakashi 0:8fdf9a60065b 163 uint32_t ctrlb = 0;
kadonotakashi 0:8fdf9a60065b 164 uint16_t baud = 0;
kadonotakashi 0:8fdf9a60065b 165
kadonotakashi 0:8fdf9a60065b 166 enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
kadonotakashi 0:8fdf9a60065b 167 enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
kadonotakashi 0:8fdf9a60065b 168
kadonotakashi 0:8fdf9a60065b 169 /* Set data order, internal muxing, and clock polarity */
kadonotakashi 0:8fdf9a60065b 170 ctrla = (uint32_t)USART_DATAORDER_LSB | // data order
kadonotakashi 0:8fdf9a60065b 171 (uint32_t)pSERIAL_S(obj)->mux_setting; // mux setting // clock polarity is not used
kadonotakashi 0:8fdf9a60065b 172
kadonotakashi 0:8fdf9a60065b 173
kadonotakashi 0:8fdf9a60065b 174 /* Get baud value from mode and clock */
kadonotakashi 0:8fdf9a60065b 175 _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate,system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num); // for asynchronous transfer mode
kadonotakashi 0:8fdf9a60065b 176
kadonotakashi 0:8fdf9a60065b 177 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 178 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 179
kadonotakashi 0:8fdf9a60065b 180 /*Set baud val */
kadonotakashi 0:8fdf9a60065b 181 _USART(obj).BAUD.reg = baud;
kadonotakashi 0:8fdf9a60065b 182
kadonotakashi 0:8fdf9a60065b 183 /* Set sample mode */
kadonotakashi 0:8fdf9a60065b 184 ctrla |= USART_TRANSFER_ASYNCHRONOUSLY;
kadonotakashi 0:8fdf9a60065b 185
kadonotakashi 0:8fdf9a60065b 186 /* for disabled external clock source */
kadonotakashi 0:8fdf9a60065b 187 ctrla |= SERCOM_USART_CTRLA_MODE(0x1);
kadonotakashi 0:8fdf9a60065b 188
kadonotakashi 0:8fdf9a60065b 189 /* Set stopbits, character size and enable transceivers */
kadonotakashi 0:8fdf9a60065b 190 ctrlb = (uint32_t)pSERIAL_S(obj)->stopbits | (uint32_t)pSERIAL_S(obj)->character_size |
kadonotakashi 0:8fdf9a60065b 191 SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN; /*transmitter and receiver enable*/
kadonotakashi 0:8fdf9a60065b 192 if (pSERIAL_S(obj)->pins[USART_RX_INDEX] == NC) { /* if pin is NC, have to disable the corresponding transmitter/receiver part */
kadonotakashi 0:8fdf9a60065b 193 ctrlb &= ~SERCOM_USART_CTRLB_RXEN; /* receiver disable */
kadonotakashi 0:8fdf9a60065b 194 }
kadonotakashi 0:8fdf9a60065b 195 if (pSERIAL_S(obj)->pins[USART_TX_INDEX] == NC) {
kadonotakashi 0:8fdf9a60065b 196 ctrlb &= ~SERCOM_USART_CTRLB_TXEN; /* transmitter disable */
kadonotakashi 0:8fdf9a60065b 197 }
kadonotakashi 0:8fdf9a60065b 198
kadonotakashi 0:8fdf9a60065b 199 /* Check parity mode bits */
kadonotakashi 0:8fdf9a60065b 200 if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) {
kadonotakashi 0:8fdf9a60065b 201 ctrla |= SERCOM_USART_CTRLA_FORM(1);
kadonotakashi 0:8fdf9a60065b 202 ctrlb |= pSERIAL_S(obj)->parity;
kadonotakashi 0:8fdf9a60065b 203 } else {
kadonotakashi 0:8fdf9a60065b 204 ctrla |= SERCOM_USART_CTRLA_FORM(0);
kadonotakashi 0:8fdf9a60065b 205 }
kadonotakashi 0:8fdf9a60065b 206
kadonotakashi 0:8fdf9a60065b 207 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 208 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 209
kadonotakashi 0:8fdf9a60065b 210 /* Write configuration to CTRLB */
kadonotakashi 0:8fdf9a60065b 211 _USART(obj).CTRLB.reg = ctrlb;
kadonotakashi 0:8fdf9a60065b 212
kadonotakashi 0:8fdf9a60065b 213 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 214 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 215
kadonotakashi 0:8fdf9a60065b 216 /* Write configuration to CTRLA */
kadonotakashi 0:8fdf9a60065b 217 _USART(obj).CTRLA.reg = ctrla;
kadonotakashi 0:8fdf9a60065b 218
kadonotakashi 0:8fdf9a60065b 219 return STATUS_OK;
kadonotakashi 0:8fdf9a60065b 220 }
kadonotakashi 0:8fdf9a60065b 221
kadonotakashi 0:8fdf9a60065b 222 void get_default_serial_values(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 223 {
kadonotakashi 0:8fdf9a60065b 224 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 225 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 226 /* Set default config to object */
kadonotakashi 0:8fdf9a60065b 227 pSERIAL_S(obj)->parity = USART_PARITY_NONE;
kadonotakashi 0:8fdf9a60065b 228 pSERIAL_S(obj)->stopbits = USART_STOPBITS_1;
kadonotakashi 0:8fdf9a60065b 229 pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT;
kadonotakashi 0:8fdf9a60065b 230 pSERIAL_S(obj)->baudrate = 9600;
kadonotakashi 0:8fdf9a60065b 231 pSERIAL_S(obj)->mux_setting = USART_RX_1_TX_2_XCK_3;
kadonotakashi 0:8fdf9a60065b 232 };
kadonotakashi 0:8fdf9a60065b 233
kadonotakashi 0:8fdf9a60065b 234 void serial_init(serial_t *obj, PinName tx, PinName rx)
kadonotakashi 0:8fdf9a60065b 235 {
kadonotakashi 0:8fdf9a60065b 236 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 237 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 238 if (g_sys_init == 0) {
kadonotakashi 0:8fdf9a60065b 239 system_init();
kadonotakashi 0:8fdf9a60065b 240 g_sys_init = 1;
kadonotakashi 0:8fdf9a60065b 241 }
kadonotakashi 0:8fdf9a60065b 242 struct system_gclk_chan_config gclk_chan_conf;
kadonotakashi 0:8fdf9a60065b 243 UARTName uart;
kadonotakashi 0:8fdf9a60065b 244 uint32_t gclk_index;
kadonotakashi 0:8fdf9a60065b 245 uint32_t pm_index;
kadonotakashi 0:8fdf9a60065b 246 uint32_t sercom_index = 0;
kadonotakashi 0:8fdf9a60065b 247 uint32_t muxsetting = 0;
kadonotakashi 0:8fdf9a60065b 248
kadonotakashi 0:8fdf9a60065b 249 get_default_serial_values(obj);
kadonotakashi 0:8fdf9a60065b 250
kadonotakashi 0:8fdf9a60065b 251 pSERIAL_S(obj)->pins[USART_TX_INDEX] = tx;
kadonotakashi 0:8fdf9a60065b 252 pSERIAL_S(obj)->pins[USART_RX_INDEX] = rx;
kadonotakashi 0:8fdf9a60065b 253 pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] = NC;
kadonotakashi 0:8fdf9a60065b 254 pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] = NC;
kadonotakashi 0:8fdf9a60065b 255
kadonotakashi 0:8fdf9a60065b 256 muxsetting = serial_find_mux_settings(obj); // getting mux setting from pins
kadonotakashi 0:8fdf9a60065b 257 sercom_index = pinmap_merge_sercom(tx, rx); // same variable sercom_index reused for optimization
kadonotakashi 0:8fdf9a60065b 258 if (sercom_index == (uint32_t)NC) {
kadonotakashi 0:8fdf9a60065b 259 /*expecting a valid value for sercom index*/
kadonotakashi 0:8fdf9a60065b 260 return;
kadonotakashi 0:8fdf9a60065b 261 }
kadonotakashi 0:8fdf9a60065b 262 sercom_index &= 0x0F;
kadonotakashi 0:8fdf9a60065b 263 uart = (UARTName)pinmap_peripheral_sercom(NC, sercom_index);
kadonotakashi 0:8fdf9a60065b 264 pUSART_S(obj) = (Sercom *)uart;
kadonotakashi 0:8fdf9a60065b 265
kadonotakashi 0:8fdf9a60065b 266 /* Disable USART module */
kadonotakashi 0:8fdf9a60065b 267 disable_usart(obj);
kadonotakashi 0:8fdf9a60065b 268
kadonotakashi 0:8fdf9a60065b 269 #if (SAML21) || (SAMC20) || (SAMC21)
kadonotakashi 0:8fdf9a60065b 270 #if (SAML21)
kadonotakashi 0:8fdf9a60065b 271 if (sercom_index == 5) {
kadonotakashi 0:8fdf9a60065b 272 pm_index = MCLK_APBDMASK_SERCOM5_Pos;
kadonotakashi 0:8fdf9a60065b 273 gclk_index = SERCOM5_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 274 } else {
kadonotakashi 0:8fdf9a60065b 275 pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
kadonotakashi 0:8fdf9a60065b 276 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 277 }
kadonotakashi 0:8fdf9a60065b 278 #else
kadonotakashi 0:8fdf9a60065b 279 pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
kadonotakashi 0:8fdf9a60065b 280 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 281 #endif
kadonotakashi 0:8fdf9a60065b 282 #else
kadonotakashi 0:8fdf9a60065b 283 pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
kadonotakashi 0:8fdf9a60065b 284 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 285 #endif
kadonotakashi 0:8fdf9a60065b 286
kadonotakashi 0:8fdf9a60065b 287 if (_USART(obj).CTRLA.reg & SERCOM_USART_CTRLA_SWRST) {
kadonotakashi 0:8fdf9a60065b 288 return; /* The module is busy resetting itself */
kadonotakashi 0:8fdf9a60065b 289 }
kadonotakashi 0:8fdf9a60065b 290
kadonotakashi 0:8fdf9a60065b 291 if (_USART(obj).CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) {
kadonotakashi 0:8fdf9a60065b 292 return; /* Check the module is enabled */
kadonotakashi 0:8fdf9a60065b 293 }
kadonotakashi 0:8fdf9a60065b 294
kadonotakashi 0:8fdf9a60065b 295 /* Turn on module in PM */
kadonotakashi 0:8fdf9a60065b 296 #if (SAML21)
kadonotakashi 0:8fdf9a60065b 297 if (sercom_index == 5) {
kadonotakashi 0:8fdf9a60065b 298 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBD, 1 << pm_index);
kadonotakashi 0:8fdf9a60065b 299 } else {
kadonotakashi 0:8fdf9a60065b 300 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
kadonotakashi 0:8fdf9a60065b 301 }
kadonotakashi 0:8fdf9a60065b 302 #else
kadonotakashi 0:8fdf9a60065b 303 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
kadonotakashi 0:8fdf9a60065b 304 #endif
kadonotakashi 0:8fdf9a60065b 305
kadonotakashi 0:8fdf9a60065b 306 /* Set up the GCLK for the module */
kadonotakashi 0:8fdf9a60065b 307 gclk_chan_conf.source_generator = GCLK_GENERATOR_0;
kadonotakashi 0:8fdf9a60065b 308 system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
kadonotakashi 0:8fdf9a60065b 309 system_gclk_chan_enable(gclk_index);
kadonotakashi 0:8fdf9a60065b 310 sercom_set_gclk_generator(GCLK_GENERATOR_0, false);
kadonotakashi 0:8fdf9a60065b 311
kadonotakashi 0:8fdf9a60065b 312 pSERIAL_S(obj)->mux_setting = muxsetting;
kadonotakashi 0:8fdf9a60065b 313 /* Set configuration according to the config struct */
kadonotakashi 0:8fdf9a60065b 314 usart_set_config_default(obj);
kadonotakashi 0:8fdf9a60065b 315
kadonotakashi 0:8fdf9a60065b 316 struct system_pinmux_config pin_conf;
kadonotakashi 0:8fdf9a60065b 317 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
kadonotakashi 0:8fdf9a60065b 318 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
kadonotakashi 0:8fdf9a60065b 319 pin_conf.powersave = false;
kadonotakashi 0:8fdf9a60065b 320
kadonotakashi 0:8fdf9a60065b 321 /* Configure the SERCOM pins according to the user configuration */
kadonotakashi 0:8fdf9a60065b 322 for (uint8_t pad = 0; pad < 4; pad++) {
kadonotakashi 0:8fdf9a60065b 323 uint32_t current_pin = pSERIAL_S(obj)->pins[pad];
kadonotakashi 0:8fdf9a60065b 324 if (current_pin != (uint32_t)NC) {
kadonotakashi 0:8fdf9a60065b 325 pin_conf.mux_position = pinmap_function_sercom((PinName)current_pin, sercom_index);
kadonotakashi 0:8fdf9a60065b 326 if ((uint8_t)NC != pin_conf.mux_position) {
kadonotakashi 0:8fdf9a60065b 327 system_pinmux_pin_set_config(current_pin, &pin_conf);
kadonotakashi 0:8fdf9a60065b 328 }
kadonotakashi 0:8fdf9a60065b 329 }
kadonotakashi 0:8fdf9a60065b 330 }
kadonotakashi 0:8fdf9a60065b 331
kadonotakashi 0:8fdf9a60065b 332 if (uart == STDIO_UART) {
kadonotakashi 0:8fdf9a60065b 333 stdio_uart_inited = 1;
kadonotakashi 0:8fdf9a60065b 334 memcpy(&stdio_uart, obj, sizeof(serial_t));
kadonotakashi 0:8fdf9a60065b 335 }
kadonotakashi 0:8fdf9a60065b 336 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 337 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 338
kadonotakashi 0:8fdf9a60065b 339 /* Enable USART module */
kadonotakashi 0:8fdf9a60065b 340 enable_usart(obj);
kadonotakashi 0:8fdf9a60065b 341 }
kadonotakashi 0:8fdf9a60065b 342
kadonotakashi 0:8fdf9a60065b 343 void serial_free(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 344 {
kadonotakashi 0:8fdf9a60065b 345 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 346 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 347 struct system_pinmux_config pin_conf;
kadonotakashi 0:8fdf9a60065b 348 serial_irq_ids[serial_get_index(obj)] = 0;
kadonotakashi 0:8fdf9a60065b 349 disable_usart(obj);
kadonotakashi 0:8fdf9a60065b 350
kadonotakashi 0:8fdf9a60065b 351 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
kadonotakashi 0:8fdf9a60065b 352 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
kadonotakashi 0:8fdf9a60065b 353 pin_conf.powersave = false;
kadonotakashi 0:8fdf9a60065b 354 pin_conf.mux_position = SYSTEM_PINMUX_GPIO;
kadonotakashi 0:8fdf9a60065b 355 /* Configure the SERCOM pins according to the user configuration */
kadonotakashi 0:8fdf9a60065b 356 for (uint8_t pad = 0; pad < 4; pad++) {
kadonotakashi 0:8fdf9a60065b 357 uint32_t current_pin = pSERIAL_S(obj)->pins[pad];
kadonotakashi 0:8fdf9a60065b 358 if (current_pin != (uint32_t)NC) {
kadonotakashi 0:8fdf9a60065b 359 system_pinmux_pin_set_config(current_pin, &pin_conf);
kadonotakashi 0:8fdf9a60065b 360 }
kadonotakashi 0:8fdf9a60065b 361 }
kadonotakashi 0:8fdf9a60065b 362 }
kadonotakashi 0:8fdf9a60065b 363
kadonotakashi 0:8fdf9a60065b 364 void serial_baud(serial_t *obj, int baudrate)
kadonotakashi 0:8fdf9a60065b 365 {
kadonotakashi 0:8fdf9a60065b 366 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 367 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 368 MBED_ASSERT((baudrate == 110) || (baudrate == 150) || (baudrate == 300) || (baudrate == 1200) ||
kadonotakashi 0:8fdf9a60065b 369 (baudrate == 2400) || (baudrate == 4800) || (baudrate == 9600) || (baudrate == 19200) || (baudrate == 38400) ||
kadonotakashi 0:8fdf9a60065b 370 (baudrate == 57600) || (baudrate == 115200) || (baudrate == 230400) || (baudrate == 460800) || (baudrate == 921600) );
kadonotakashi 0:8fdf9a60065b 371
kadonotakashi 0:8fdf9a60065b 372 struct system_gclk_chan_config gclk_chan_conf;
kadonotakashi 0:8fdf9a60065b 373 uint32_t gclk_index;
kadonotakashi 0:8fdf9a60065b 374 uint16_t baud = 0;
kadonotakashi 0:8fdf9a60065b 375 uint32_t sercom_index = 0;
kadonotakashi 0:8fdf9a60065b 376 enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
kadonotakashi 0:8fdf9a60065b 377 enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
kadonotakashi 0:8fdf9a60065b 378
kadonotakashi 0:8fdf9a60065b 379 pSERIAL_S(obj)->baudrate = baudrate;
kadonotakashi 0:8fdf9a60065b 380 disable_usart(obj);
kadonotakashi 0:8fdf9a60065b 381
kadonotakashi 0:8fdf9a60065b 382 sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj));
kadonotakashi 0:8fdf9a60065b 383 #if (SAML21) || (SAMC20) || (SAMC21)
kadonotakashi 0:8fdf9a60065b 384 #if (SAML21)
kadonotakashi 0:8fdf9a60065b 385 if (sercom_index == 5) {
kadonotakashi 0:8fdf9a60065b 386 gclk_index = SERCOM5_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 387 } else {
kadonotakashi 0:8fdf9a60065b 388 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 389 }
kadonotakashi 0:8fdf9a60065b 390 #else
kadonotakashi 0:8fdf9a60065b 391 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 392 #endif
kadonotakashi 0:8fdf9a60065b 393 #else
kadonotakashi 0:8fdf9a60065b 394 gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
kadonotakashi 0:8fdf9a60065b 395 #endif
kadonotakashi 0:8fdf9a60065b 396 gclk_chan_conf.source_generator = GCLK_GENERATOR_0;
kadonotakashi 0:8fdf9a60065b 397 system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
kadonotakashi 0:8fdf9a60065b 398 system_gclk_chan_enable(gclk_index);
kadonotakashi 0:8fdf9a60065b 399 sercom_set_gclk_generator(GCLK_GENERATOR_0, false);
kadonotakashi 0:8fdf9a60065b 400
kadonotakashi 0:8fdf9a60065b 401 /* Get baud value from mode and clock */
kadonotakashi 0:8fdf9a60065b 402 _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate, system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);
kadonotakashi 0:8fdf9a60065b 403
kadonotakashi 0:8fdf9a60065b 404 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 405 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 406
kadonotakashi 0:8fdf9a60065b 407 /*Set baud val */
kadonotakashi 0:8fdf9a60065b 408 _USART(obj).BAUD.reg = baud;
kadonotakashi 0:8fdf9a60065b 409 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 410 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 411
kadonotakashi 0:8fdf9a60065b 412 enable_usart(obj);
kadonotakashi 0:8fdf9a60065b 413 }
kadonotakashi 0:8fdf9a60065b 414
kadonotakashi 0:8fdf9a60065b 415 void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
kadonotakashi 0:8fdf9a60065b 416 {
kadonotakashi 0:8fdf9a60065b 417 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 418 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 419 MBED_ASSERT((stop_bits == 1) || (stop_bits == 2));
kadonotakashi 0:8fdf9a60065b 420 MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven));
kadonotakashi 0:8fdf9a60065b 421 MBED_ASSERT((data_bits == 5) || (data_bits == 6) || (data_bits == 7) || (data_bits == 8) /*|| (data_bits == 9)*/);
kadonotakashi 0:8fdf9a60065b 422
kadonotakashi 0:8fdf9a60065b 423 /* Cache new register values to minimize the number of register writes */
kadonotakashi 0:8fdf9a60065b 424 uint32_t ctrla = 0;
kadonotakashi 0:8fdf9a60065b 425 uint32_t ctrlb = 0;
kadonotakashi 0:8fdf9a60065b 426
kadonotakashi 0:8fdf9a60065b 427 disable_usart(obj);
kadonotakashi 0:8fdf9a60065b 428
kadonotakashi 0:8fdf9a60065b 429 ctrla = _USART(obj).CTRLA.reg;
kadonotakashi 0:8fdf9a60065b 430 ctrlb = _USART(obj).CTRLB.reg;
kadonotakashi 0:8fdf9a60065b 431
kadonotakashi 0:8fdf9a60065b 432 ctrla &= ~(SERCOM_USART_CTRLA_FORM_Msk);
kadonotakashi 0:8fdf9a60065b 433 ctrlb &= ~(SERCOM_USART_CTRLB_CHSIZE_Msk);
kadonotakashi 0:8fdf9a60065b 434 ctrlb &= ~(SERCOM_USART_CTRLB_SBMODE);
kadonotakashi 0:8fdf9a60065b 435 ctrlb &= ~(SERCOM_USART_CTRLB_PMODE);
kadonotakashi 0:8fdf9a60065b 436
kadonotakashi 0:8fdf9a60065b 437 switch (stop_bits) {
kadonotakashi 0:8fdf9a60065b 438 case 1:
kadonotakashi 0:8fdf9a60065b 439 pSERIAL_S(obj)->stopbits = USART_STOPBITS_1;
kadonotakashi 0:8fdf9a60065b 440 break;
kadonotakashi 0:8fdf9a60065b 441 case 2:
kadonotakashi 0:8fdf9a60065b 442 pSERIAL_S(obj)->stopbits = USART_STOPBITS_2;
kadonotakashi 0:8fdf9a60065b 443 break;
kadonotakashi 0:8fdf9a60065b 444 default:
kadonotakashi 0:8fdf9a60065b 445 pSERIAL_S(obj)->stopbits = USART_STOPBITS_1;
kadonotakashi 0:8fdf9a60065b 446 }
kadonotakashi 0:8fdf9a60065b 447
kadonotakashi 0:8fdf9a60065b 448 switch (parity) {
kadonotakashi 0:8fdf9a60065b 449 case ParityNone:
kadonotakashi 0:8fdf9a60065b 450 pSERIAL_S(obj)->parity = USART_PARITY_NONE;
kadonotakashi 0:8fdf9a60065b 451 break;
kadonotakashi 0:8fdf9a60065b 452 case ParityOdd:
kadonotakashi 0:8fdf9a60065b 453 pSERIAL_S(obj)->parity = USART_PARITY_ODD;
kadonotakashi 0:8fdf9a60065b 454 break;
kadonotakashi 0:8fdf9a60065b 455 case ParityEven:
kadonotakashi 0:8fdf9a60065b 456 pSERIAL_S(obj)->parity = USART_PARITY_EVEN;
kadonotakashi 0:8fdf9a60065b 457 break;
kadonotakashi 0:8fdf9a60065b 458 default:
kadonotakashi 0:8fdf9a60065b 459 pSERIAL_S(obj)->parity = USART_PARITY_NONE;
kadonotakashi 0:8fdf9a60065b 460 }
kadonotakashi 0:8fdf9a60065b 461
kadonotakashi 0:8fdf9a60065b 462 switch (data_bits) {
kadonotakashi 0:8fdf9a60065b 463 case 5:
kadonotakashi 0:8fdf9a60065b 464 pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_5BIT;
kadonotakashi 0:8fdf9a60065b 465 break;
kadonotakashi 0:8fdf9a60065b 466 case 6:
kadonotakashi 0:8fdf9a60065b 467 pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_6BIT;
kadonotakashi 0:8fdf9a60065b 468 break;
kadonotakashi 0:8fdf9a60065b 469 case 7:
kadonotakashi 0:8fdf9a60065b 470 pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_7BIT;
kadonotakashi 0:8fdf9a60065b 471 break;
kadonotakashi 0:8fdf9a60065b 472 case 8:
kadonotakashi 0:8fdf9a60065b 473 pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT;
kadonotakashi 0:8fdf9a60065b 474 break; // 9 bit transfer not required in mbed
kadonotakashi 0:8fdf9a60065b 475 default:
kadonotakashi 0:8fdf9a60065b 476 pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT;
kadonotakashi 0:8fdf9a60065b 477 }
kadonotakashi 0:8fdf9a60065b 478
kadonotakashi 0:8fdf9a60065b 479
kadonotakashi 0:8fdf9a60065b 480 /* Set stopbits, character size and enable transceivers */
kadonotakashi 0:8fdf9a60065b 481 ctrlb |= (pSERIAL_S(obj)->stopbits | pSERIAL_S(obj)->character_size);
kadonotakashi 0:8fdf9a60065b 482
kadonotakashi 0:8fdf9a60065b 483 /* Check parity mode bits */
kadonotakashi 0:8fdf9a60065b 484 if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) {
kadonotakashi 0:8fdf9a60065b 485 ctrla |= SERCOM_USART_CTRLA_FORM(1);
kadonotakashi 0:8fdf9a60065b 486 ctrlb |= pSERIAL_S(obj)->parity;
kadonotakashi 0:8fdf9a60065b 487 } else {
kadonotakashi 0:8fdf9a60065b 488 ctrla |= SERCOM_USART_CTRLA_FORM(0);
kadonotakashi 0:8fdf9a60065b 489 }
kadonotakashi 0:8fdf9a60065b 490
kadonotakashi 0:8fdf9a60065b 491 /* Write configuration to CTRLB */
kadonotakashi 0:8fdf9a60065b 492 _USART(obj).CTRLB.reg = ctrlb;
kadonotakashi 0:8fdf9a60065b 493
kadonotakashi 0:8fdf9a60065b 494 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 495 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 496
kadonotakashi 0:8fdf9a60065b 497 /* Write configuration to CTRLA */
kadonotakashi 0:8fdf9a60065b 498 _USART(obj).CTRLA.reg = ctrla;
kadonotakashi 0:8fdf9a60065b 499
kadonotakashi 0:8fdf9a60065b 500 /* Wait until synchronization is complete */
kadonotakashi 0:8fdf9a60065b 501 usart_syncing(obj);
kadonotakashi 0:8fdf9a60065b 502
kadonotakashi 0:8fdf9a60065b 503 enable_usart(obj);
kadonotakashi 0:8fdf9a60065b 504 }
kadonotakashi 0:8fdf9a60065b 505
kadonotakashi 0:8fdf9a60065b 506 #ifdef DEVICE_SERIAL_FC
kadonotakashi 0:8fdf9a60065b 507
kadonotakashi 0:8fdf9a60065b 508 void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
kadonotakashi 0:8fdf9a60065b 509 {
kadonotakashi 0:8fdf9a60065b 510 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 511 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 512 uint32_t muxsetting = 0;
kadonotakashi 0:8fdf9a60065b 513 uint32_t sercom_index = 0;
kadonotakashi 0:8fdf9a60065b 514
kadonotakashi 0:8fdf9a60065b 515 pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] = rxflow;
kadonotakashi 0:8fdf9a60065b 516 pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] = txflow;
kadonotakashi 0:8fdf9a60065b 517 muxsetting = serial_find_mux_settings(obj); // getting mux setting from pins
kadonotakashi 0:8fdf9a60065b 518 sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], pSERIAL_S(obj)->pins[USART_RX_INDEX]); // same variable sercom_index reused for optimization
kadonotakashi 0:8fdf9a60065b 519 if (sercom_index == (uint32_t)NC) {
kadonotakashi 0:8fdf9a60065b 520 /*expecting a valid value for sercom index*/
kadonotakashi 0:8fdf9a60065b 521 return;
kadonotakashi 0:8fdf9a60065b 522 }
kadonotakashi 0:8fdf9a60065b 523
kadonotakashi 0:8fdf9a60065b 524 disable_usart(obj);
kadonotakashi 0:8fdf9a60065b 525
kadonotakashi 0:8fdf9a60065b 526 /* Set configuration according to the config struct */
kadonotakashi 0:8fdf9a60065b 527 pSERIAL_S(obj)->mux_setting = muxsetting; // mux setting to be changed for configuring hardware control
kadonotakashi 0:8fdf9a60065b 528 usart_set_config_default(obj);
kadonotakashi 0:8fdf9a60065b 529
kadonotakashi 0:8fdf9a60065b 530 struct system_pinmux_config pin_conf;
kadonotakashi 0:8fdf9a60065b 531 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
kadonotakashi 0:8fdf9a60065b 532 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
kadonotakashi 0:8fdf9a60065b 533 pin_conf.powersave = false;
kadonotakashi 0:8fdf9a60065b 534
kadonotakashi 0:8fdf9a60065b 535 for (uint8_t pad = 0; pad < 2; pad++) { // setting for rx and tx
kadonotakashi 0:8fdf9a60065b 536 uint32_t current_pin = pSERIAL_S(obj)->pins[pad];
kadonotakashi 0:8fdf9a60065b 537 if (current_pin != (uint32_t)NC) {
kadonotakashi 0:8fdf9a60065b 538 pin_conf.mux_position = pinmap_function_sercom((PinName)current_pin, sercom_index);
kadonotakashi 0:8fdf9a60065b 539 if ((uint8_t)NC != pin_conf.mux_position) {
kadonotakashi 0:8fdf9a60065b 540 system_pinmux_pin_set_config(current_pin, &pin_conf);
kadonotakashi 0:8fdf9a60065b 541 }
kadonotakashi 0:8fdf9a60065b 542 }
kadonotakashi 0:8fdf9a60065b 543 }
kadonotakashi 0:8fdf9a60065b 544 if((FlowControlRTS == type) || (FlowControlRTSCTS== type)) {
kadonotakashi 0:8fdf9a60065b 545 if (pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] != NC) {
kadonotakashi 0:8fdf9a60065b 546 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT; // setting for rxflow
kadonotakashi 0:8fdf9a60065b 547 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
kadonotakashi 0:8fdf9a60065b 548 pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] , sercom_index);
kadonotakashi 0:8fdf9a60065b 549 if ((uint8_t)NC != pin_conf.mux_position) {
kadonotakashi 0:8fdf9a60065b 550 system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX], &pin_conf);
kadonotakashi 0:8fdf9a60065b 551 }
kadonotakashi 0:8fdf9a60065b 552 }
kadonotakashi 0:8fdf9a60065b 553 }
kadonotakashi 0:8fdf9a60065b 554 if((FlowControlCTS == type) || (FlowControlRTSCTS== type)) {
kadonotakashi 0:8fdf9a60065b 555 if (pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] != NC) {
kadonotakashi 0:8fdf9a60065b 556 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; // setting for txflow
kadonotakashi 0:8fdf9a60065b 557 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
kadonotakashi 0:8fdf9a60065b 558 pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] , sercom_index);
kadonotakashi 0:8fdf9a60065b 559 if ((uint8_t)NC != pin_conf.mux_position) {
kadonotakashi 0:8fdf9a60065b 560 system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX], &pin_conf);
kadonotakashi 0:8fdf9a60065b 561 }
kadonotakashi 0:8fdf9a60065b 562 }
kadonotakashi 0:8fdf9a60065b 563 }
kadonotakashi 0:8fdf9a60065b 564 enable_usart(obj);
kadonotakashi 0:8fdf9a60065b 565 }
kadonotakashi 0:8fdf9a60065b 566
kadonotakashi 0:8fdf9a60065b 567 #endif //DEVICE_SERIAL_FC
kadonotakashi 0:8fdf9a60065b 568
kadonotakashi 0:8fdf9a60065b 569 void serial_break_set(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 570 {
kadonotakashi 0:8fdf9a60065b 571 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 572 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 573 struct system_pinmux_config pin_conf;
kadonotakashi 0:8fdf9a60065b 574 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT;
kadonotakashi 0:8fdf9a60065b 575 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
kadonotakashi 0:8fdf9a60065b 576 pin_conf.mux_position = SYSTEM_PINMUX_GPIO;
kadonotakashi 0:8fdf9a60065b 577 pin_conf.powersave = false;
kadonotakashi 0:8fdf9a60065b 578
kadonotakashi 0:8fdf9a60065b 579 if (pSERIAL_S(obj)->pins[USART_TX_INDEX] != NC) {
kadonotakashi 0:8fdf9a60065b 580 system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TX_INDEX], &pin_conf);
kadonotakashi 0:8fdf9a60065b 581 }
kadonotakashi 0:8fdf9a60065b 582 }
kadonotakashi 0:8fdf9a60065b 583
kadonotakashi 0:8fdf9a60065b 584 void serial_break_clear(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 585 {
kadonotakashi 0:8fdf9a60065b 586 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 587 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 588 uint32_t sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], pSERIAL_S(obj)->pins[USART_RX_INDEX]);
kadonotakashi 0:8fdf9a60065b 589
kadonotakashi 0:8fdf9a60065b 590 struct system_pinmux_config pin_conf;
kadonotakashi 0:8fdf9a60065b 591 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
kadonotakashi 0:8fdf9a60065b 592 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
kadonotakashi 0:8fdf9a60065b 593 pin_conf.powersave = false;
kadonotakashi 0:8fdf9a60065b 594
kadonotakashi 0:8fdf9a60065b 595 if (pSERIAL_S(obj)->pins[USART_TX_INDEX] != NC) {
kadonotakashi 0:8fdf9a60065b 596 pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], sercom_index);
kadonotakashi 0:8fdf9a60065b 597 if ((uint8_t)NC != pin_conf.mux_position) {
kadonotakashi 0:8fdf9a60065b 598 system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TX_INDEX], &pin_conf);
kadonotakashi 0:8fdf9a60065b 599 }
kadonotakashi 0:8fdf9a60065b 600 }
kadonotakashi 0:8fdf9a60065b 601 }
kadonotakashi 0:8fdf9a60065b 602
kadonotakashi 0:8fdf9a60065b 603 void serial_pinout_tx(PinName tx)
kadonotakashi 0:8fdf9a60065b 604 {
kadonotakashi 0:8fdf9a60065b 605 pinmap_pinout(tx, PinMap_SERCOM_PAD);
kadonotakashi 0:8fdf9a60065b 606 }
kadonotakashi 0:8fdf9a60065b 607
kadonotakashi 0:8fdf9a60065b 608 /******************************************************************************
kadonotakashi 0:8fdf9a60065b 609 * INTERRUPTS HANDLING
kadonotakashi 0:8fdf9a60065b 610 ******************************************************************************/
kadonotakashi 0:8fdf9a60065b 611 inline uint8_t serial_get_index(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 612 {
kadonotakashi 0:8fdf9a60065b 613 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 614 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 615 switch ((int)pUSART_S(obj)) {
kadonotakashi 0:8fdf9a60065b 616 case UART_0:
kadonotakashi 0:8fdf9a60065b 617 return 0;
kadonotakashi 0:8fdf9a60065b 618 case UART_1:
kadonotakashi 0:8fdf9a60065b 619 return 1;
kadonotakashi 0:8fdf9a60065b 620 case UART_2:
kadonotakashi 0:8fdf9a60065b 621 return 2;
kadonotakashi 0:8fdf9a60065b 622 case UART_3:
kadonotakashi 0:8fdf9a60065b 623 return 3;
kadonotakashi 0:8fdf9a60065b 624 case UART_4:
kadonotakashi 0:8fdf9a60065b 625 return 4;
kadonotakashi 0:8fdf9a60065b 626 case UART_5:
kadonotakashi 0:8fdf9a60065b 627 return 5;
kadonotakashi 0:8fdf9a60065b 628 }
kadonotakashi 0:8fdf9a60065b 629 return 0;
kadonotakashi 0:8fdf9a60065b 630 }
kadonotakashi 0:8fdf9a60065b 631
kadonotakashi 0:8fdf9a60065b 632 static inline void uart_irq(SercomUsart *const usart, uint32_t index)
kadonotakashi 0:8fdf9a60065b 633 {
kadonotakashi 0:8fdf9a60065b 634 MBED_ASSERT(usart != (void*)0);
kadonotakashi 0:8fdf9a60065b 635 uint16_t interrupt_status;
kadonotakashi 0:8fdf9a60065b 636 interrupt_status = usart->INTFLAG.reg;
kadonotakashi 0:8fdf9a60065b 637 interrupt_status &= usart->INTENSET.reg;
kadonotakashi 0:8fdf9a60065b 638
kadonotakashi 0:8fdf9a60065b 639 if (serial_irq_ids[index] != 0) {
kadonotakashi 0:8fdf9a60065b 640 if (interrupt_status & SERCOM_USART_INTFLAG_TXC) { // for transmit complete
kadonotakashi 0:8fdf9a60065b 641 usart->INTFLAG.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 642 if (irq_handler) {
kadonotakashi 0:8fdf9a60065b 643 irq_handler(serial_irq_ids[index], TxIrq);
kadonotakashi 0:8fdf9a60065b 644 }
kadonotakashi 0:8fdf9a60065b 645 }
kadonotakashi 0:8fdf9a60065b 646 if (interrupt_status & SERCOM_USART_INTFLAG_RXC) { // for receive complete
kadonotakashi 0:8fdf9a60065b 647 usart->INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
kadonotakashi 0:8fdf9a60065b 648 if (irq_handler) {
kadonotakashi 0:8fdf9a60065b 649 irq_handler(serial_irq_ids[index], RxIrq);
kadonotakashi 0:8fdf9a60065b 650 }
kadonotakashi 0:8fdf9a60065b 651 }
kadonotakashi 0:8fdf9a60065b 652 }
kadonotakashi 0:8fdf9a60065b 653 }
kadonotakashi 0:8fdf9a60065b 654
kadonotakashi 0:8fdf9a60065b 655 void uart0_irq()
kadonotakashi 0:8fdf9a60065b 656 {
kadonotakashi 0:8fdf9a60065b 657 uart_irq((SercomUsart *)UART_0, 0);
kadonotakashi 0:8fdf9a60065b 658 }
kadonotakashi 0:8fdf9a60065b 659
kadonotakashi 0:8fdf9a60065b 660 void uart1_irq()
kadonotakashi 0:8fdf9a60065b 661 {
kadonotakashi 0:8fdf9a60065b 662 uart_irq((SercomUsart *)UART_1, 1);
kadonotakashi 0:8fdf9a60065b 663 }
kadonotakashi 0:8fdf9a60065b 664
kadonotakashi 0:8fdf9a60065b 665 void uart2_irq()
kadonotakashi 0:8fdf9a60065b 666 {
kadonotakashi 0:8fdf9a60065b 667 uart_irq((SercomUsart *)UART_2, 2);
kadonotakashi 0:8fdf9a60065b 668 }
kadonotakashi 0:8fdf9a60065b 669
kadonotakashi 0:8fdf9a60065b 670 void uart3_irq()
kadonotakashi 0:8fdf9a60065b 671 {
kadonotakashi 0:8fdf9a60065b 672 uart_irq((SercomUsart *)UART_3, 3);
kadonotakashi 0:8fdf9a60065b 673 }
kadonotakashi 0:8fdf9a60065b 674
kadonotakashi 0:8fdf9a60065b 675 void uart4_irq()
kadonotakashi 0:8fdf9a60065b 676 {
kadonotakashi 0:8fdf9a60065b 677 uart_irq((SercomUsart *)UART_4, 4);
kadonotakashi 0:8fdf9a60065b 678 }
kadonotakashi 0:8fdf9a60065b 679
kadonotakashi 0:8fdf9a60065b 680 void uart5_irq()
kadonotakashi 0:8fdf9a60065b 681 {
kadonotakashi 0:8fdf9a60065b 682 uart_irq((SercomUsart *)UART_5, 5);
kadonotakashi 0:8fdf9a60065b 683 }
kadonotakashi 0:8fdf9a60065b 684
kadonotakashi 0:8fdf9a60065b 685 uint32_t get_serial_vector (serial_t *obj)
kadonotakashi 0:8fdf9a60065b 686 {
kadonotakashi 0:8fdf9a60065b 687 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 688 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 689 uint32_t vector = 0;
kadonotakashi 0:8fdf9a60065b 690 switch ((int)pUSART_S(obj)) {
kadonotakashi 0:8fdf9a60065b 691 case UART_0:
kadonotakashi 0:8fdf9a60065b 692 vector = (uint32_t)uart0_irq;
kadonotakashi 0:8fdf9a60065b 693 break;
kadonotakashi 0:8fdf9a60065b 694 case UART_1:
kadonotakashi 0:8fdf9a60065b 695 vector = (uint32_t)uart1_irq;
kadonotakashi 0:8fdf9a60065b 696 break;
kadonotakashi 0:8fdf9a60065b 697 case UART_2:
kadonotakashi 0:8fdf9a60065b 698 vector = (uint32_t)uart2_irq;
kadonotakashi 0:8fdf9a60065b 699 break;
kadonotakashi 0:8fdf9a60065b 700 case UART_3:
kadonotakashi 0:8fdf9a60065b 701 vector = (uint32_t)uart3_irq;
kadonotakashi 0:8fdf9a60065b 702 break;
kadonotakashi 0:8fdf9a60065b 703 case UART_4:
kadonotakashi 0:8fdf9a60065b 704 vector = (uint32_t)uart4_irq;
kadonotakashi 0:8fdf9a60065b 705 break;
kadonotakashi 0:8fdf9a60065b 706 case UART_5:
kadonotakashi 0:8fdf9a60065b 707 vector = (uint32_t)uart5_irq;
kadonotakashi 0:8fdf9a60065b 708 break;
kadonotakashi 0:8fdf9a60065b 709 }
kadonotakashi 0:8fdf9a60065b 710 return vector;
kadonotakashi 0:8fdf9a60065b 711 }
kadonotakashi 0:8fdf9a60065b 712
kadonotakashi 0:8fdf9a60065b 713 void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
kadonotakashi 0:8fdf9a60065b 714 {
kadonotakashi 0:8fdf9a60065b 715 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 716 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 717 irq_handler = handler;
kadonotakashi 0:8fdf9a60065b 718 serial_irq_ids[serial_get_index(obj)] = id;
kadonotakashi 0:8fdf9a60065b 719 }
kadonotakashi 0:8fdf9a60065b 720
kadonotakashi 0:8fdf9a60065b 721 IRQn_Type get_serial_irq_num (serial_t *obj)
kadonotakashi 0:8fdf9a60065b 722 {
kadonotakashi 0:8fdf9a60065b 723 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 724 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 725 switch ((int)pUSART_S(obj)) {
kadonotakashi 0:8fdf9a60065b 726 case UART_0:
kadonotakashi 0:8fdf9a60065b 727 return SERCOM0_IRQn;
kadonotakashi 0:8fdf9a60065b 728 case UART_1:
kadonotakashi 0:8fdf9a60065b 729 return SERCOM1_IRQn;
kadonotakashi 0:8fdf9a60065b 730 case UART_2:
kadonotakashi 0:8fdf9a60065b 731 return SERCOM2_IRQn;
kadonotakashi 0:8fdf9a60065b 732 case UART_3:
kadonotakashi 0:8fdf9a60065b 733 return SERCOM3_IRQn;
kadonotakashi 0:8fdf9a60065b 734 case UART_4:
kadonotakashi 0:8fdf9a60065b 735 return SERCOM4_IRQn;
kadonotakashi 0:8fdf9a60065b 736 case UART_5:
kadonotakashi 0:8fdf9a60065b 737 return SERCOM5_IRQn;
kadonotakashi 0:8fdf9a60065b 738 default:
kadonotakashi 0:8fdf9a60065b 739 MBED_ASSERT(0);
kadonotakashi 0:8fdf9a60065b 740 }
kadonotakashi 0:8fdf9a60065b 741 return SERCOM0_IRQn; // to avoid warning
kadonotakashi 0:8fdf9a60065b 742 }
kadonotakashi 0:8fdf9a60065b 743
kadonotakashi 0:8fdf9a60065b 744 void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
kadonotakashi 0:8fdf9a60065b 745 {
kadonotakashi 0:8fdf9a60065b 746 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 747 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 748 IRQn_Type irq_n = (IRQn_Type)0;
kadonotakashi 0:8fdf9a60065b 749 uint32_t vector = 0;
kadonotakashi 0:8fdf9a60065b 750
kadonotakashi 0:8fdf9a60065b 751 vector = get_serial_vector(obj);
kadonotakashi 0:8fdf9a60065b 752 irq_n = get_serial_irq_num(obj);
kadonotakashi 0:8fdf9a60065b 753
kadonotakashi 0:8fdf9a60065b 754 if (enable) {
kadonotakashi 0:8fdf9a60065b 755 switch (irq) {
kadonotakashi 0:8fdf9a60065b 756 case RxIrq:
kadonotakashi 0:8fdf9a60065b 757 _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
kadonotakashi 0:8fdf9a60065b 758 break;
kadonotakashi 0:8fdf9a60065b 759 case TxIrq:
kadonotakashi 0:8fdf9a60065b 760 _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 761 break;
kadonotakashi 0:8fdf9a60065b 762 }
kadonotakashi 0:8fdf9a60065b 763 NVIC_SetVector(irq_n, vector);
kadonotakashi 0:8fdf9a60065b 764 NVIC_EnableIRQ(irq_n);
kadonotakashi 0:8fdf9a60065b 765
kadonotakashi 0:8fdf9a60065b 766 } else {
kadonotakashi 0:8fdf9a60065b 767 switch (irq) {
kadonotakashi 0:8fdf9a60065b 768 case RxIrq:
kadonotakashi 0:8fdf9a60065b 769 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
kadonotakashi 0:8fdf9a60065b 770 break;
kadonotakashi 0:8fdf9a60065b 771 case TxIrq:
kadonotakashi 0:8fdf9a60065b 772 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 773 break;
kadonotakashi 0:8fdf9a60065b 774 }
kadonotakashi 0:8fdf9a60065b 775 NVIC_DisableIRQ(irq_n);
kadonotakashi 0:8fdf9a60065b 776 }
kadonotakashi 0:8fdf9a60065b 777 }
kadonotakashi 0:8fdf9a60065b 778
kadonotakashi 0:8fdf9a60065b 779 /******************************************************************************
kadonotakashi 0:8fdf9a60065b 780 * READ/WRITE
kadonotakashi 0:8fdf9a60065b 781 ******************************************************************************/
kadonotakashi 0:8fdf9a60065b 782 int serial_getc(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 783 {
kadonotakashi 0:8fdf9a60065b 784 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 785 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 786 while (!serial_readable(obj));
kadonotakashi 0:8fdf9a60065b 787 return _USART(obj).DATA.reg ;
kadonotakashi 0:8fdf9a60065b 788 }
kadonotakashi 0:8fdf9a60065b 789
kadonotakashi 0:8fdf9a60065b 790 void serial_putc(serial_t *obj, int c)
kadonotakashi 0:8fdf9a60065b 791 {
kadonotakashi 0:8fdf9a60065b 792 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 793 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 794 uint16_t q = (c & SERCOM_USART_DATA_MASK);
kadonotakashi 0:8fdf9a60065b 795 while (!serial_writable(obj));
kadonotakashi 0:8fdf9a60065b 796 _USART(obj).DATA.reg = q;
kadonotakashi 0:8fdf9a60065b 797 while (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)); // wait till data is sent
kadonotakashi 0:8fdf9a60065b 798 }
kadonotakashi 0:8fdf9a60065b 799
kadonotakashi 0:8fdf9a60065b 800 int serial_readable(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 801 {
kadonotakashi 0:8fdf9a60065b 802 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 803 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 804 uint32_t status = 1;
kadonotakashi 0:8fdf9a60065b 805 if (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_RXC)) {
kadonotakashi 0:8fdf9a60065b 806 status = 0;
kadonotakashi 0:8fdf9a60065b 807 } else {
kadonotakashi 0:8fdf9a60065b 808 status = 1;
kadonotakashi 0:8fdf9a60065b 809 }
kadonotakashi 0:8fdf9a60065b 810 return status;
kadonotakashi 0:8fdf9a60065b 811 }
kadonotakashi 0:8fdf9a60065b 812
kadonotakashi 0:8fdf9a60065b 813 int serial_writable(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 814 {
kadonotakashi 0:8fdf9a60065b 815 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 816 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 817 uint32_t status = 1;
kadonotakashi 0:8fdf9a60065b 818 if (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)) {
kadonotakashi 0:8fdf9a60065b 819 status = 0;
kadonotakashi 0:8fdf9a60065b 820 } else {
kadonotakashi 0:8fdf9a60065b 821 status = 1;
kadonotakashi 0:8fdf9a60065b 822 }
kadonotakashi 0:8fdf9a60065b 823 return status;
kadonotakashi 0:8fdf9a60065b 824 }
kadonotakashi 0:8fdf9a60065b 825
kadonotakashi 0:8fdf9a60065b 826 /************************************************************************************
kadonotakashi 0:8fdf9a60065b 827 * ASYNCHRONOUS HAL *
kadonotakashi 0:8fdf9a60065b 828 ************************************************************************************/
kadonotakashi 0:8fdf9a60065b 829
kadonotakashi 0:8fdf9a60065b 830 #if DEVICE_SERIAL_ASYNCH
kadonotakashi 0:8fdf9a60065b 831
kadonotakashi 0:8fdf9a60065b 832 /************************************
kadonotakashi 0:8fdf9a60065b 833 * HELPER FUNCTIONS *
kadonotakashi 0:8fdf9a60065b 834 ***********************************/
kadonotakashi 0:8fdf9a60065b 835 void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable)
kadonotakashi 0:8fdf9a60065b 836 {
kadonotakashi 0:8fdf9a60065b 837 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 838 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 839 if(enable) {
kadonotakashi 0:8fdf9a60065b 840 pSERIAL_S(obj)->events |= event;
kadonotakashi 0:8fdf9a60065b 841 } else {
kadonotakashi 0:8fdf9a60065b 842 pSERIAL_S(obj)->events &= ~ event;
kadonotakashi 0:8fdf9a60065b 843 }
kadonotakashi 0:8fdf9a60065b 844 }
kadonotakashi 0:8fdf9a60065b 845
kadonotakashi 0:8fdf9a60065b 846 void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable)
kadonotakashi 0:8fdf9a60065b 847 {
kadonotakashi 0:8fdf9a60065b 848 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 849 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 850 if(enable) {
kadonotakashi 0:8fdf9a60065b 851 pSERIAL_S(obj)->events |= event;
kadonotakashi 0:8fdf9a60065b 852 } else {
kadonotakashi 0:8fdf9a60065b 853 pSERIAL_S(obj)->events &= ~ event;
kadonotakashi 0:8fdf9a60065b 854 }
kadonotakashi 0:8fdf9a60065b 855 }
kadonotakashi 0:8fdf9a60065b 856
kadonotakashi 0:8fdf9a60065b 857 void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width)
kadonotakashi 0:8fdf9a60065b 858 {
kadonotakashi 0:8fdf9a60065b 859 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 860 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 861 MBED_ASSERT(tx != (void*)0);
kadonotakashi 0:8fdf9a60065b 862 // We only support byte buffers for now
kadonotakashi 0:8fdf9a60065b 863 MBED_ASSERT(width == 8);
kadonotakashi 0:8fdf9a60065b 864
kadonotakashi 0:8fdf9a60065b 865 if(serial_tx_active(obj)) return;
kadonotakashi 0:8fdf9a60065b 866
kadonotakashi 0:8fdf9a60065b 867 obj->tx_buff.buffer = tx;
kadonotakashi 0:8fdf9a60065b 868 obj->tx_buff.length = tx_length;
kadonotakashi 0:8fdf9a60065b 869 obj->tx_buff.pos = 0;
kadonotakashi 0:8fdf9a60065b 870
kadonotakashi 0:8fdf9a60065b 871 return;
kadonotakashi 0:8fdf9a60065b 872 }
kadonotakashi 0:8fdf9a60065b 873
kadonotakashi 0:8fdf9a60065b 874 void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width)
kadonotakashi 0:8fdf9a60065b 875 {
kadonotakashi 0:8fdf9a60065b 876 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 877 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 878 MBED_ASSERT(rx != (void*)0);
kadonotakashi 0:8fdf9a60065b 879 // We only support byte buffers for now
kadonotakashi 0:8fdf9a60065b 880 MBED_ASSERT(width == 8);
kadonotakashi 0:8fdf9a60065b 881
kadonotakashi 0:8fdf9a60065b 882 if(serial_rx_active(obj)) return;
kadonotakashi 0:8fdf9a60065b 883
kadonotakashi 0:8fdf9a60065b 884 obj->rx_buff.buffer = rx;
kadonotakashi 0:8fdf9a60065b 885 obj->rx_buff.length = rx_length;
kadonotakashi 0:8fdf9a60065b 886 obj->rx_buff.pos = 0;
kadonotakashi 0:8fdf9a60065b 887
kadonotakashi 0:8fdf9a60065b 888 return;
kadonotakashi 0:8fdf9a60065b 889 }
kadonotakashi 0:8fdf9a60065b 890
kadonotakashi 0:8fdf9a60065b 891 void serial_set_char_match(serial_t *obj, uint8_t char_match)
kadonotakashi 0:8fdf9a60065b 892 {
kadonotakashi 0:8fdf9a60065b 893 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 894 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 895 if (char_match != SERIAL_RESERVED_CHAR_MATCH) {
kadonotakashi 0:8fdf9a60065b 896 obj->char_match = char_match;
kadonotakashi 0:8fdf9a60065b 897 }
kadonotakashi 0:8fdf9a60065b 898 }
kadonotakashi 0:8fdf9a60065b 899
kadonotakashi 0:8fdf9a60065b 900 /************************************
kadonotakashi 0:8fdf9a60065b 901 * TRANSFER FUNCTIONS *
kadonotakashi 0:8fdf9a60065b 902 ***********************************/
kadonotakashi 0:8fdf9a60065b 903 int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
kadonotakashi 0:8fdf9a60065b 904 {
kadonotakashi 0:8fdf9a60065b 905 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 906 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 907 MBED_ASSERT(tx != (void*)0);
kadonotakashi 0:8fdf9a60065b 908 if(tx_length == 0) return 0;
kadonotakashi 0:8fdf9a60065b 909
kadonotakashi 0:8fdf9a60065b 910 serial_tx_buffer_set(obj, (void *)tx, tx_length, tx_width);
kadonotakashi 0:8fdf9a60065b 911 serial_tx_enable_event(obj, event, true);
kadonotakashi 0:8fdf9a60065b 912
kadonotakashi 0:8fdf9a60065b 913 NVIC_ClearPendingIRQ(get_serial_irq_num(obj));
kadonotakashi 0:8fdf9a60065b 914 NVIC_DisableIRQ(get_serial_irq_num(obj));
kadonotakashi 0:8fdf9a60065b 915 NVIC_SetVector(get_serial_irq_num(obj), (uint32_t)handler);
kadonotakashi 0:8fdf9a60065b 916 NVIC_EnableIRQ(get_serial_irq_num(obj));
kadonotakashi 0:8fdf9a60065b 917
kadonotakashi 0:8fdf9a60065b 918 if (pUSART_S(obj)) {
kadonotakashi 0:8fdf9a60065b 919 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 920 _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_DRE;
kadonotakashi 0:8fdf9a60065b 921 }
kadonotakashi 0:8fdf9a60065b 922 return 0;
kadonotakashi 0:8fdf9a60065b 923 }
kadonotakashi 0:8fdf9a60065b 924
kadonotakashi 0:8fdf9a60065b 925 void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
kadonotakashi 0:8fdf9a60065b 926 {
kadonotakashi 0:8fdf9a60065b 927 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 928 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 929 MBED_ASSERT(rx != (void*)0);
kadonotakashi 0:8fdf9a60065b 930
kadonotakashi 0:8fdf9a60065b 931 serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
kadonotakashi 0:8fdf9a60065b 932 serial_rx_enable_event(obj, event, true);
kadonotakashi 0:8fdf9a60065b 933 serial_set_char_match(obj, char_match);
kadonotakashi 0:8fdf9a60065b 934 serial_rx_buffer_set(obj, rx, rx_length, rx_width);
kadonotakashi 0:8fdf9a60065b 935
kadonotakashi 0:8fdf9a60065b 936 NVIC_ClearPendingIRQ(get_serial_irq_num(obj));
kadonotakashi 0:8fdf9a60065b 937 NVIC_DisableIRQ(get_serial_irq_num(obj));
kadonotakashi 0:8fdf9a60065b 938 NVIC_SetVector(get_serial_irq_num(obj), (uint32_t)handler);
kadonotakashi 0:8fdf9a60065b 939 NVIC_EnableIRQ(get_serial_irq_num(obj));
kadonotakashi 0:8fdf9a60065b 940
kadonotakashi 0:8fdf9a60065b 941 if (pUSART_S(obj)) {
kadonotakashi 0:8fdf9a60065b 942 _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
kadonotakashi 0:8fdf9a60065b 943 }
kadonotakashi 0:8fdf9a60065b 944 return;
kadonotakashi 0:8fdf9a60065b 945 }
kadonotakashi 0:8fdf9a60065b 946
kadonotakashi 0:8fdf9a60065b 947 uint8_t serial_tx_active(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 948 {
kadonotakashi 0:8fdf9a60065b 949 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 950 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 951 return ((obj->tx_buff.length > 0) ? true : false);
kadonotakashi 0:8fdf9a60065b 952 }
kadonotakashi 0:8fdf9a60065b 953
kadonotakashi 0:8fdf9a60065b 954 uint8_t serial_rx_active(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 955 {
kadonotakashi 0:8fdf9a60065b 956 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 957 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 958 return ((obj->rx_buff.length > 0) ? true : false);
kadonotakashi 0:8fdf9a60065b 959 }
kadonotakashi 0:8fdf9a60065b 960
kadonotakashi 0:8fdf9a60065b 961 int serial_tx_irq_handler_asynch(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 962 {
kadonotakashi 0:8fdf9a60065b 963 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 964 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 965 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 966 serial_tx_abort_asynch(obj);
kadonotakashi 0:8fdf9a60065b 967 return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
kadonotakashi 0:8fdf9a60065b 968 }
kadonotakashi 0:8fdf9a60065b 969
kadonotakashi 0:8fdf9a60065b 970 int serial_rx_irq_handler_asynch(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 971 {
kadonotakashi 0:8fdf9a60065b 972 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 973 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 974 int event = 0;
kadonotakashi 0:8fdf9a60065b 975 /* This interrupt handler is called from USART irq */
kadonotakashi 0:8fdf9a60065b 976 uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
kadonotakashi 0:8fdf9a60065b 977 uint8_t error_code = 0;
kadonotakashi 0:8fdf9a60065b 978 uint16_t received_data = 0;
kadonotakashi 0:8fdf9a60065b 979
kadonotakashi 0:8fdf9a60065b 980 error_code = (uint8_t)(_USART(obj).STATUS.reg & SERCOM_USART_STATUS_MASK);
kadonotakashi 0:8fdf9a60065b 981 /* Check if an error has occurred during the receiving */
kadonotakashi 0:8fdf9a60065b 982 if (error_code) {
kadonotakashi 0:8fdf9a60065b 983 /* Check which error occurred */
kadonotakashi 0:8fdf9a60065b 984 if (error_code & SERCOM_USART_STATUS_FERR) {
kadonotakashi 0:8fdf9a60065b 985 /* Store the error code and clear flag by writing 1 to it */
kadonotakashi 0:8fdf9a60065b 986 _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_FERR;
kadonotakashi 0:8fdf9a60065b 987 serial_rx_abort_asynch(obj);
kadonotakashi 0:8fdf9a60065b 988 return SERIAL_EVENT_RX_FRAMING_ERROR;
kadonotakashi 0:8fdf9a60065b 989 } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
kadonotakashi 0:8fdf9a60065b 990 /* Store the error code and clear flag by writing 1 to it */
kadonotakashi 0:8fdf9a60065b 991 _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_BUFOVF;
kadonotakashi 0:8fdf9a60065b 992 serial_rx_abort_asynch(obj);
kadonotakashi 0:8fdf9a60065b 993 return SERIAL_EVENT_RX_OVERFLOW;
kadonotakashi 0:8fdf9a60065b 994 } else if (error_code & SERCOM_USART_STATUS_PERR) {
kadonotakashi 0:8fdf9a60065b 995 /* Store the error code and clear flag by writing 1 to it */
kadonotakashi 0:8fdf9a60065b 996 _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_PERR;
kadonotakashi 0:8fdf9a60065b 997 serial_rx_abort_asynch(obj);
kadonotakashi 0:8fdf9a60065b 998 return SERIAL_EVENT_RX_PARITY_ERROR;
kadonotakashi 0:8fdf9a60065b 999 }
kadonotakashi 0:8fdf9a60065b 1000 }
kadonotakashi 0:8fdf9a60065b 1001
kadonotakashi 0:8fdf9a60065b 1002 /* Read current packet from DATA register,
kadonotakashi 0:8fdf9a60065b 1003 * increment buffer pointer and decrement buffer length */
kadonotakashi 0:8fdf9a60065b 1004 received_data = (_USART(obj).DATA.reg & SERCOM_USART_DATA_MASK);
kadonotakashi 0:8fdf9a60065b 1005
kadonotakashi 0:8fdf9a60065b 1006 /* Read value will be at least 8-bits long */
kadonotakashi 0:8fdf9a60065b 1007 buf[obj->rx_buff.pos] = received_data;
kadonotakashi 0:8fdf9a60065b 1008 /* Increment 8-bit pointer */
kadonotakashi 0:8fdf9a60065b 1009 obj->rx_buff.pos++;
kadonotakashi 0:8fdf9a60065b 1010
kadonotakashi 0:8fdf9a60065b 1011 /* Check if the last character have been received */
kadonotakashi 0:8fdf9a60065b 1012 if(--(obj->rx_buff.length) == 0) {
kadonotakashi 0:8fdf9a60065b 1013 event |= SERIAL_EVENT_RX_COMPLETE;
kadonotakashi 0:8fdf9a60065b 1014 if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
kadonotakashi 0:8fdf9a60065b 1015 event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
kadonotakashi 0:8fdf9a60065b 1016 }
kadonotakashi 0:8fdf9a60065b 1017 _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
kadonotakashi 0:8fdf9a60065b 1018 serial_rx_abort_asynch(obj);
kadonotakashi 0:8fdf9a60065b 1019 return event & obj->serial.events;
kadonotakashi 0:8fdf9a60065b 1020 }
kadonotakashi 0:8fdf9a60065b 1021
kadonotakashi 0:8fdf9a60065b 1022 /* Check for character match event */
kadonotakashi 0:8fdf9a60065b 1023 if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
kadonotakashi 0:8fdf9a60065b 1024 event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
kadonotakashi 0:8fdf9a60065b 1025 }
kadonotakashi 0:8fdf9a60065b 1026
kadonotakashi 0:8fdf9a60065b 1027 /* Return to the call back if character match occured */
kadonotakashi 0:8fdf9a60065b 1028 if(event != 0) {
kadonotakashi 0:8fdf9a60065b 1029 serial_rx_abort_asynch(obj);
kadonotakashi 0:8fdf9a60065b 1030 return event & obj->serial.events;
kadonotakashi 0:8fdf9a60065b 1031 }
kadonotakashi 0:8fdf9a60065b 1032 return 0;
kadonotakashi 0:8fdf9a60065b 1033 }
kadonotakashi 0:8fdf9a60065b 1034
kadonotakashi 0:8fdf9a60065b 1035 int serial_irq_handler_asynch(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 1036 {
kadonotakashi 0:8fdf9a60065b 1037 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 1038 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 1039 uint16_t interrupt_status;
kadonotakashi 0:8fdf9a60065b 1040 uint8_t *buf = obj->tx_buff.buffer;
kadonotakashi 0:8fdf9a60065b 1041
kadonotakashi 0:8fdf9a60065b 1042 interrupt_status = _USART(obj).INTFLAG.reg;
kadonotakashi 0:8fdf9a60065b 1043 interrupt_status &= _USART(obj).INTENSET.reg;
kadonotakashi 0:8fdf9a60065b 1044
kadonotakashi 0:8fdf9a60065b 1045 if (pUSART_S(obj)) {
kadonotakashi 0:8fdf9a60065b 1046 if (interrupt_status & SERCOM_USART_INTFLAG_DRE) {
kadonotakashi 0:8fdf9a60065b 1047 /* Interrupt has another TX source */
kadonotakashi 0:8fdf9a60065b 1048 if(obj->tx_buff.pos >= obj->tx_buff.length) {
kadonotakashi 0:8fdf9a60065b 1049 /* Transfer complete. Switch off interrupt and return event. */
kadonotakashi 0:8fdf9a60065b 1050 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_DRE;
kadonotakashi 0:8fdf9a60065b 1051 _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 1052 } else {
kadonotakashi 0:8fdf9a60065b 1053 while((serial_writable(obj)) && (obj->tx_buff.pos <= (obj->tx_buff.length - 1))) {
kadonotakashi 0:8fdf9a60065b 1054 _USART(obj).DATA.reg = buf[obj->tx_buff.pos];
kadonotakashi 0:8fdf9a60065b 1055 obj->tx_buff.pos++;
kadonotakashi 0:8fdf9a60065b 1056 }
kadonotakashi 0:8fdf9a60065b 1057 }
kadonotakashi 0:8fdf9a60065b 1058 }
kadonotakashi 0:8fdf9a60065b 1059 if (interrupt_status & SERCOM_USART_INTFLAG_TXC) {
kadonotakashi 0:8fdf9a60065b 1060 return serial_tx_irq_handler_asynch(obj);
kadonotakashi 0:8fdf9a60065b 1061 }
kadonotakashi 0:8fdf9a60065b 1062 if (interrupt_status & SERCOM_USART_INTFLAG_RXC) {
kadonotakashi 0:8fdf9a60065b 1063 return serial_rx_irq_handler_asynch(obj);
kadonotakashi 0:8fdf9a60065b 1064 }
kadonotakashi 0:8fdf9a60065b 1065 }
kadonotakashi 0:8fdf9a60065b 1066 return 0;
kadonotakashi 0:8fdf9a60065b 1067 }
kadonotakashi 0:8fdf9a60065b 1068
kadonotakashi 0:8fdf9a60065b 1069 void serial_tx_abort_asynch(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 1070 {
kadonotakashi 0:8fdf9a60065b 1071 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 1072 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 1073 _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 1074 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_TXC;
kadonotakashi 0:8fdf9a60065b 1075 obj->tx_buff.length = 0;
kadonotakashi 0:8fdf9a60065b 1076 obj->rx_buff.pos = 0;
kadonotakashi 0:8fdf9a60065b 1077
kadonotakashi 0:8fdf9a60065b 1078 }
kadonotakashi 0:8fdf9a60065b 1079
kadonotakashi 0:8fdf9a60065b 1080 void serial_rx_abort_asynch(serial_t *obj)
kadonotakashi 0:8fdf9a60065b 1081 {
kadonotakashi 0:8fdf9a60065b 1082 /* Sanity check arguments */
kadonotakashi 0:8fdf9a60065b 1083 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 1084 _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
kadonotakashi 0:8fdf9a60065b 1085 _USART(obj).INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
kadonotakashi 0:8fdf9a60065b 1086 obj->rx_buff.length = 0;
kadonotakashi 0:8fdf9a60065b 1087 obj->rx_buff.pos = 0;
kadonotakashi 0:8fdf9a60065b 1088 }
kadonotakashi 0:8fdf9a60065b 1089
kadonotakashi 0:8fdf9a60065b 1090 #endif