diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralNames.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralNames.h index 195e983fc1..9537a4a00f 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralNames.h +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralNames.h @@ -33,7 +33,12 @@ extern "C" { typedef enum { - UART_0 = (int)0x42000800UL // Base address of SERCOM0 + UART_0 = (int)0x42000800UL, // Base address of SERCOM0 + UART_1 = (int)0x42000C00UL, // Base address of SERCOM1 + UART_2 = (int)0x42001000UL, // Base address of SERCOM2 + UART_3 = (int)0x42001400UL, // Base address of SERCOM3 + UART_4 = (int)0x42001800UL, // Base address of SERCOM4 + UART_5 = (int)0x42001C00UL // Base address of SERCOM5 } UARTName; /* typedef enum { diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralPins.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralPins.h index 636af1e4a9..c387b946de 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralPins.h +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PeripheralPins.h @@ -20,6 +20,8 @@ #include "pinmap.h" #include "PeripheralNames.h" +void find_pin_settings (PinName output, PinName input, PinName clock, uint32_t* pad_pinmuxes); +uint32_t find_mux_setting (PinName output, PinName input, PinName clock); /************RTC***************/ //extern const PinMap PinMap_RTC[]; @@ -46,4 +48,6 @@ extern const PinMap PinMap_UART_RX[]; /************PWM***************/ //extern const PinMap PinMap_PWM[]; + + #endif diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PinNames.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PinNames.h index bf0fb21b47..d6242a882e 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PinNames.h +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/PinNames.h @@ -94,9 +94,13 @@ typedef enum { PB29 = 61, PB30 = 62, PB31 = 63, + + PC16 = 64, + PC18 = 65, + PC19 = 66, - USBTX = PA04, - USBRX = PA05, + USBTX = PA04, + USBRX = PA05, // Not connected NC = (int)0xFFFFFFFF diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/PeripheralPins.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/PeripheralPins.c index 7925cdfb81..d11028dfa0 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/PeripheralPins.c +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/PeripheralPins.c @@ -16,6 +16,18 @@ #include "PeripheralPins.h" +#define SERCOM_NULL 0xFF +#define MUX_NULL 0xFF + +#define SERCOM_USART_CTRLA_RXPO_Pos 20 /**< \brief (SERCOM_USART_CTRLA) Receive Data Pinout */ +#define SERCOM_USART_CTRLA_RXPO_Msk (0x3ul << SERCOM_USART_CTRLA_RXPO_Pos) +#define SERCOM_USART_CTRLA_RXPO(value) ((SERCOM_USART_CTRLA_RXPO_Msk & ((value) << SERCOM_USART_CTRLA_RXPO_Pos))) + +#define SERCOM_USART_CTRLA_TXPO_Pos 16 /**< \brief (SERCOM_USART_CTRLA) Transmit Data Pinout */ +#define SERCOM_USART_CTRLA_TXPO_Msk (0x3ul << SERCOM_USART_CTRLA_TXPO_Pos) +#define SERCOM_USART_CTRLA_TXPO(value) ((SERCOM_USART_CTRLA_TXPO_Msk & ((value) << SERCOM_USART_CTRLA_TXPO_Pos))) + + /************RTC***************/ const PinMap PinMap_RTC[] = { }; @@ -60,3 +72,438 @@ const PinMap PinMap_SPI_SSEL[] = { /************PWM***************/ const PinMap PinMap_PWM[] = { }; + +/********SERCOM MAPPING*********/ +struct pin_sercom{ + uint8_t pad_num; // a pin always mapped to a pad + uint8_t com_num[2]; // a pin always mapped to maximum of 2 sercoms +// uint8_t pin_mux[2]; // Mux setting for the pin A,B...H ---> 0,1...7 +}; +struct pin_values{ + uint8_t pin; + uint8_t pad; + uint8_t com; +}; + +struct pin_sercom SAM21[] = {{0, {1, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA00 + {1, {1, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA01 + {0, {0, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA04 + {1, {0, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA05 + {2, {0, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA06 + {3, {0, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA07 + {0, {0, 2}/*, {2, 3}*/}, // PA08 + {1, {0, 2}/*, {2, 3}*/}, // PA09 + {0, {2, SERCOM_NULL}/*, {2, MUX_NULL}*/}, // PA12 + {1, {2, SERCOM_NULL}/*, {2, MUX_NULL}*/}, // PA13 + {2, {2, SERCOM_NULL}/*, {2, MUX_NULL}*/}, // PA14 + {3, {2, SERCOM_NULL}/*, {2, MUX_NULL}*/}, // PA15 + {0, {1, 3}/*, {2, 3}*/}, // PA16 + {1, {1, 3}/*, {2, 3}*/}, // PA17 + {2, {1, 3}/*, {2, 3}*/}, // PA18 + {3, {1, 3}/*, {2, 3}*/}, // PA19 + {0, {3, 5}/*, {2, 3}*/}, // PA22 + {1, {3, 5}/*, {2, 3}*/}, // PA23 + {2, {3, 5}/*, {2, 3}*/}, // PA24 + {3, {3, 5}/*, {2, 3}*/}, // PA25 + {0, {3, SERCOM_NULL}/*, {5, MUX_NULL}*/}, // PA27 + {1, {3, SERCOM_NULL}/*, {5, MUX_NULL}*/}, // PA28 + {2, {1, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA30 + {3, {1, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PA31 + {0, {5, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PB02 + {1, {5, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PB03 + {2, {5, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PB22 + {3, {5, SERCOM_NULL}/*, {3, MUX_NULL}*/}, // PB23 + {2, {4, SERCOM_NULL}/*, {5, MUX_NULL}*/}, // PB30 + {1, {4, SERCOM_NULL}/*, {5, MUX_NULL}*/}, // PB31 + {3, {4, SERCOM_NULL}/*, {5, MUX_NULL}*/}, // PC18 + {0, {4, SERCOM_NULL}/*, {5, MUX_NULL}*/} // PC19 +}; +const PinMap PinMap_SERCOM_PINS[] = { + {PA00}, + {PA01}, + {PA04}, + {PA05}, + {PA06}, + {PA07}, + {PA08}, + {PA09}, + {PA12}, + {PA13}, + {PA14}, + {PA15}, + {PA16}, + {PA17}, + {PA18}, + {PA19}, + {PA22}, + {PA23}, + {PA24}, + {PA25}, + {PA27}, + {PA28}, + {PA30}, + {PA31}, + + {PB02}, + {PB03}, + {PB22}, + {PB23}, + {PB30}, + {PB31}, + + {PC18}, + {PC19} + +}; + +uint32_t pinmap_find_sercom_index (PinName pin, const PinMap* map) +{ + uint8_t count = 0; + while (map->pin != NC) { + if (map->pin == pin) + return count; + map++; + count++; + } + return (uint32_t)NC; +} + +uint32_t pinmap_sercom_peripheral (PinName pin1, PinName pin2) +{ + uint8_t index1 = 0, index2 = 0; + + if ((pin1 == (PinName)NC) || (pin2 == (PinName)NC)) { + return (uint32_t)NC; + } + + index1 = pinmap_find_sercom_index(pin1, PinMap_SERCOM_PINS); + index2 = pinmap_find_sercom_index(pin2, PinMap_SERCOM_PINS); + + if (SAM21[index1].com_num[1] == SERCOM_NULL) { + return SAM21[index1].com_num[0]; + } else { + if ((SAM21[index1].com_num[0] == SAM21[index2].com_num[0]) || (SAM21[index1].com_num[0] == SAM21[index2].com_num[1])) { + return SAM21[index1].com_num[0]; + } else { + return SAM21[index1].com_num[1]; + } + } +} + +uint32_t pinmap_sercom_pad (PinName pin) +{ + uint8_t index = 0; + + if (pin == (PinName)NC) + return (uint32_t)NC; + + index = pinmap_find_sercom_index(pin, PinMap_SERCOM_PINS); + return SAM21[index].pad_num; +} + +uint32_t find_sercom_pinmux (struct pin_values* PinValues) +{ + switch (PinValues->com) { + case 0: // SERCOM0 + switch (PinValues->pin) { + case PA04: + return PINMUX_PA04D_SERCOM0_PAD0; + break; + case PA08: + return PINMUX_PA08C_SERCOM0_PAD0; + break; + case PA05: + return PINMUX_PA05D_SERCOM0_PAD1; + break; + case PA09: + return PINMUX_PA09C_SERCOM0_PAD1; + break; + case PA06: + return PINMUX_PA06D_SERCOM0_PAD2; + break; + case PA10: + return PINMUX_PA10C_SERCOM0_PAD2; + break; + case PA07: + return PINMUX_PA07D_SERCOM0_PAD3; + break; + case PA11: + return PINMUX_PA11C_SERCOM0_PAD3; + break; + default: + break; + } + break; + case 1: // SERCOM1 + switch (PinValues->pin) { + case PA16: + return PINMUX_PA16C_SERCOM1_PAD0; + break; + case PA00: + return PINMUX_PA00D_SERCOM1_PAD0; + break; + case PA17: + return PINMUX_PA17C_SERCOM1_PAD1; + break; + case PA01: + return PINMUX_PA01D_SERCOM1_PAD1; + break; + case PA30: + return PINMUX_PA30D_SERCOM1_PAD2; + break; + case PA18: + return PINMUX_PA18C_SERCOM1_PAD2; + break; + case PA31: + return PINMUX_PA31D_SERCOM1_PAD3; + break; + case PA19: + return PINMUX_PA19C_SERCOM1_PAD3; + break; + default: + break; + } + break; + case 2: // SERCOM2 + switch (PinValues->pin) { + case PA08: + return PINMUX_PA08D_SERCOM2_PAD0; + break; + case PA12: + return PINMUX_PA12C_SERCOM2_PAD0; + break; + case PA09: + return PINMUX_PA09D_SERCOM2_PAD1; + break; + case PA13: + return PINMUX_PA13C_SERCOM2_PAD1; + break; + case PA10: + return PINMUX_PA10D_SERCOM2_PAD2; + break; + case PA14: + return PINMUX_PA14C_SERCOM2_PAD2; + break; + case PA11: + return PINMUX_PA11D_SERCOM2_PAD3; + break; + case PA15: + return PINMUX_PA15C_SERCOM2_PAD3; + break; + default: + break; + } + break; + case 3: // SERCOM3 + switch (PinValues->pin) { + case PA16: + return PINMUX_PA16D_SERCOM3_PAD0; + break; + case PA22: + return PINMUX_PA22C_SERCOM3_PAD0; + break; + case PA27: + return PINMUX_PA27F_SERCOM3_PAD0; + break; + case PA17: + return PINMUX_PA17D_SERCOM3_PAD1; + break; + case PA23: + return PINMUX_PA23C_SERCOM3_PAD1; + break; + case PA28: + return PINMUX_PA28F_SERCOM3_PAD1; + break; + case PA18: + return PINMUX_PA18D_SERCOM3_PAD2; + break; + case PA20: + return PINMUX_PA20D_SERCOM3_PAD2; + break; + case PA24: + return PINMUX_PA24C_SERCOM3_PAD2; + break; + case PA19: + return PINMUX_PA19D_SERCOM3_PAD3; + break; + case PA25: + return PINMUX_PA25C_SERCOM3_PAD3; + break; + default: + break; + } + break; + case 4: // SERCOM4 + switch (PinValues->pin) { + case PA12: + return PINMUX_PA12D_SERCOM4_PAD0; + break; + case PB08: + return PINMUX_PB08D_SERCOM4_PAD0; + break; + case PC19: + return PINMUX_PC19F_SERCOM4_PAD0; + break; + case PA13: + return PINMUX_PA13D_SERCOM4_PAD1; + break; + case PB09: + return PINMUX_PB09D_SERCOM4_PAD1; + break; + case PB31: + return PINMUX_PB31F_SERCOM4_PAD1; + break; + case PA14: + return PINMUX_PA14D_SERCOM4_PAD2; + break; + case PB14: + return PINMUX_PB14C_SERCOM4_PAD2; + break; + case PB30: + return PINMUX_PB30F_SERCOM4_PAD2; + break; + case PA15: + return PINMUX_PA15D_SERCOM4_PAD3; + break; + case PB15: + return PINMUX_PB15C_SERCOM4_PAD3; + break; + case PC18: + return PINMUX_PC18F_SERCOM4_PAD3; + break; + default: + break; + } + break; + case 5: // SERCOM5 + switch (PinValues->pin) { + case PB16: + return PINMUX_PB16C_SERCOM5_PAD0; + break; + case PA22: + return PINMUX_PA22D_SERCOM5_PAD0; + break; + case PB02: + return PINMUX_PB02D_SERCOM5_PAD0; + break; + case PB30: + return PINMUX_PB30D_SERCOM5_PAD0; + break; + case PB17: + return PINMUX_PB17C_SERCOM5_PAD1; + break; + case PA23: + return PINMUX_PA23D_SERCOM5_PAD1; + break; + case PB03: + return PINMUX_PB03D_SERCOM5_PAD1; + break; + case PB31: + return PINMUX_PB31D_SERCOM5_PAD1; + break; + case PA24: + return PINMUX_PA24D_SERCOM5_PAD2; + break; + case PB00: + return PINMUX_PB00D_SERCOM5_PAD2; + break; + case PB22: + return PINMUX_PB22D_SERCOM5_PAD2; + break; + case PA20: + return PINMUX_PA20C_SERCOM5_PAD2; + break; + case PA25: + return PINMUX_PA25D_SERCOM5_PAD3; + break; + case PB23: + return PINMUX_PB23D_SERCOM5_PAD3; + break; + default: + break; + } + break; + } +} +uint32_t find_mux_setting (PinName output, PinName input, PinName clock) +{ + struct pin_values input_values, output_values, clock_values; + uint32_t mux_setting = 0; + + input_values.pin = input; + output_values.pin = output; + clock_values.pin = clock; + + input_values.com = pinmap_sercom_peripheral(input, output); + output_values.com = input_values.com; + clock_values.com = input_values.com; + + input_values.pad = pinmap_sercom_pad(input); + output_values.pad = pinmap_sercom_pad(output); + clock_values.pad = pinmap_sercom_pad(clock); + + switch(input_values.pad) { //TODO: Condition for hardware flow control enabled is different. + case 0: + mux_setting |= SERCOM_USART_CTRLA_RXPO(0); + break; + case 1: + mux_setting |= SERCOM_USART_CTRLA_RXPO(1); + break; + case 2: + mux_setting |= SERCOM_USART_CTRLA_RXPO(2); + break; + case 3: + mux_setting |= SERCOM_USART_CTRLA_RXPO(3); + break; + } + + if (((output_values.pad == 0) && (clock_values.pad == 1)) || (output_values.pad == 0)) { + mux_setting |= SERCOM_USART_CTRLA_TXPO(0); + } + else if((output_values.pad == 2) && (clock_values.pad == 3)) { + mux_setting |= SERCOM_USART_CTRLA_TXPO(1); + } + /*else if((output_values.pad == 0)) { // condition for hardware enabled + mux_setting |= SERCOM_USART_CTRLA_TXPO(2); + }*/ + else { + mux_setting = mux_setting; // dummy condition + } + + return mux_setting; +} + +void find_pin_settings (PinName output, PinName input, PinName clock, uint32_t* pad_pinmuxes) +{ + struct pin_values input_values, output_values, clock_values; + uint8_t i = 0; + + for (i = 0; i < 4 ; i++ ){ // load default values for the pins + pad_pinmuxes[i] = 0xFFFFFFFF; //PINMUX_UNUSED + } + + input_values.pin = input; + output_values.pin = output; + clock_values.pin = clock; + + input_values.com = pinmap_sercom_peripheral(input, output); + output_values.com = input_values.com; + clock_values.com = input_values.com; + + input_values.pad = pinmap_sercom_pad(input); + output_values.pad = pinmap_sercom_pad(output); + clock_values.pad = pinmap_sercom_pad(clock); + + if (input_values.pad < 0x04) + pad_pinmuxes[input_values.pad] = find_sercom_pinmux(&input_values); + if (output_values.pad < 0x04) + pad_pinmuxes[output_values.pad] = find_sercom_pinmux(&output_values); + if (clock_values.pad < 0x04) + pad_pinmuxes[clock_values.pad] = find_sercom_pinmux(&clock_values); + +} + + + + + diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h index cc113407e1..25eae68214 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/TARGET_SAMR21G18A/device.h @@ -27,6 +27,7 @@ #define DEVICE_SERIAL 1 #define DEVICE_SERIAL_FC 1 +#define DEVICE_SERIAL_ASYNCH 1 #define DEVICE_I2C 0 #define DEVICE_I2CSLAVE 0 diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/gpio_api.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/gpio_api.c index a29b4ca8d4..58e87adc2b 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/gpio_api.c +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/gpio_api.c @@ -79,7 +79,7 @@ void gpio_dir(gpio_t *obj, PinDirection direction) { pin_conf.direction = PORT_PIN_DIR_INPUT; break; case PIN_OUTPUT: - pin_conf.direction = PORT_PIN_DIR_OUTPUT; + pin_conf.direction = /*PORT_PIN_DIR_OUTPUT*/PORT_PIN_DIR_OUTPUT_WTH_READBACK; break; case PIN_INPUT_OUTPUT: pin_conf.direction = PORT_PIN_DIR_OUTPUT_WTH_READBACK; diff --git a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c index 15088b51ca..e0e69008a2 100644 --- a/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c +++ b/libraries/mbed/targets/hal/TARGET_Atmel/TARGET_SAM21/serial_api.c @@ -22,9 +22,18 @@ #include "usart.h" #include "samr21_xplained_pro.h" -#define _USART(obj) obj->usart->USART -#define USART_NUM 1 // for SAMR21 // to be updated for samd21 -//#define USART_BUF 8 +#if DEVICE_SERIAL_ASYNCH +#define pUSART_S(obj) obj->serial.usart +#define pSERIAL_S(obj) ((struct serial_s*)&(obj->serial)) +#else +#define pUSART_S(obj) obj->serial +#define pSERIAL_S(obj) ((struct serial_s*)obj) +#endif +#define _USART(obj) pUSART_S(obj)->USART +#define USART_NUM 6 + + +uint8_t serial_get_index(serial_t *obj); static uint32_t serial_irq_ids[USART_NUM] = {0}; static uart_irq_handler irq_handler; @@ -32,13 +41,6 @@ static uart_irq_handler irq_handler; int stdio_uart_inited = 0; serial_t stdio_uart; - -/*struct serial_global_data_s{ - uint8_t string[USART_BUF]; - uint8_t count; - }; -static struct serial_global_data_s uart_data[USART_NUM];*/ - extern uint8_t g_sys_init; static inline bool usart_syncing(serial_t *obj) @@ -56,7 +58,7 @@ static inline void enable_usart(serial_t *obj) #if USART_CALLBACK_MODE == true //TODO: to be implemented /* Enable Global interrupt for module */ - system_interrupt_enable(_sercom_get_interrupt_vector(obj->usart)); +// system_interrupt_enable(_sercom_get_interrupt_vector(pUSART_S(obj))); // not required in implementation #endif /* Wait until synchronization is complete */ @@ -73,7 +75,7 @@ static inline void disable_usart(serial_t *obj) #if USART_CALLBACK_MODE == true //TODO: to be implemented /* Disable Global interrupt for module */ - system_interrupt_disable(_sercom_get_interrupt_vector(obj->usart)); +// system_interrupt_disable(_sercom_get_interrupt_vector(pUSART_S(obj))); // not required in implementation #endif /* Wait until synchronization is complete */ usart_syncing(obj); @@ -100,7 +102,7 @@ static enum status_code usart_set_config_asf( serial_t *obj) { /* Index for generic clock */ - uint32_t sercom_index = _sercom_get_sercom_inst_index(obj->usart); + uint32_t sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj)); uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE; /* Cache new register values to minimize the number of register writes */ @@ -112,31 +114,31 @@ static enum status_code usart_set_config_asf( serial_t *obj) enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16; /* Set data order, internal muxing, and clock polarity */ - ctrla = (uint32_t)obj->data_order | - (uint32_t)obj->mux_setting | + ctrla = (uint32_t)pSERIAL_S(obj)->data_order | + (uint32_t)pSERIAL_S(obj)->mux_setting | #ifdef FEATURE_USART_OVER_SAMPLE - obj->sample_adjustment | - obj->sample_rate | + pSERIAL_S(obj)->sample_adjustment | + pSERIAL_S(obj)->sample_rate | #endif - (obj->clock_polarity_inverted << SERCOM_USART_CTRLA_CPOL_Pos); + (pSERIAL_S(obj)->clock_polarity_inverted << SERCOM_USART_CTRLA_CPOL_Pos); /* Get baud value from mode and clock */ - switch (obj->transfer_mode) + switch (pSERIAL_S(obj)->transfer_mode) { case USART_TRANSFER_SYNCHRONOUSLY: - if (!obj->use_external_clock) { - _sercom_get_sync_baud_val(obj->baudrate, + if (!pSERIAL_S(obj)->use_external_clock) { + _sercom_get_sync_baud_val(pSERIAL_S(obj)->baudrate, system_gclk_chan_get_hz(gclk_index), &baud); } break; case USART_TRANSFER_ASYNCHRONOUSLY: - if (obj->use_external_clock) { - _sercom_get_async_baud_val(obj->baudrate, - obj->ext_clock_freq, &baud, mode, sample_num); + if (pSERIAL_S(obj)->use_external_clock) { + _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate, + pSERIAL_S(obj)->ext_clock_freq, &baud, mode, sample_num); } else { - _sercom_get_async_baud_val(obj->baudrate, + _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate, system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num); } @@ -150,9 +152,9 @@ static enum status_code usart_set_config_asf( serial_t *obj) _USART(obj).BAUD.reg = baud; /* Set sample mode */ - ctrla |= obj->transfer_mode; + ctrla |= pSERIAL_S(obj)->transfer_mode; - if (obj->use_external_clock == false) { + if (pSERIAL_S(obj)->use_external_clock == false) { ctrla |= SERCOM_USART_CTRLA_MODE(0x1); } else { @@ -160,23 +162,23 @@ static enum status_code usart_set_config_asf( serial_t *obj) } /* Set stopbits, character size and enable transceivers */ - ctrlb = (uint32_t)obj->stopbits | (uint32_t)obj->character_size | + ctrlb = (uint32_t)pSERIAL_S(obj)->stopbits | (uint32_t)pSERIAL_S(obj)->character_size | #ifdef FEATURE_USART_START_FRAME_DECTION - (obj->start_frame_detection_enable << SERCOM_USART_CTRLB_SFDE_Pos) | + (pSERIAL_S(obj)->start_frame_detection_enable << SERCOM_USART_CTRLB_SFDE_Pos) | #endif - (obj->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) | - (obj->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos); + (pSERIAL_S(obj)->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) | + (pSERIAL_S(obj)->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos); /* Check parity mode bits */ - if (obj->parity != USART_PARITY_NONE) { + if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) { ctrla |= SERCOM_USART_CTRLA_FORM(1); - ctrlb |= obj->parity; + ctrlb |= pSERIAL_S(obj)->parity; } else { ctrla |= SERCOM_USART_CTRLA_FORM(0); } /* Set whether module should run in standby. */ - if (obj->run_in_standby || system_is_debugger_present()) { + if (pSERIAL_S(obj)->run_in_standby || system_is_debugger_present()) { ctrla |= SERCOM_USART_CTRLA_RUNSTDBY; } @@ -195,6 +197,30 @@ static enum status_code usart_set_config_asf( serial_t *obj) return STATUS_OK; } +void get_default_serial_values(serial_t *obj){ + /* Set default config to object */ + pSERIAL_S(obj)->data_order = USART_DATAORDER_LSB; + pSERIAL_S(obj)->transfer_mode = USART_TRANSFER_ASYNCHRONOUSLY; + pSERIAL_S(obj)->parity = USART_PARITY_NONE; + pSERIAL_S(obj)->stopbits = USART_STOPBITS_1; + pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT; + pSERIAL_S(obj)->baudrate = 9600; + pSERIAL_S(obj)->receiver_enable = true; + pSERIAL_S(obj)->transmitter_enable = true; + pSERIAL_S(obj)->clock_polarity_inverted = false; + pSERIAL_S(obj)->use_external_clock = false; + pSERIAL_S(obj)->ext_clock_freq = 0; + pSERIAL_S(obj)->mux_setting = USART_RX_1_TX_2_XCK_3; + pSERIAL_S(obj)->run_in_standby = false; + pSERIAL_S(obj)->generator_source = GCLK_GENERATOR_0; + pSERIAL_S(obj)->pinmux_pad0 = PINMUX_DEFAULT; + pSERIAL_S(obj)->pinmux_pad1 = PINMUX_DEFAULT; + pSERIAL_S(obj)->pinmux_pad2 = PINMUX_DEFAULT; + pSERIAL_S(obj)->pinmux_pad3 = PINMUX_DEFAULT; + pSERIAL_S(obj)->start_frame_detection_enable = false; + }; + + void serial_init(serial_t *obj, PinName tx, PinName rx) { if (g_sys_init == 0) { system_init(); @@ -202,49 +228,51 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { } struct system_gclk_chan_config gclk_chan_conf; + UARTName uart; uint32_t gclk_index; uint32_t pm_index; uint32_t sercom_index = 0; - - obj->usart = EXT1_UART_MODULE; + uint32_t muxsetting = 0; + uint32_t padsetting[4] = {0}; + + pUSART_S(obj) = EXT1_UART_MODULE; /* Disable USART module */ disable_usart(obj); - /* Set default config to object */ - obj->data_order = USART_DATAORDER_LSB; - obj->transfer_mode = USART_TRANSFER_ASYNCHRONOUSLY; - obj->parity = USART_PARITY_NONE; - obj->stopbits = USART_STOPBITS_1; - obj->character_size = USART_CHARACTER_SIZE_8BIT; - obj->baudrate = 9600; - obj->receiver_enable = true; - obj->transmitter_enable = true; - obj->clock_polarity_inverted = false; - obj->use_external_clock = false; - obj->ext_clock_freq = 0; - obj->mux_setting = USART_RX_1_TX_2_XCK_3; - obj->run_in_standby = false; - obj->generator_source = GCLK_GENERATOR_0; - obj->pinmux_pad0 = PINMUX_DEFAULT; - obj->pinmux_pad1 = PINMUX_DEFAULT; - obj->pinmux_pad2 = PINMUX_DEFAULT; - obj->pinmux_pad3 = PINMUX_DEFAULT; - obj->start_frame_detection_enable = false; + get_default_serial_values(obj); - obj->mux_setting = EDBG_CDC_SERCOM_MUX_SETTING; // to be done according to the pin received from user - obj->pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0; - obj->pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1; - obj->pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2; - obj->pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3; - - //TODO: now noly UART0. code to get the SERCOM instance from Pins (pinmapping) to be added later - UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); - UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); - UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); - - sercom_index = _sercom_get_sercom_inst_index(obj->usart); + find_pin_settings(tx, rx, NC, &padsetting[0]); // tx, rx, clk, pad array // getting pads from pins + muxsetting = find_mux_setting(tx, rx, NC); // getting mux setting from pins + sercom_index = pinmap_sercom_peripheral(tx, rx); // same variable sercom_index reused for optimization + switch (sercom_index){ + case 0: + uart = UART_0; + break; + case 1: + uart = UART_1; + break; + case 2: + uart = UART_2; + break; + case 3: + uart = UART_3; + break; + case 4: + uart = UART_4; + break; + case 5: + uart = UART_5; + break; + } + + pSERIAL_S(obj)->mux_setting = muxsetting;//EDBG_CDC_SERCOM_MUX_SETTING; + pSERIAL_S(obj)->pinmux_pad0 = padsetting[0];//EDBG_CDC_SERCOM_PINMUX_PAD0; + pSERIAL_S(obj)->pinmux_pad1 = padsetting[1];//EDBG_CDC_SERCOM_PINMUX_PAD1; + pSERIAL_S(obj)->pinmux_pad2 = padsetting[2];//EDBG_CDC_SERCOM_PINMUX_PAD2; + pSERIAL_S(obj)->pinmux_pad3 = padsetting[3];//EDBG_CDC_SERCOM_PINMUX_PAD3; + sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj)); pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos; gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE; @@ -260,11 +288,11 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index); /* Set up the GCLK for the module */ - obj->generator_source = GCLK_GENERATOR_0; - gclk_chan_conf.source_generator = obj->generator_source; + pSERIAL_S(obj)->generator_source = GCLK_GENERATOR_0; + gclk_chan_conf.source_generator = pSERIAL_S(obj)->generator_source; system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); - sercom_set_gclk_generator(obj->generator_source, false); + sercom_set_gclk_generator(pSERIAL_S(obj)->generator_source, false); /* Set configuration according to the config struct */ usart_set_config_asf(obj); @@ -274,8 +302,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE; uint32_t pad_pinmuxes[] = { - obj->pinmux_pad0, obj->pinmux_pad1, - obj->pinmux_pad2, obj->pinmux_pad3 + pSERIAL_S(obj)->pinmux_pad0, pSERIAL_S(obj)->pinmux_pad1, + pSERIAL_S(obj)->pinmux_pad2, pSERIAL_S(obj)->pinmux_pad3 }; /* Configure the SERCOM pins according to the user configuration */ @@ -283,7 +311,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { uint32_t current_pinmux = pad_pinmuxes[pad]; if (current_pinmux == PINMUX_DEFAULT) { - current_pinmux = _sercom_get_default_pad(obj->usart, pad); + current_pinmux = _sercom_get_default_pad(pUSART_S(obj), pad); } if (current_pinmux != PINMUX_UNUSED) { @@ -306,7 +334,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) { } void serial_free(serial_t *obj) { - serial_irq_ids[obj->index] = 0; + serial_irq_ids[serial_get_index(obj)] = 0; } void serial_baud(serial_t *obj, int baudrate) { @@ -321,34 +349,34 @@ void serial_baud(serial_t *obj, int baudrate) { enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC; enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16; - obj->baudrate = baudrate; + pSERIAL_S(obj)->baudrate = baudrate; disable_usart(obj); - sercom_index = _sercom_get_sercom_inst_index(obj->usart); + sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj)); gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE; - obj->generator_source = GCLK_GENERATOR_0; - gclk_chan_conf.source_generator = obj->generator_source; + pSERIAL_S(obj)->generator_source = GCLK_GENERATOR_0; + gclk_chan_conf.source_generator = pSERIAL_S(obj)->generator_source; system_gclk_chan_set_config(gclk_index, &gclk_chan_conf); system_gclk_chan_enable(gclk_index); - sercom_set_gclk_generator(obj->generator_source, false); + sercom_set_gclk_generator(pSERIAL_S(obj)->generator_source, false); /* Get baud value from mode and clock */ - switch (obj->transfer_mode) + switch (pSERIAL_S(obj)->transfer_mode) { case USART_TRANSFER_SYNCHRONOUSLY: - if (!obj->use_external_clock) { - _sercom_get_sync_baud_val(obj->baudrate, + if (!pSERIAL_S(obj)->use_external_clock) { + _sercom_get_sync_baud_val(pSERIAL_S(obj)->baudrate, system_gclk_chan_get_hz(gclk_index), &baud); } break; case USART_TRANSFER_ASYNCHRONOUSLY: - if (obj->use_external_clock) { - _sercom_get_async_baud_val(obj->baudrate, - obj->ext_clock_freq, &baud, mode, sample_num); + if (pSERIAL_S(obj)->use_external_clock) { + _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate, + pSERIAL_S(obj)->ext_clock_freq, &baud, mode, sample_num); } else { - _sercom_get_async_baud_val(obj->baudrate, + _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate, system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num); } break; @@ -385,57 +413,54 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b switch (stop_bits){ case 1: - obj->stopbits = USART_STOPBITS_1; + pSERIAL_S(obj)->stopbits = USART_STOPBITS_1; break; case 2: - obj->stopbits = USART_STOPBITS_2; + pSERIAL_S(obj)->stopbits = USART_STOPBITS_2; break; default: - obj->stopbits = USART_STOPBITS_1; + pSERIAL_S(obj)->stopbits = USART_STOPBITS_1; } switch (parity){ case ParityNone: - obj->parity = USART_PARITY_NONE; + pSERIAL_S(obj)->parity = USART_PARITY_NONE; break; case ParityOdd: - obj->parity = USART_PARITY_ODD; + pSERIAL_S(obj)->parity = USART_PARITY_ODD; break; case ParityEven: - obj->parity = USART_PARITY_EVEN; + pSERIAL_S(obj)->parity = USART_PARITY_EVEN; break; default: - obj->parity = USART_PARITY_NONE; + pSERIAL_S(obj)->parity = USART_PARITY_NONE; } switch (data_bits){ case 5: - obj->character_size = USART_CHARACTER_SIZE_5BIT; + pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_5BIT; break; case 6: - obj->character_size = USART_CHARACTER_SIZE_6BIT; + pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_6BIT; break; case 7: - obj->character_size = USART_CHARACTER_SIZE_7BIT; + pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_7BIT; break; case 8: - obj->character_size = USART_CHARACTER_SIZE_8BIT; - break; - /*case 9: - obj->character_size = USART_CHARACTER_SIZE_9BIT; - break;*/ + pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT; + break; // 9 bit transfer not required in mbed default: - obj->character_size = USART_CHARACTER_SIZE_8BIT; + pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT; } /* Set stopbits, character size and enable transceivers */ - ctrlb = (uint32_t)obj->stopbits | (uint32_t)obj->character_size; + ctrlb = (uint32_t)pSERIAL_S(obj)->stopbits | (uint32_t)pSERIAL_S(obj)->character_size; /* Check parity mode bits */ - if (obj->parity != USART_PARITY_NONE) { + if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) { ctrla |= SERCOM_USART_CTRLA_FORM(1); - ctrlb |= obj->parity; + ctrlb |= pSERIAL_S(obj)->parity; } else { ctrla |= SERCOM_USART_CTRLA_FORM(0); } @@ -458,14 +483,38 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b /****************************************************************************** * INTERRUPTS HANDLING ******************************************************************************/ +/** +* Get index of serial object, relating it to the physical peripheral. +* +* @param obj pointer to serial object +* @return internal index of U(S)ART peripheral +*/ +inline uint8_t serial_get_index(serial_t *obj) +{ + switch ((int)pSERIAL_S(obj)) { + case UART_0: + return 0; + case UART_1: + return 1; + case UART_2: + return 2; + case UART_3: + return 3; + case UART_4: + return 4; + case UART_5: + return 5; + } + return 0; +} static inline void uart_irq(SercomUsart *const usart, uint32_t index) { uint16_t interrupt_status; interrupt_status = usart->INTFLAG.reg; interrupt_status &= usart->INTENSET.reg; if (serial_irq_ids[index] != 0) { - if (interrupt_status & SERCOM_USART_INTFLAG_TXC) // for transmit complete + if (interrupt_status & SERCOM_USART_INTFLAG_TXC) // for transmit complete { - usart->INTENCLR.reg = SERCOM_USART_INTFLAG_TXC; + usart->INTENCLR.reg = SERCOM_USART_INTFLAG_TXC; irq_handler(serial_irq_ids[index], TxIrq); } /*if (interrupt_status & SERCOM_USART_INTFLAG_DRE) // for data ready for transmit @@ -493,15 +542,29 @@ void uart0_irq() { uart_irq((SercomUsart *)UART_0, 0); } -/*#if UART_NUM > 1 -void uart1_irq() {uart_irq(UART1->S1, 1);} -void uart2_irq() {uart_irq(UART2->S1, 2);} -#endif -*/ +void uart1_irq() { + uart_irq((SercomUsart *)UART_1, 0); +} + +void uart2_irq() { + uart_irq((SercomUsart *)UART_2, 0); +} + +void uart3_irq() { + uart_irq((SercomUsart *)UART_3, 0); +} + +void uart4_irq() { + uart_irq((SercomUsart *)UART_4, 0); +} + +void uart5_irq() { + uart_irq((SercomUsart *)UART_5, 0); +} void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { irq_handler = handler; - serial_irq_ids[obj->index] = id; + serial_irq_ids[serial_get_index(obj)] = id; } void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { @@ -512,11 +575,31 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { disable_usart(obj); ctrlb = _USART(obj).CTRLB.reg; - switch ((int)obj->usart) { + switch ((int)pUSART_S(obj)) { case UART_0: - irq_n = SERCOM0_IRQn; - vector = (uint32_t)&uart0_irq; - break; + irq_n = SERCOM0_IRQn; + vector = (uint32_t)&uart0_irq; + break; + case UART_1: + irq_n = SERCOM1_IRQn; + vector = (uint32_t)&uart1_irq; + break; + case UART_2: + irq_n = SERCOM2_IRQn; + vector = (uint32_t)&uart2_irq; + break; + case UART_3: + irq_n = SERCOM3_IRQn; + vector = (uint32_t)&uart3_irq; + break; + case UART_4: + irq_n = SERCOM4_IRQn; + vector = (uint32_t)&uart4_irq; + break; + case UART_5: + irq_n = SERCOM5_IRQn; + vector = (uint32_t)&uart5_irq; + break; } if (enable) { @@ -559,9 +642,6 @@ int serial_getc(serial_t *obj) { void serial_putc(serial_t *obj, int c) { uint16_t q = (c & SERCOM_USART_DATA_MASK); while (!serial_writable(obj)); -// uart_data[obj->index].count++; -// uart_data[obj->index].string[uart_data[obj->index].count] = q; -// _USART(obj).INTENSET.reg = SERCOM_USART_INTFLAG_DRE; _USART(obj).DATA.reg = q; while (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)); // wait till data is sent } @@ -627,7 +707,16 @@ void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable) */ void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width) { + // We only support byte buffers for now + MBED_ASSERT(width == 8); + if(serial_tx_active(obj)) return; + + obj->tx_buff.buffer = tx; + obj->tx_buff.length = tx_length; + obj->tx_buff.pos = 0; + + return; } /** Configure the TX buffer for an asynchronous read serial transaction @@ -638,7 +727,16 @@ void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width) */ void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width) { + // We only support byte buffers for now + MBED_ASSERT(width == 8); + if(serial_rx_active(obj)) return; + + obj->rx_buff.buffer = rx; + obj->rx_buff.length = rx_length; + obj->rx_buff.pos = 0; + + return; } /** Set character to be matched. If an event is enabled, and received character