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