Skip to content

Commit 651862f

Browse files
WIP SPI SERCOM clock source changes
1 parent 59d869d commit 651862f

File tree

2 files changed

+30
-22
lines changed

2 files changed

+30
-22
lines changed

cores/arduino/SERCOM.cpp

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,24 @@
3030
SERCOM::SERCOM(Sercom* s)
3131
{
3232
sercom = s;
33+
34+
#if defined(__SAMD51__)
35+
// A briefly-available but now deprecated feature had the SPI clock source
36+
// set via a compile-time setting (MAX_SPI)...problem was this affected
37+
// ALL SERCOMs, whereas some (anything read/write, e.g. SD cards) should
38+
// not exceed the standard 24 MHz setting. Newer code, if it needs faster
39+
// write-only SPI (e.g. to screen), should override the SERCOM clock on a
40+
// per-peripheral basis. Nonetheless, we check SERCOM_SPI_FREQ_REF here
41+
// (MAX_SPI * 2) to retain compatibility with any interim projects that
42+
// might have relied on the compile-time setting. But please, don't.
43+
#if SERCOM_SPI_FREQ_REF == F_CPU // F_CPU clock = GCLK0
44+
clockSource = SERCOM_CLOCK_SOURCE_FCPU;
45+
#elif SERCOM_SPI_FREQ_REF == 48000000 // 48 MHz clock = GCLK1 (standard)
46+
clockSource = SERCOM_CLOCK_SOURCE_48M;
47+
#elif SERCOM_SPI_FREQ_REF == 100000000 // 100 MHz clock = GCLK2
48+
clockSource = SERCOM_CLOCK_SOURCE_100M;
49+
#endif
50+
#endif // end __SAMD51__
3351
}
3452

3553
/* =========================
@@ -733,13 +751,17 @@ int8_t SERCOM::getSercomIndex(void) {
733751
// This is currently for overriding an SPI SERCOM's clock source only --
734752
// NOT for UART or WIRE SERCOMs, where it will have unintended consequences.
735753
// It does not check.
736-
void SERCOM::setClockSource(int idx, SercomClockSource src, bool core) {
754+
void SERCOM::setClockSource(int8_t idx, SercomClockSource src, bool core) {
755+
756+
if(src == SERCOM_CLOCK_SOURCE_NO_CHANGE) return;
737757

738758
uint8_t clk_id = core ? sercomData[idx].id_core : sercomData[idx].id_slow;
739759

740760
GCLK->PCHCTRL[clk_id].bit.CHEN = 0; // Disable timer
741761
while(GCLK->PCHCTRL[clk_id].bit.CHEN); // Wait for disable
742762

763+
if(core) clockSource = src; // Save SercomClockSource value
764+
743765
// From cores/arduino/startup.c:
744766
// GCLK0 = F_CPU
745767
// GCLK1 = 48 MHz
@@ -749,7 +771,7 @@ void SERCOM::setClockSource(int idx, SercomClockSource src, bool core) {
749771
if(src == SERCOM_CLOCK_SOURCE_FCPU) {
750772
GCLK->PCHCTRL[clk_id].reg =
751773
GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
752-
if(core) freqRef = F_CPU;
774+
if(core) freqRef = F_CPU; // Save clock frequency value
753775
} else if(src == SERCOM_CLOCK_SOURCE_48M) {
754776
GCLK->PCHCTRL[clk_id].reg =
755777
GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
@@ -772,6 +794,7 @@ void SERCOM::setClockSource(int idx, SercomClockSource src, bool core) {
772794
}
773795
#endif
774796

797+
775798
void SERCOM::initClockNVIC( void )
776799
{
777800
int8_t idx = getSercomIndex();
@@ -785,29 +808,12 @@ void SERCOM::initClockNVIC( void )
785808
NVIC_EnableIRQ(sercomData[idx].irq[i]);
786809
}
787810

788-
// A briefly-availabe but now deprecated feature had the SPI clock source
789-
// set via a compile-time setting (MAX_SPI)...problem was this affected
790-
// ALL SERCOMs, whereas some (anything read/write, e.g. SD cards) should
791-
// not exceed the standard 24 MHz setting. Newer code, if it needs faster
792-
// write-only SPI (e.g. to screen), should override the SERCOM clock on a
793-
// per-peripheral basis. Nonetheless, we check SERCOM_SPI_FREQ_REF here
794-
// (MAX_SPI * 2) to retain compatibility with any interim projects that
795-
// might have relied on the compile-time setting. But please, don't.
796-
797811
// SPI DMA speed is dictated by the "slow clock," so BOTH are set to the
798812
// same clock source (clk_slow isn't sourced from XOSC32K as before).
799813
// This might have power implications for sleep code.
800814

801-
#if SERCOM_SPI_FREQ_REF == F_CPU // F_CPU clock = GCLK0
802-
setClockSource(idx, SERCOM_CLOCK_SOURCE_FCPU, true); // true = core clock
803-
setClockSource(idx, SERCOM_CLOCK_SOURCE_FCPU, false); // false = slow clock
804-
#elif SERCOM_SPI_FREQ_REF == 48000000 // 48 MHz clock = GCLK1 (standard)
805-
setClockSource(idx, SERCOM_CLOCK_SOURCE_48M , true);
806-
setClockSource(idx, SERCOM_CLOCK_SOURCE_48M , false);
807-
#elif SERCOM_SPI_FREQ_REF == 100000000 // 100 MHz clock = GCLK2
808-
setClockSource(idx, SERCOM_CLOCK_SOURCE_100M, true);
809-
setClockSource(idx, SERCOM_CLOCK_SOURCE_100M, false);
810-
#endif
815+
setClockSource(idx, clockSource, true); // true = core clock
816+
setClockSource(idx, clockSource, false); // false = slow clock
811817

812818
#else // end if SAMD51 (prob SAMD21)
813819

cores/arduino/SERCOM.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,15 @@ class SERCOM
233233
uint8_t readDataWIRE( void ) ;
234234
int8_t getSercomIndex(void);
235235
#if defined(__SAMD51__)
236-
void setClockSource(int idx, SercomClockSource src, bool core);
236+
void setClockSource(int8_t idx, SercomClockSource src, bool core);
237+
SercomClockSource getClockSource(void) { return clockSource; };
237238
uint32_t getFreqRef(void) { return freqRef; };
238239
#endif
239240

240241
private:
241242
Sercom* sercom;
242243
#if defined(__SAMD51__)
244+
SercomClockSource clockSource;
243245
uint32_t freqRef;
244246
#endif
245247
uint8_t calculateBaudrateSynchronous(uint32_t baudrate);

0 commit comments

Comments
 (0)