After a lengthy period of learning the FRDM-KL03 with KDS, I have finally figured out how to get into the VLLSx modes and wake from them successfully. Below is a list of the some of the important things that I learned in hopes that it might help others in the same situation as me:
1. Avoid using the high level functions and HAL functions that were made to make your life easier. They don't. It is easier to simply work with the registers as defined in the user's manual. Simply write the "register_name=" and then a binary or hex representation of the bits in the that register. In this way, you will know exactly what you are working with.
2. Find the KLQRUG document from NXP. It was very helpful and I only found it late in my learning period.
3. Do not use the built in "hardware.init()" file, or at the very least understand what it does. I extracted from it the things I needed and left the rest. I prefer to define all my own settings now. Also, as it turns out, one of the functions in the hardware.init file writes to the PMPROT register, I did not discover this until very late. This register can only be written once and is needed to be set for entry into low power modes. The setting in the hardware.init is not the right setting.
4. Review the errata, particularly e8068. There is a bug regarding the RTC clock that prevents entry into low power states. When you are using KDS, you need to make sure that you do the following:
a) Enable the RTC clock gate
b) Disable the RTC time counter
c) Write to the RTC_TSR register to clear the RTC_SR[TIF] flag which gets set during POR
d) Disable the RTC clock gate
This needs to be done before you go into the sleepmodes.
5. Somewhere near the beginning of the main program, the ACK Isolation flag needs to be cleared. By writing a 1 to this setting when it is set releases the I/O pads and certain peripherals to their normal run mode state. I set this after my port/GPIO settings.
6. When setting up the SMC registers for VLLSx sleep modes, you need to add at least one dummyread lines after you write to the PMCTRL register. This will ensure that the write is complete before stopping the core. I did this with two lines: dummyread=SMC_PMCTRL;
7. You need to set the SLEEPDEEP bit to enable deep sleep. This bit is part of the system control which is not included in the KL03 manual since it is an ARM thing. This bit is set with the following command:
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
8. To actually enter the VLLSx sleep mode, the WFI (wait for interrupt) command must be used (__asm__("wfi"); And yes, you need the underscores...there are two on each side of the "asm".
9. You can wake from the VLLSx mode in many ways. I started by just using the reset button on the FRDM-KL03. In this way, I didn't need to have any wake-up code or interrupts or other things when I was just trying to get it to sleep. After I got the processor to sleep, I started looking at ways to wake it up. The documentation is confusing about this. The KL03 has an LLWU module, but it only works with the pin enable. It does not have any modules that work within the LLWU module. If you use the LLWU_PE then be sure to set the port pin as an input. I was also able to wake the processor using an LPTMR interrupt, as long as it was initialized and there was an external clock. Both wake-up methods needs interrupt handlers where the wakeup flag is cleared (LLWU) or the interrupt flag is cleared (LPTMR).
I hope this helps!