What I'm using
Tiva C launchpad (TM4C123GH6PMI chip)
CCS v5.4
Tiva C driver library v1.1
Hello,
I need a little guidance regarding deep sleep mode. My understanding (from reading the datasheet and peripheral users guide) is that you are required to power your peripherals off of the PIOSC when in deep sleep mode. I would like to run my system clock off of the PLL to do work then go to sleep still running the peripherals while sleeping.
While reading the data sheet I saw that, for the ADC, you are supposed to power up the PLL and then enable PIOSC in the CS bit field and then disable the PLL. I've tried all the ways I could come up with but I don't seem to be having much luck. Could someone explain how to do this using the API? I've tried variations of this code:
SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_INT); SysCtlDelay(5); //HWREG(ADC0_BASE + 0xFC8) |= 0x01; SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_INT); SysCtlDelay(5);
but it doesn't seem to work no matter what I or in there.
I am also having a similar problem with my timer. It is being set based on an 80Mhz clock then I hit deep sleep and I think it changes to 16Mhz making my counter now very very slow. In other words, I'm setting my counter to count to 80,000,000 based on an 80Mhz clock, but when I go to deep sleep my counter runs off of the 16Mhz clock meaning I'm counting to 80,000,000 with a 16Mhz clock making it take much longer to generate an interrupt.
I'm confident my code works correctly because if I configure the system clock to 16Mhz PIOSC from the beginning and use deep sleep it looks like it works fine. I get interrupts and my adc values get updated etc... I think I'm just lacking an good enough understanding of how things behave in deep sleep mode and how you run with the PLL at high speeds when woken up, but still run peripherals off the 16Mhz PIOSC.
Below is some of my pertinent code sections:
Below is the code that works fine off of the 16Mhz PIOSC in deep sleep mode. The commented sections are things I've tried to figure this out. How do I accomplish running the CPU at 80Mhz when the system wakes up (or just off of the PLL in general) while running everything else off of the PIOSC while asleep? Is that even correct...am I'm understanding correctly that you have to use the PIOSC for peripherals in deep sleep?
#include <stdio.h> /* * TM4C123G */ // TI file includes #include "driverlib/pin_map.h" #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "driverlib/uart.h" #include "uartstdio.h" #include "driverlib/timer.h" #include "driverlib/adc.h" // My file includes #include "ADC_configuration.h" //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // //***************************************************************************** #ifdef DEBUG void __error__(char *pcFilename, unsigned long ulLine) { } #endif void InitConsole(void) { // ---- Setup UART0 PA0/PA1 ---- // // Enable PORTA (Uart) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); // Enable UART0 SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); // Use 16Mhz internal Oscillator as UART BRCLK UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC); // Select UART function for PA0/PA1 GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // Initialize the UART for console I/O. UARTStdioConfig(0, 115200, 16000000); SysCtlDelay(5); //-------------------------------// } int main(void) { uint32_t clock_rate; //uint32_t ADC_data_1step[1]; //uint32_t ADC_data_1step[8]; //uint32_t ADC_data_1step[2]; uint32_t ADC_data_1step[4]; uint32_t ui32TempValueC; // Initialize variables ADC_data_flag = 0; // ADC data ready //ADC_data_1step[0] = 0; // System clock set to 80Mhz using the 16 Mhz external crystal (MainOscillator) using PLL //SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_INT); SysCtlDelay(5); //HWREG(ADC0_BASE + 0xFC8) |= 0x01; SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_INT); SysCtlDelay(5); // Enable PortF (LEDS) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // Enable PORTF (toggle pin) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // Setup GPIOF Pins as outputs GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3); // Setup PB.1 as an output for scope GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_1); InitConsole(); WTimer0_64_config(); // Configure ADC ADC0_ProcTrig_Oversampling0_4ch(); // Operate ADC in Deep Sleep from PIOSC // Configuration for sleep mode (not working yet in deep sleep) SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_WTIMER0); SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralClockGating(true); // Enable Global processor interrupts IntMasterEnable(); // Config complete, turn on green LED UARTprintf("Configuration complete! \n"); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x00); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0x04); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0x00); // Enable Timer0 TimerEnable(WTIMER0_BASE, TIMER_A); while(1){ clock_rate = SysCtlClockGet(); if(ADC_data_flag == 1){ ADCSequenceDataGet(ADC0_BASE, 0, ADC_data_1step); ui32TempValueC = 1475 - ((2475 * ADC_data_1step[0]) / 4096); UARTprintf("Degrees C = %3d*C", ui32TempValueC/10); UARTprintf("\n"); ADC_data_flag = 0; } SysCtlDeepSleep(); } return 0; }
My timer configuration:
void WTimer0_64_config(void) { //------ Setup Timer 64-bit -----// // Enable Timer peripheral SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0); // Configure WTimer0 in 64-bit mode TimerConfigure(WTIMER0_BASE, TIMER_CFG_PERIODIC_UP); // load timer with SysClk/100 (1mS increments) TimerLoadSet64(WTIMER0_BASE, (uint64_t)SysCtlClockGet()); // Enable interrupts TimerIntEnable(WTIMER0_BASE, TIMER_TIMA_TIMEOUT); // Register ISR TimerIntRegister(WTIMER0_BASE, TIMER_A, *WTimer0IntHandler); // Clear interrupts TimerIntClear(WTIMER0_BASE, TIMER_TIMA_TIMEOUT); //-------------------------------// }
My ADC configuration:
void ADC0_ProcTrig_Oversampling0_4ch(void) { // ADC0 // Sequence0 (2-steps, 8-sample FIFO) // Step0 (Only use 4 step in 8 step sequencer) // Processor Triggered // Sample Channel = AIN0 (PE3) // // Enable ADC peripheral SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // Enable PORTE so we and use A0 (PE3) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // Set GPIO PE3 as an ADC input GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); // Enable Sequence 0 (single sample), trigger on processor, // highest priority ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0); // Configure Sequencer 0 to sample 4 channels each store in a step // Interrupt on step3 -> final step ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); // Register interrupt handler ADCIntRegister(ADC0_BASE, 0, *ADC0IntHandler); // Clear interrupt flag ADCIntClear(ADC0_BASE, 0); // Enable interrupts ADCIntEnable(ADC0_BASE, 0); // Enable Sequencer ADCSequenceEnable(ADC0_BASE, 0); }
I've worked on using the:
// Configuration for sleep mode (not working yet in deep sleep) SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_WTIMER0); SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralDeepSleepEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralClockGating(true);
calls a bit as well and they don't seem to help.
Thanks for any input,
Rob