From 3c6f9b55f7700ce480e8feb77b78486f01abbc67 Mon Sep 17 00:00:00 2001 From: Jonathan BAUDIN <jonathan.baudin@atmel.com> Date: Fri, 9 May 2014 14:07:29 +0200 Subject: [PATCH] Initialize clock --- cores/arduino/SERCOM.cpp | 122 ++++++++++++++++++++++-------- cores/arduino/SERCOM.h | 5 +- variants/arduino_zero/variant.cpp | 42 +++++----- 3 files changed, 113 insertions(+), 56 deletions(-) diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index 99b3ed57..4fdd9f44 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -1,18 +1,27 @@ #include "SERCOM.h" -SERCOM::SERCOM(Sercom* sercom) +SERCOM::SERCOM(Sercom* s) { - this->sercom = sercom; + sercom = s; } /* ========================= * ===== Sercom UART * ========================= */ +// Constants for Clock multiplexers +#define GENERIC_CLOCK_SERCOM0 (0x14ul) +#define GENERIC_CLOCK_SERCOM1 (0x15ul) +#define GENERIC_CLOCK_SERCOM2 (0x16ul) +#define GENERIC_CLOCK_SERCOM3 (0x17ul) +#define GENERIC_CLOCK_SERCOM4 (0x18ul) +#define GENERIC_CLOCK_SERCOM5 (0x19ul) + void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { resetUART(); + initClock(); //Setting the CTRLA register sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | @@ -35,7 +44,13 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint sampleRateValue = 3; //Asynchronous arithmetic mode - sercom->USART.BAUD.reg = 65535 * ( 1 - sampleRateValue * division(baudrate,SERCOM_FREQ_REF)); + //sercom->USART.BAUD.reg = 65535 * ( 1 - sampleRateValue * division(baudrate,SERCOM_FREQ_REF)); + int tmpBaud = (baudrate / SERCOM_FREQ_REF); + tmpBaud = ( 1 - sampleRateValue * tmpBaud); + tmpBaud = (65535ul) * tmpBaud; + + tmpBaud = 40369; + sercom->USART.BAUD.reg = tmpBaud; } } void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits) @@ -132,7 +147,7 @@ int SERCOM::writeDataUART(uint8_t data) flushUART(); //Put data into DATA register - sercom->USART.DATA.bit.DATA = data; + sercom->USART.DATA.reg = (uint16_t)data; return 1; } @@ -155,7 +170,7 @@ void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize ch (0x1ul) << SERCOM_SPI_CTRLB_RXEN_Pos; //Active the SPI receiver. } -void SERCOM::initClock(SercomSpiClockMode clockMode, uint32_t baudrate) +void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate) { //Extract data from clockMode int cpha, cpol; @@ -291,36 +306,77 @@ uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate) uint32_t SERCOM::division(uint32_t dividend, uint32_t divisor) { - // division WITHOUT division operator + //// division WITHOUT division operator + // + //uint32_t denom = divisor; + //uint32_t current = 1; + //uint32_t answer = 0; +// + //if ( denom > dividend) + //return 0; +// + //if ( denom == dividend) + //return 1; +// + //while (denom <= dividend) { + //denom <<= 1; + //current <<= 1; + //} +// + //denom >>= 1; + //current >>= 1; +// + //while (current!=0) { + //if ( dividend >= denom) { + //dividend -= denom; + //answer |= current; + //} + //current >>= 1; + //denom >>= 1; + //} + // + //return answer; +} + +void SERCOM::initClock() +{ + uint8_t clockId; + + if(sercom == SERCOM0) + { + clockId = GENERIC_CLOCK_SERCOM0; + } + else if(sercom == SERCOM1) + { + clockId = GENERIC_CLOCK_SERCOM1; + } + else if(sercom == SERCOM2) + { + clockId = GENERIC_CLOCK_SERCOM2; + } + else if(sercom == SERCOM3) + { + clockId = GENERIC_CLOCK_SERCOM3; + } + else if(sercom == SERCOM4) + { + clockId = GENERIC_CLOCK_SERCOM4; + } + else if(sercom == SERCOM5) + { + clockId = GENERIC_CLOCK_SERCOM5; + } - uint32_t denom = divisor; - uint32_t current = 1; - uint32_t answer = 0; - - if ( denom > dividend) - return 0; - - if ( denom == dividend) - return 1; + //Setting clock + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOM0) + GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source + GCLK_CLKCTRL_CLKEN ; + - while (denom <= dividend) { - denom <<= 1; - current <<= 1; - } - - denom >>= 1; - current >>= 1; - - while (current!=0) { - if ( dividend >= denom) { - dividend -= denom; - answer |= current; - } - current >>= 1; - denom >>= 1; - } - - return answer; + while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) + { + /* Wait for synchronization */ + } } diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h index 3bbeca22..86b2a2ca 100644 --- a/cores/arduino/SERCOM.h +++ b/cores/arduino/SERCOM.h @@ -127,7 +127,7 @@ typedef enum class SERCOM { public: - SERCOM(Sercom* sercom); + SERCOM(Sercom* s); /* ========== SERCOM OBJECT ========== */ static SERCOM * sercom0; @@ -156,7 +156,7 @@ class SERCOM /* ========== SPI ========== */ void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder); - void initClock(SercomSpiClockMode clockMode, uint32_t baudrate); + void initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate); void resetSPI(); void enableSPI(); @@ -198,6 +198,7 @@ class SERCOM Sercom* sercom; uint8_t calculateBaudrateSynchronous(uint32_t baudrate); uint32_t division(uint32_t dividend, uint32_t divisor); + void initClock(); }; #endif diff --git a/variants/arduino_zero/variant.cpp b/variants/arduino_zero/variant.cpp index de13f0b5..2a6c7522 100644 --- a/variants/arduino_zero/variant.cpp +++ b/variants/arduino_zero/variant.cpp @@ -87,11 +87,11 @@ */ const PinDescription g_APinDescription[]= { - // 0 .. 19 - Digital pins - // ---------------------- - // 0/1 - SERCOM/UART (Serial) - { PORTA, 10, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RX: SERCOM0/PAD[2] - { PORTA, 11, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // TX: SERCOM0/PAD[3] + // 0 .. 19 - Digital pins + // ---------------------- + // 0/1 - SERCOM/UART (Serial) + { PORTA, 10, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RX: SERCOM0/PAD[2] + { PORTA, 11, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // TX: SERCOM0/PAD[3] // 2..12 { PORTA, 8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0 }, // TCC0/WO[0] @@ -116,28 +116,28 @@ const PinDescription g_APinDescription[]= { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // DAC/VREFP // 16..17 I2C (SDA/SCL) - { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SDA: SERCOM3/PAD[0] - { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCL: SERCOM3/PAD[1] + { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SDA: SERCOM3/PAD[0] + { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCL: SERCOM3/PAD[1] // 18..23 SPI (ICSP:MISO,SCK,MOSI) - { PORTA, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MISO: SERCOM4/PAD[0] - { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // 5V0 - { PORTB, 11, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCK: SERCOM4/PAD[3] - { PORTB, 10, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI: SERCOM4/PAD[2] - { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RESET - { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // GND - - // 24..29 - Analog pins + { PORTA, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MISO: SERCOM4/PAD[0] + { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // 5V0 + { PORTB, 11, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCK: SERCOM4/PAD[3] + { PORTB, 10, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI: SERCOM4/PAD[2] + { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RESET + { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // GND + + // 24..29 - Analog pins // -------------------- // 24 - A0 (DAC output) { PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER }, // DAC/VOUT // 25..29 - A1-A5 - { PORTB, 8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[2] - { PORTB, 9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[3] - { PORTA, 4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[4] - { PORTA, 5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[5] - { PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[10] + { PORTB, 8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[2] + { PORTB, 9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[3] + { PORTA, 4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[4] + { PORTA, 5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[5] + { PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER }, // ADC/AIN[10] // 30..31 - RX/TX LEDS (PB03/PA27) { PORTB, 3, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // use as pure output @@ -148,4 +148,4 @@ const PinDescription g_APinDescription[]= { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DM { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DP -} ; +} ; \ No newline at end of file -- GitLab