mirror of https://github.com/ARMmbed/mbed-os.git
* Pin mux logic added for sercom
* added support for 6 uarts in code. * updated gpio for output setting * updated device.h for adding async apis for serialpull/1214/head
parent
98d628b67f
commit
a7b2cee60d
|
@ -33,7 +33,12 @@ extern "C" {
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
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;
|
} UARTName;
|
||||||
/*
|
/*
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "PeripheralNames.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***************/
|
/************RTC***************/
|
||||||
//extern const PinMap PinMap_RTC[];
|
//extern const PinMap PinMap_RTC[];
|
||||||
|
|
||||||
|
@ -46,4 +48,6 @@ extern const PinMap PinMap_UART_RX[];
|
||||||
/************PWM***************/
|
/************PWM***************/
|
||||||
//extern const PinMap PinMap_PWM[];
|
//extern const PinMap PinMap_PWM[];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -94,9 +94,13 @@ typedef enum {
|
||||||
PB29 = 61,
|
PB29 = 61,
|
||||||
PB30 = 62,
|
PB30 = 62,
|
||||||
PB31 = 63,
|
PB31 = 63,
|
||||||
|
|
||||||
|
PC16 = 64,
|
||||||
|
PC18 = 65,
|
||||||
|
PC19 = 66,
|
||||||
|
|
||||||
USBTX = PA04,
|
USBTX = PA04,
|
||||||
USBRX = PA05,
|
USBRX = PA05,
|
||||||
|
|
||||||
// Not connected
|
// Not connected
|
||||||
NC = (int)0xFFFFFFFF
|
NC = (int)0xFFFFFFFF
|
||||||
|
|
|
@ -16,6 +16,18 @@
|
||||||
|
|
||||||
#include "PeripheralPins.h"
|
#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***************/
|
/************RTC***************/
|
||||||
const PinMap PinMap_RTC[] = {
|
const PinMap PinMap_RTC[] = {
|
||||||
};
|
};
|
||||||
|
@ -60,3 +72,438 @@ const PinMap PinMap_SPI_SSEL[] = {
|
||||||
/************PWM***************/
|
/************PWM***************/
|
||||||
const PinMap PinMap_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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#define DEVICE_SERIAL 1
|
#define DEVICE_SERIAL 1
|
||||||
#define DEVICE_SERIAL_FC 1
|
#define DEVICE_SERIAL_FC 1
|
||||||
|
#define DEVICE_SERIAL_ASYNCH 1
|
||||||
|
|
||||||
#define DEVICE_I2C 0
|
#define DEVICE_I2C 0
|
||||||
#define DEVICE_I2CSLAVE 0
|
#define DEVICE_I2CSLAVE 0
|
||||||
|
|
|
@ -79,7 +79,7 @@ void gpio_dir(gpio_t *obj, PinDirection direction) {
|
||||||
pin_conf.direction = PORT_PIN_DIR_INPUT;
|
pin_conf.direction = PORT_PIN_DIR_INPUT;
|
||||||
break;
|
break;
|
||||||
case PIN_OUTPUT:
|
case PIN_OUTPUT:
|
||||||
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
|
pin_conf.direction = /*PORT_PIN_DIR_OUTPUT*/PORT_PIN_DIR_OUTPUT_WTH_READBACK;
|
||||||
break;
|
break;
|
||||||
case PIN_INPUT_OUTPUT:
|
case PIN_INPUT_OUTPUT:
|
||||||
pin_conf.direction = PORT_PIN_DIR_OUTPUT_WTH_READBACK;
|
pin_conf.direction = PORT_PIN_DIR_OUTPUT_WTH_READBACK;
|
||||||
|
|
|
@ -22,9 +22,18 @@
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
#include "samr21_xplained_pro.h"
|
#include "samr21_xplained_pro.h"
|
||||||
|
|
||||||
#define _USART(obj) obj->usart->USART
|
#if DEVICE_SERIAL_ASYNCH
|
||||||
#define USART_NUM 1 // for SAMR21 // to be updated for samd21
|
#define pUSART_S(obj) obj->serial.usart
|
||||||
//#define USART_BUF 8
|
#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 uint32_t serial_irq_ids[USART_NUM] = {0};
|
||||||
static uart_irq_handler irq_handler;
|
static uart_irq_handler irq_handler;
|
||||||
|
@ -32,13 +41,6 @@ static uart_irq_handler irq_handler;
|
||||||
int stdio_uart_inited = 0;
|
int stdio_uart_inited = 0;
|
||||||
serial_t stdio_uart;
|
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;
|
extern uint8_t g_sys_init;
|
||||||
|
|
||||||
static inline bool usart_syncing(serial_t *obj)
|
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
|
#if USART_CALLBACK_MODE == true //TODO: to be implemented
|
||||||
/* Enable Global interrupt for module */
|
/* 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
|
#endif
|
||||||
|
|
||||||
/* Wait until synchronization is complete */
|
/* 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
|
#if USART_CALLBACK_MODE == true //TODO: to be implemented
|
||||||
/* Disable Global interrupt for module */
|
/* 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
|
#endif
|
||||||
/* Wait until synchronization is complete */
|
/* Wait until synchronization is complete */
|
||||||
usart_syncing(obj);
|
usart_syncing(obj);
|
||||||
|
@ -100,7 +102,7 @@ static enum status_code usart_set_config_asf( serial_t *obj)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Index for generic clock */
|
/* 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;
|
uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
|
||||||
|
|
||||||
/* Cache new register values to minimize the number of register writes */
|
/* 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;
|
enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
|
||||||
|
|
||||||
/* Set data order, internal muxing, and clock polarity */
|
/* Set data order, internal muxing, and clock polarity */
|
||||||
ctrla = (uint32_t)obj->data_order |
|
ctrla = (uint32_t)pSERIAL_S(obj)->data_order |
|
||||||
(uint32_t)obj->mux_setting |
|
(uint32_t)pSERIAL_S(obj)->mux_setting |
|
||||||
#ifdef FEATURE_USART_OVER_SAMPLE
|
#ifdef FEATURE_USART_OVER_SAMPLE
|
||||||
obj->sample_adjustment |
|
pSERIAL_S(obj)->sample_adjustment |
|
||||||
obj->sample_rate |
|
pSERIAL_S(obj)->sample_rate |
|
||||||
#endif
|
#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 */
|
/* Get baud value from mode and clock */
|
||||||
switch (obj->transfer_mode)
|
switch (pSERIAL_S(obj)->transfer_mode)
|
||||||
{
|
{
|
||||||
case USART_TRANSFER_SYNCHRONOUSLY:
|
case USART_TRANSFER_SYNCHRONOUSLY:
|
||||||
if (!obj->use_external_clock) {
|
if (!pSERIAL_S(obj)->use_external_clock) {
|
||||||
_sercom_get_sync_baud_val(obj->baudrate,
|
_sercom_get_sync_baud_val(pSERIAL_S(obj)->baudrate,
|
||||||
system_gclk_chan_get_hz(gclk_index), &baud);
|
system_gclk_chan_get_hz(gclk_index), &baud);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USART_TRANSFER_ASYNCHRONOUSLY:
|
case USART_TRANSFER_ASYNCHRONOUSLY:
|
||||||
if (obj->use_external_clock) {
|
if (pSERIAL_S(obj)->use_external_clock) {
|
||||||
_sercom_get_async_baud_val(obj->baudrate,
|
_sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate,
|
||||||
obj->ext_clock_freq, &baud, mode, sample_num);
|
pSERIAL_S(obj)->ext_clock_freq, &baud, mode, sample_num);
|
||||||
} else {
|
} 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);
|
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;
|
_USART(obj).BAUD.reg = baud;
|
||||||
|
|
||||||
/* Set sample mode */
|
/* 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);
|
ctrla |= SERCOM_USART_CTRLA_MODE(0x1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -160,23 +162,23 @@ static enum status_code usart_set_config_asf( serial_t *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set stopbits, character size and enable transceivers */
|
/* 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
|
#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
|
#endif
|
||||||
(obj->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) |
|
(pSERIAL_S(obj)->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) |
|
||||||
(obj->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos);
|
(pSERIAL_S(obj)->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos);
|
||||||
|
|
||||||
/* Check parity mode bits */
|
/* Check parity mode bits */
|
||||||
if (obj->parity != USART_PARITY_NONE) {
|
if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) {
|
||||||
ctrla |= SERCOM_USART_CTRLA_FORM(1);
|
ctrla |= SERCOM_USART_CTRLA_FORM(1);
|
||||||
ctrlb |= obj->parity;
|
ctrlb |= pSERIAL_S(obj)->parity;
|
||||||
} else {
|
} else {
|
||||||
ctrla |= SERCOM_USART_CTRLA_FORM(0);
|
ctrla |= SERCOM_USART_CTRLA_FORM(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set whether module should run in standby. */
|
/* 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;
|
ctrla |= SERCOM_USART_CTRLA_RUNSTDBY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +197,30 @@ static enum status_code usart_set_config_asf( serial_t *obj)
|
||||||
return STATUS_OK;
|
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) {
|
void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
if (g_sys_init == 0) {
|
if (g_sys_init == 0) {
|
||||||
system_init();
|
system_init();
|
||||||
|
@ -202,49 +228,51 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct system_gclk_chan_config gclk_chan_conf;
|
struct system_gclk_chan_config gclk_chan_conf;
|
||||||
|
UARTName uart;
|
||||||
uint32_t gclk_index;
|
uint32_t gclk_index;
|
||||||
uint32_t pm_index;
|
uint32_t pm_index;
|
||||||
uint32_t sercom_index = 0;
|
uint32_t sercom_index = 0;
|
||||||
|
uint32_t muxsetting = 0;
|
||||||
obj->usart = EXT1_UART_MODULE;
|
uint32_t padsetting[4] = {0};
|
||||||
|
|
||||||
|
pUSART_S(obj) = EXT1_UART_MODULE;
|
||||||
|
|
||||||
/* Disable USART module */
|
/* Disable USART module */
|
||||||
disable_usart(obj);
|
disable_usart(obj);
|
||||||
|
|
||||||
/* Set default config to object */
|
get_default_serial_values(obj);
|
||||||
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;
|
|
||||||
|
|
||||||
obj->mux_setting = EDBG_CDC_SERCOM_MUX_SETTING; // to be done according to the pin received from user
|
find_pin_settings(tx, rx, NC, &padsetting[0]); // tx, rx, clk, pad array // getting pads from pins
|
||||||
obj->pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
|
muxsetting = find_mux_setting(tx, rx, NC); // getting mux setting from pins
|
||||||
obj->pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
|
sercom_index = pinmap_sercom_peripheral(tx, rx); // same variable sercom_index reused for optimization
|
||||||
obj->pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
|
switch (sercom_index){
|
||||||
obj->pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
|
case 0:
|
||||||
|
uart = UART_0;
|
||||||
//TODO: now noly UART0. code to get the SERCOM instance from Pins (pinmapping) to be added later
|
break;
|
||||||
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
|
case 1:
|
||||||
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
|
uart = UART_1;
|
||||||
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
|
break;
|
||||||
|
case 2:
|
||||||
sercom_index = _sercom_get_sercom_inst_index(obj->usart);
|
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;
|
pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
|
||||||
gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
|
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);
|
system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
|
||||||
|
|
||||||
/* Set up the GCLK for the module */
|
/* Set up the GCLK for the module */
|
||||||
obj->generator_source = GCLK_GENERATOR_0;
|
pSERIAL_S(obj)->generator_source = GCLK_GENERATOR_0;
|
||||||
gclk_chan_conf.source_generator = obj->generator_source;
|
gclk_chan_conf.source_generator = pSERIAL_S(obj)->generator_source;
|
||||||
system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
|
system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
|
||||||
system_gclk_chan_enable(gclk_index);
|
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 */
|
/* Set configuration according to the config struct */
|
||||||
usart_set_config_asf(obj);
|
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;
|
pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
|
||||||
|
|
||||||
uint32_t pad_pinmuxes[] = {
|
uint32_t pad_pinmuxes[] = {
|
||||||
obj->pinmux_pad0, obj->pinmux_pad1,
|
pSERIAL_S(obj)->pinmux_pad0, pSERIAL_S(obj)->pinmux_pad1,
|
||||||
obj->pinmux_pad2, obj->pinmux_pad3
|
pSERIAL_S(obj)->pinmux_pad2, pSERIAL_S(obj)->pinmux_pad3
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Configure the SERCOM pins according to the user configuration */
|
/* 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];
|
uint32_t current_pinmux = pad_pinmuxes[pad];
|
||||||
|
|
||||||
if (current_pinmux == PINMUX_DEFAULT) {
|
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) {
|
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) {
|
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) {
|
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_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
|
||||||
enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
|
enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
|
||||||
|
|
||||||
obj->baudrate = baudrate;
|
pSERIAL_S(obj)->baudrate = baudrate;
|
||||||
disable_usart(obj);
|
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;
|
gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
|
||||||
|
|
||||||
obj->generator_source = GCLK_GENERATOR_0;
|
pSERIAL_S(obj)->generator_source = GCLK_GENERATOR_0;
|
||||||
gclk_chan_conf.source_generator = obj->generator_source;
|
gclk_chan_conf.source_generator = pSERIAL_S(obj)->generator_source;
|
||||||
system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
|
system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
|
||||||
system_gclk_chan_enable(gclk_index);
|
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 */
|
/* Get baud value from mode and clock */
|
||||||
switch (obj->transfer_mode)
|
switch (pSERIAL_S(obj)->transfer_mode)
|
||||||
{
|
{
|
||||||
case USART_TRANSFER_SYNCHRONOUSLY:
|
case USART_TRANSFER_SYNCHRONOUSLY:
|
||||||
if (!obj->use_external_clock) {
|
if (!pSERIAL_S(obj)->use_external_clock) {
|
||||||
_sercom_get_sync_baud_val(obj->baudrate,
|
_sercom_get_sync_baud_val(pSERIAL_S(obj)->baudrate,
|
||||||
system_gclk_chan_get_hz(gclk_index), &baud);
|
system_gclk_chan_get_hz(gclk_index), &baud);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USART_TRANSFER_ASYNCHRONOUSLY:
|
case USART_TRANSFER_ASYNCHRONOUSLY:
|
||||||
if (obj->use_external_clock) {
|
if (pSERIAL_S(obj)->use_external_clock) {
|
||||||
_sercom_get_async_baud_val(obj->baudrate,
|
_sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate,
|
||||||
obj->ext_clock_freq, &baud, mode, sample_num);
|
pSERIAL_S(obj)->ext_clock_freq, &baud, mode, sample_num);
|
||||||
} else {
|
} 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);
|
system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -385,57 +413,54 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
|
||||||
|
|
||||||
switch (stop_bits){
|
switch (stop_bits){
|
||||||
case 1:
|
case 1:
|
||||||
obj->stopbits = USART_STOPBITS_1;
|
pSERIAL_S(obj)->stopbits = USART_STOPBITS_1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
obj->stopbits = USART_STOPBITS_2;
|
pSERIAL_S(obj)->stopbits = USART_STOPBITS_2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
obj->stopbits = USART_STOPBITS_1;
|
pSERIAL_S(obj)->stopbits = USART_STOPBITS_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (parity){
|
switch (parity){
|
||||||
case ParityNone:
|
case ParityNone:
|
||||||
obj->parity = USART_PARITY_NONE;
|
pSERIAL_S(obj)->parity = USART_PARITY_NONE;
|
||||||
break;
|
break;
|
||||||
case ParityOdd:
|
case ParityOdd:
|
||||||
obj->parity = USART_PARITY_ODD;
|
pSERIAL_S(obj)->parity = USART_PARITY_ODD;
|
||||||
break;
|
break;
|
||||||
case ParityEven:
|
case ParityEven:
|
||||||
obj->parity = USART_PARITY_EVEN;
|
pSERIAL_S(obj)->parity = USART_PARITY_EVEN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
obj->parity = USART_PARITY_NONE;
|
pSERIAL_S(obj)->parity = USART_PARITY_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (data_bits){
|
switch (data_bits){
|
||||||
case 5:
|
case 5:
|
||||||
obj->character_size = USART_CHARACTER_SIZE_5BIT;
|
pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_5BIT;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
obj->character_size = USART_CHARACTER_SIZE_6BIT;
|
pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_6BIT;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
obj->character_size = USART_CHARACTER_SIZE_7BIT;
|
pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_7BIT;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
obj->character_size = USART_CHARACTER_SIZE_8BIT;
|
pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT;
|
||||||
break;
|
break; // 9 bit transfer not required in mbed
|
||||||
/*case 9:
|
|
||||||
obj->character_size = USART_CHARACTER_SIZE_9BIT;
|
|
||||||
break;*/
|
|
||||||
default:
|
default:
|
||||||
obj->character_size = USART_CHARACTER_SIZE_8BIT;
|
pSERIAL_S(obj)->character_size = USART_CHARACTER_SIZE_8BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Set stopbits, character size and enable transceivers */
|
/* 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 */
|
/* Check parity mode bits */
|
||||||
if (obj->parity != USART_PARITY_NONE) {
|
if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) {
|
||||||
ctrla |= SERCOM_USART_CTRLA_FORM(1);
|
ctrla |= SERCOM_USART_CTRLA_FORM(1);
|
||||||
ctrlb |= obj->parity;
|
ctrlb |= pSERIAL_S(obj)->parity;
|
||||||
} else {
|
} else {
|
||||||
ctrla |= SERCOM_USART_CTRLA_FORM(0);
|
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
|
* 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) {
|
static inline void uart_irq(SercomUsart *const usart, uint32_t index) {
|
||||||
uint16_t interrupt_status;
|
uint16_t interrupt_status;
|
||||||
interrupt_status = usart->INTFLAG.reg;
|
interrupt_status = usart->INTFLAG.reg;
|
||||||
interrupt_status &= usart->INTENSET.reg;
|
interrupt_status &= usart->INTENSET.reg;
|
||||||
if (serial_irq_ids[index] != 0) {
|
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);
|
irq_handler(serial_irq_ids[index], TxIrq);
|
||||||
}
|
}
|
||||||
/*if (interrupt_status & SERCOM_USART_INTFLAG_DRE) // for data ready for transmit
|
/*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);
|
uart_irq((SercomUsart *)UART_0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*#if UART_NUM > 1
|
void uart1_irq() {
|
||||||
void uart1_irq() {uart_irq(UART1->S1, 1);}
|
uart_irq((SercomUsart *)UART_1, 0);
|
||||||
void uart2_irq() {uart_irq(UART2->S1, 2);}
|
}
|
||||||
#endif
|
|
||||||
*/
|
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) {
|
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
|
||||||
irq_handler = handler;
|
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) {
|
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);
|
disable_usart(obj);
|
||||||
ctrlb = _USART(obj).CTRLB.reg;
|
ctrlb = _USART(obj).CTRLB.reg;
|
||||||
|
|
||||||
switch ((int)obj->usart) {
|
switch ((int)pUSART_S(obj)) {
|
||||||
case UART_0:
|
case UART_0:
|
||||||
irq_n = SERCOM0_IRQn;
|
irq_n = SERCOM0_IRQn;
|
||||||
vector = (uint32_t)&uart0_irq;
|
vector = (uint32_t)&uart0_irq;
|
||||||
break;
|
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) {
|
if (enable) {
|
||||||
|
@ -559,9 +642,6 @@ int serial_getc(serial_t *obj) {
|
||||||
void serial_putc(serial_t *obj, int c) {
|
void serial_putc(serial_t *obj, int c) {
|
||||||
uint16_t q = (c & SERCOM_USART_DATA_MASK);
|
uint16_t q = (c & SERCOM_USART_DATA_MASK);
|
||||||
while (!serial_writable(obj));
|
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;
|
_USART(obj).DATA.reg = q;
|
||||||
while (!(_USART(obj).INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)); // wait till data is sent
|
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)
|
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
|
/** 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)
|
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
|
/** Set character to be matched. If an event is enabled, and received character
|
||||||
|
|
Loading…
Reference in New Issue