Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xmega clock calibration issues #6

Open
ahtn opened this issue Jun 13, 2017 · 0 comments
Open

xmega clock calibration issues #6

ahtn opened this issue Jun 13, 2017 · 0 comments

Comments

@ahtn
Copy link

ahtn commented Jun 13, 2017

I found some issues with the 48MHz DFLL calibration with the xmega code. It was working some of the time but depending on the USB port used and the temperature, it would often fail to enumerate.

In the clock setup, the compare value for the DFLL is 0xB71B. The datasheet is a bit unclear here, but what it's supposed to be set to is the ratio between the target clock frequency and the DFLL reference frequency. That is for a target clock speed of 48MHz using the USB SOF at 1kHz (1kHz because SOF is every 1ms) the correct value to use is 48MHz / 1kHz = 48000 = 0xbb80.

Further I found that for best reliability, the DFLL should only be enabled once the xmega has started receiving SOF packets. My code looked like this:

ISR(USB_BUSEVENT_vect){
	if (USB.INTFLAGSACLR & USB_SOFIF_bm){
		USB.INTFLAGSACLR = USB_SOFIF_bm;

		// enable DFLL now
		DFLLRC32M.CTRL = DFLL_ENABLE_bm;

		// don't need SOF interrupts any more
		USB.INTCTRLA &= ~USB_SOFIE_bm;

	}else if (USB.INTFLAGSACLR & (USB_CRCIF_bm | USB_UNFIF_bm | USB_OVFIF_bm)){
		USB.INTFLAGSACLR = (USB_CRCIF_bm | USB_UNFIF_bm | USB_OVFIF_bm);
	}else if (USB.INTFLAGSACLR & USB_STALLIF_bm){
		USB.INTFLAGSACLR = USB_STALLIF_bm;
	}else{
		USB.INTFLAGSACLR = USB_SUSPENDIF_bm | USB_RESUMEIF_bm | USB_RSTIF_bm;

		if (USB.STATUS & USB_BUSRST_bm){
			USB.STATUS &= ~USB_BUSRST_bm;
			usb_reset();
			usb_cb_reset();

		}

		// disable the DFLL now that the USB device is suspended/reset
		DFLLRC32M.CTRL &= ~DFLL_ENABLE_bm;

		// re-enable the SOF interrupts so that the DFLL can be re-enabled
		// later.
		USB.INTCTRLA |= USB_SOFIE_bm;

		// re-load the factory calibration values for the RC oscillator
		NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
		DFLLRC32M.CALA = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSCA));
		DFLLRC32M.CALB = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSC));
		NVM.CMD = NVM_CMD_NO_OPERATION_gc;
	}
}

EDIT: working code example can be found here:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant