While my bread-and-butter micro has been the SAMD51, I have an application where the ATSAMD09 is the perfect fit (by spec). I don't actually need much more than to configure some clocks, as all I'm using the D09 for is as a integer-N prescalar. As such, the core of my need is to manipulate the GCLK resources. Reading over the DS, unlike the D51 where you can manipulate the resource through individual bit operations, the D09/D21 must be written to "in bulk" or with all settings in one go. No problem, I can switch my methods to just OR'ing values. The datasheet also indicates you must 1. set the divisor first, 2. set the generator resource, then 3. set the Clock resource (if you're using it).
My finding is that any write to the GCLK peripheral crashes the part. For example:
pGCLK->generatorDivisor = DIVIDE_BY_1 | GCLK_ID1;
Locks the part. Using the SAMICE debugger, you can pause before hand and it responds fine. You step into this instruction, and the system hangs. Pausing the debugger does nothing.
Now traditionally, this kind of behavior has me looking at the address mapping of a peripheral, and then to the register itself should the general mapping be correct. In this case, the root resource GCLK is correctly mapped to 0x4000C00; the division register is correctly offset by 8 bytes (0x4000C08). Other issues I have considered was perhaps (somehow) the GCLK resource in the power manager was janky, but no, the GCLK resource is enabled (1) in APBAMASK.
Now proceeding, just to be thorough, I went to the generator control. The following line:
pGCLK->generatorControl = GCLK_ID1 | GCLK_GEN_SOURCE_OSC8M | GCLK_GEN_ENABLE | GCLK_OUTPUT_ENABLE; // Use the int 8M osc, route to gen 1, enable output and generator
Also causes the part to lock up. And both do this on ID0 as well. The current program, just to figure out the problem I'm having with GCLK, is:
int main(void)
{
volatile uint32_t configWord=0;
// Setup the port
pPortA->directionSet = (1 << 9); // pa09 to output
pPortA->pinMux[4].member.word = 0x66;
pPortA->pCfg[8].member.bits.pmuxEnable=1;
pPortA->pCfg[8].member.bits.inputEnable=1;
pPortA->pCfg[9].member.bits.pmuxEnable=1;
pPortA->pCfg[9].member.bits.driveStrength=1;
pPortA->directionSet = (1 << 14);
pPortA->out = 0;
pSysControl->XOSC.word=0x2;
pSysControl->OSC8M.bits.prescalar = 0;
pGCLK->control.bits.reset = 1; // reset the GCLK resource
pGCLK->generatorDivisor = DIVIDE_BY_1 | GCLK_ID1; // setup a baseline division rate for GCLK1
pGCLK->generatorControl = GCLK_ID1 | GCLK_GEN_SOURCE_OSC8M | GCLK_GEN_ENABLE | GCLK_OUTPUT_ENABLE; // Use the int 8M osc, route to gen 1, enable output and generator
while (1)
{
pPortA->outToggle = (1<<14);
}
}
The aim is to just toggle a pin if I can get through the clocking resource, but thus far it's all a miss. Does anyone have any inputs or ideas on what I'm missing?