Skip to content

Commit 66a067b

Browse files
committed
enumeration workin' for xtalless samd21g (xtal output for debug) - 32khz not right tho?
1 parent cfd2cca commit 66a067b

File tree

2 files changed

+168
-30
lines changed

2 files changed

+168
-30
lines changed

bootloaders/feather/Makefile

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
# License along with this library; if not, write to the Free Software
1616
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1717

18+
19+
# pick: FEATHER_M0, METRO_M0, FEATHER_SAMR, GEMMA_M0, TRINKET_M0
20+
21+
TARGET=TRINKET_M0
22+
1823
# -----------------------------------------------------------------------------
1924
# Paths
2025
ifeq ($(OS),Windows_NT)
@@ -68,10 +73,27 @@ else
6873
CFLAGS+=-Os -DDEBUG=0
6974
endif
7075

71-
# Adafruit Feather Zero (0x239A 0x000B)
72-
#CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x0B -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23
73-
# Adafruit Feather SAMR (0x239A 0x0014)
74-
CFLAGS_EXTRA?=-D__SAMR21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x14 -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23
76+
ifeq ($(TARGET), FEATHER_M0)
77+
# Adafruit Feather Zero (0x239A 0x000B)
78+
CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x0B -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23
79+
NAME=feather_m0_samd21g18_sam_ba
80+
else ifeq ($(TARGET), METRO_M0)
81+
# Adafruit Metro Zero (0x239A 0x0013)
82+
CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x13 -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23
83+
NAME=metro_m0_samd21g18_sam_ba
84+
else ifeq ($(TARGET), FEATHER_SAMR)
85+
# Adafruit Feather SAMR (0x239A 0x0014)
86+
CFLAGS_EXTRA?=-D__SAMR21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x14 -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23
87+
NAME=feather_samr_samr21g18_sam_ba
88+
else ifeq ($(TARGET), TRINKET_M0)
89+
# Adafruit Trinket M0 (0x239A 0x0016), crystalless *fix chipset*
90+
CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x16 -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23 -DSTRING_MANUFACTURER="Adafruit Industries LLC" -DSTRING_PRODUCT="Adafruit Trinket M0" -DCRYSTALLESS
91+
NAME=trinket_m0_samd21g18_sam_ba
92+
else
93+
# ???
94+
$(error Unknown target, please edit makefile to select FEATHER_M0, METRO_M0, TRINKET_M0 or FEATHER_SAMR )
95+
endif
96+
7597
# Arduino Zero (PID == 0x004D)
7698
# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
7799
# Genuino Zero (PID == 0x024D)
@@ -81,8 +103,6 @@ CFLAGS_EXTRA?=-D__SAMR21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x14 -DUSB_VID_
81103
# Genuino MKR1000 (PID == 0x024E)
82104
# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x02 -DUSB_PID_LOW=0x4E -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
83105

84-
# samd or samr
85-
NAME=samr21_sam_ba
86106

87107
INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/Device/ATMEL/"
88108

bootloaders/feather/board_init.c

Lines changed: 142 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,17 @@
4444

4545
void board_init(void)
4646
{
47+
48+
49+
#if !defined(CRYSTALLESS)
50+
4751
/* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
4852
NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val;
4953

5054
/* Turn on the digital interface clock */
5155
PM->APBAMASK.reg |= PM_APBAMASK_GCLK;
5256

57+
5358
/* ----------------------------------------------------------------------------------------------
5459
* 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
5560
*/
@@ -86,7 +91,7 @@ void board_init(void)
8691
/* Write Generic Clock Generator 1 configuration */
8792
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
8893
GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
89-
// GCLK_GENCTRL_OE | // Output clock to a pin for tests
94+
// GCLK_GENCTRL_OE | // Output clock to a pin for tests
9095
GCLK_GENCTRL_GENEN;
9196

9297
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
@@ -175,29 +180,6 @@ void board_init(void)
175180
/* Wait for synchronization */
176181
}
177182

178-
#if 0
179-
/* ----------------------------------------------------------------------------------------------
180-
* 6) Modify PRESCaler value of OSC8M to have 8MHz
181-
*/
182-
SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_1_Val;
183-
SYSCTRL->OSC8M.bit.ONDEMAND = 0;
184-
185-
/* ----------------------------------------------------------------------------------------------
186-
* 7) Put OSC8M as source for Generic Clock Generator 3
187-
*/
188-
GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ); // Generic Clock Generator 3
189-
190-
/* Write Generic Clock Generator 3 configuration */
191-
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3
192-
GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
193-
// GCLK_GENCTRL_OE | // Output clock to a pin for tests
194-
GCLK_GENCTRL_GENEN;
195-
196-
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
197-
{
198-
/* Wait for synchronization */
199-
}
200-
#endif //0
201183

202184
/*
203185
* Now that all system clocks are configured, we can set CPU and APBx BUS clocks.
@@ -207,4 +189,140 @@ void board_init(void)
207189
PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val;
208190
PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val;
209191
PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val;
192+
#else
193+
194+
/////////////////////////////////////////
195+
196+
/* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
197+
NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val;
198+
199+
////////////////////////////////////////
200+
uint32_t temp_genctrl_config = 0;
201+
202+
// ENABLE OUTPUT OF GENCLK 0 on D2 (PA14)
203+
// Write to the PINCFG register to enable the peripheral multiplexer
204+
PORT->Group[0].PINCFG[14].reg = 1;
205+
// Enable peripheral function H for PA14, refer chapter I/O Multiplexing in the device datasheet
206+
PORT->Group[0].PMUX[7].bit.PMUXE = 7;
207+
208+
// ENABLE OUTPUT OF GENCLK 1 on D5 (PA15)
209+
// Write to the PINCFG register to enable the peripheral multiplexer
210+
PORT->Group[0].PINCFG[15].reg = 1;
211+
// Enable peripheral function H for PA15, refer chapter I/O Multiplexing in the device datasheet
212+
PORT->Group[0].PMUX[7].bit.PMUXO = 7;
213+
214+
// ENABLE OUTPUT OF GENCLK 2 on D11 (PA16) - should be OSC8M @ 8MHz
215+
// Write to the PINCFG register to enable the peripheral multiplexer
216+
PORT->Group[0].PINCFG[16].reg = 1;
217+
// Enable peripheral function H for PA16, refer chapter I/O Multiplexing in the device datasheet
218+
PORT->Group[0].PMUX[8].bit.PMUXE = 7;
219+
220+
221+
/////////////////////////////////////////////////
222+
223+
/* Set OSC8M prescalar to divide by 1, now gclk0 is @ 8mhz */
224+
SYSCTRL->OSC8M.bit.PRESC = 0;
225+
226+
227+
/* ----------------------------------------------------------------------------------------------
228+
* 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
229+
*/
230+
231+
uint32_t calib = (*((uint32_t *) SYSCTRL_FUSES_OSC32K_ADDR) & SYSCTRL_FUSES_OSC32K_Msk) >> SYSCTRL_FUSES_OSC32K_Pos;
232+
233+
SYSCTRL->OSC32K.reg = SYSCTRL_OSC32K_CALIB(calib) | SYSCTRL_OSC32K_STARTUP( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
234+
SYSCTRL_OSC32K_EN32K | SYSCTRL_OSC32K_ENABLE;
235+
236+
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY) == 0 ); // Wait for oscillator stabilization
237+
238+
/* ----------------------------------------------------------------------------------------------
239+
* 2) Put OSC32K as source of Generic Clock Generator 1
240+
*/
241+
242+
GCLK_GENCTRL_Type genctrl={0};
243+
uint32_t temp_genctrl;
244+
245+
GCLK->GENCTRL.bit.ID = 1; // Read GENERATOR_ID - GCLK_GEN_1
246+
247+
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); // wait for data to be ready
248+
249+
temp_genctrl = GCLK->GENCTRL.reg;
250+
genctrl.bit.SRC = GCLK_GENCTRL_SRC_OSC32K_Val; // gclk 1 is now = osc32k
251+
genctrl.bit.GENEN = 1;
252+
genctrl.bit.RUNSTDBY = 0;
253+
genctrl.bit.OE = 1; // output on GCLK_IO[1] pin for debugging
254+
255+
GCLK->GENCTRL.reg = (genctrl.reg | temp_genctrl); // set it!
256+
257+
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
258+
259+
260+
/* Configure OSC8M as source for GCLK_GEN 2 */
261+
GCLK->GENCTRL.bit.ID = 2; // Read GENERATOR_ID - GCLK_GEN_2
262+
263+
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); // wait for data to be ready
264+
265+
temp_genctrl = GCLK->GENCTRL.reg;
266+
genctrl.bit.SRC = GCLK_GENCTRL_SRC_OSC8M_Val; // gclk 2 is now = osc8m
267+
genctrl.bit.GENEN = 1;
268+
genctrl.bit.RUNSTDBY = 0;
269+
genctrl.bit.OE = 1; // output on GCLK_IO[2] pin for debugging
270+
GCLK->GENCTRL.reg = (genctrl.reg | temp_genctrl); // set it!
271+
272+
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
273+
274+
// Turn on DFLL
275+
SYSCTRL_DFLLCTRL_Type dfllctrl_conf = {0};
276+
SYSCTRL_DFLLVAL_Type dfllval_conf = {0};
277+
uint32_t coarse =( *((uint32_t *)(NVMCTRL_OTP4)
278+
+ (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32))
279+
>> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32))
280+
& ((1 << 6) - 1);
281+
if (coarse == 0x3f) {
282+
coarse = 0x1f;
283+
}
284+
uint32_t fine =( *((uint32_t *)(NVMCTRL_OTP4)
285+
+ (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32))
286+
>> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32))
287+
& ((1 << 10) - 1);
288+
if (fine == 0x3ff) {
289+
fine = 0x1ff;
290+
}
291+
dfllval_conf.bit.COARSE = coarse;
292+
dfllval_conf.bit.FINE = fine;
293+
dfllctrl_conf.bit.USBCRM = 1; // usb correction
294+
dfllctrl_conf.bit.BPLCKC = 0;
295+
dfllctrl_conf.bit.QLDIS = 0;
296+
dfllctrl_conf.bit.CCDIS = 1;
297+
dfllctrl_conf.bit.ENABLE = 1;
298+
299+
SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0;
300+
while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY));
301+
SYSCTRL->DFLLMUL.reg = 48000;
302+
SYSCTRL->DFLLVAL.reg = dfllval_conf.reg;
303+
SYSCTRL->DFLLCTRL.reg = dfllctrl_conf.reg;
304+
305+
//
306+
GCLK_CLKCTRL_Type clkctrl={0};
307+
uint16_t temp;
308+
GCLK->CLKCTRL.bit.ID = 2; // GCLK_ID - DFLL48M Reference
309+
temp = GCLK->CLKCTRL.reg;
310+
clkctrl.bit.CLKEN = 1;
311+
clkctrl.bit.WRTLOCK = 0;
312+
clkctrl.bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val;
313+
GCLK->CLKCTRL.reg = (clkctrl.reg | temp);
314+
315+
// Configure DFLL48M as source for GCLK_GEN 0
316+
GCLK->GENCTRL.bit.ID = 0; // GENERATOR_ID - GCLK_GEN_0
317+
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
318+
temp_genctrl = GCLK->GENCTRL.reg;
319+
genctrl.bit.SRC = GCLK_GENCTRL_SRC_DFLL48M_Val;
320+
genctrl.bit.GENEN = 1;
321+
genctrl.bit.RUNSTDBY = 0;
322+
genctrl.bit.OE = 1;
323+
GCLK->GENCTRL.reg = (genctrl.reg | temp_genctrl);
324+
while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
325+
326+
#endif
327+
210328
}

0 commit comments

Comments
 (0)