Search the Community

Showing results for tags 'energia'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • News
    • Announcements
    • Suggestions
    • New users say Hi!
  • Spotlight!
    • Sponsor Spotlight
    • Sponsor Giveaways
  • Energia
    • Energia - MSP
    • Energia - TivaC/CC3XXX
    • Energia - C2000
    • Energia Libraries
  • MSP Technical Forums
    • General
    • Compilers and IDEs
    • Development Kits
    • Programmers and Debuggers
    • Code vault
    • Projects
    • Booster Packs
    • Energia
  • Tiva-C, Hercules, CCXXXX ARM Technical Forums
    • General
    • SensorTag
    • Tiva-C, Hercules, CC3XXX Launchpad Booster Packs
    • Code Vault
    • Projects
    • Compilers and IDEs
    • Development Kits and Custom Boards
  • Beagle ARM Cortex A8 Technical Forums
    • General
    • Code Snippets and Scripts
    • Cases, Capes and Plugin Boards
    • Projects
  • General Electronics Forum
    • General Electronics
    • Other Microcontrollers
  • Connect
    • Embedded Systems/Test Equipment Deals
    • Buy, Trade and Sell
    • The 43oh Store
    • Community Projects
    • Fireside Chat
  • C2000 Technical Forums
    • General
    • Development Kits
    • Code Vault
    • Projects
    • BoosterPacks


There are no results to display.

Found 407 results

  1. This project is an offshoot of an earlier investigation of wireless wearables using the MSP430G2553: The concept has been successfully tested and is described below. I plan regular updates as the project progresses. The objective is to develop a wearable powered by a coin cell that can be controlled remotely. It could be used, as an example, in the tiara below or on a costume worn by dancers in a performance and controlled from offstage. In the photo an earlier MSP430G2553 coin cell powered wearable is attached to the tiara and driving 3 WS2812 LEDs. The constraints are: cost - unit cost for the receiver of $10 or less technology - common off the shelf components, MSP430G2553 construction - standard double sided PCB spec, keep SMD parts large enough to be hand soldered power - CR2032 (rated 3V and 225 mAH) life - needs to run at least half an hour on fresh batteries reception - 10m with clear line of sight, update at least every 100 ms transmission - desirable but not required size - 40mm/1.6" diameter for receiver programming - Energia desirable schedule - 6 month completion The transmitter will probably be placed on a "Booster Pack" for a LaunchPad running Energia. Multiple LEDs will be driven to gain extra distance, and if required multiple transmitters could be set up from different angles to assure good reception. A display would be helpful as on the FR6989 shown below with an IR LED. The initial Energia transmission sketch to test the concept is located here: The sketch was developed in Energia V17 using a MSP430G2553 LaunchPad and a 940 nm infrared LED. It loops from 0 to 255 and sends a single byte with the count via infrared to the receiver when a button is pushed. The packets for sending bytes do not follow an existing protocol. It is specific to this application and developed with the goal of getting a byte transmitted at least every 100 ms. The receiver will be a custom MSP430G2553 board powered by a coin cell with a TSOP38238 IR receiver. There will LEDs on the PCB and it will also have the capability to drive LEDs off board. The preliminary receiver code was written in C using CCS and direct register access: . The framework for the code is based on a post by RobG here on 43oh. The receiver takes transmissions from the Energia sketch linked above and outputs the current byte on eight LEDs in binary form. When the last byte is received it clears the LEDs and outputs the number of bytes received in error out of the expected 255. This allows analysis of reception at different distances and conditions. Shown below is the preliminary testing setup. In the foreground is the G2553 receiver with a TSOP38238 and output LEDs on a breadboard. Middle ground is a G2553 with the infrared LED sending bytes. Background is output from the receiver being monitored on an oscilloscope. The output of the TSOP38238 is quite clean and no errors were seen with the transmitter and receiver this close together. Transmission is at approximately 1000 bytes per minute or 16+ bytes/sec which is within the desired range. I subsequently modified the test setup to run off batteries so I could do some preliminary distance testing. With clear line of sight reception I saw no errors up to 5 meters with one transmission LED aimed directly at the receiver. Errors crept in after that, especially if the transmission is off to one side, not pointed directly at the receiver, or at a greater distance. Near term activities: increase the number of transmission LEDs evaluate the impact of off-center transmission further test in an environment that doesn't have reflective surfaces add WS2812 driver capability and investigating the impact of TSOP38238 interrupts on the WS2812 driver evaluate 2032 battery life further
  2. Hi! I would like to interface a combined GPS + GSM module to an MSP-EXP430FR5969 using Energia. The aim is at the press of a button/signal, an SMS is sent with the GPS lat/long coordinates at the time of the press. I am planning to use this module ( to connect it all up. I've seen a lot of Arduino examples on this (e.g. using tinyGPS and softwareSerial) but I'm not sure if this same code will work on the MSP430. Will it? How can I go about changing the Arduino set up/pin definitions so that it'll work on the MSP430 using Energia? Thanks in advance
  3. Hello, I'm not used to playing with C/C++ or even with compiled languages so maybe it'll be a dumb question but after a lot of research, I don't know what to do. I have an issue at compilation in a CCS project for CC3200 and I've already posted a question in the compiler section of TI's forum. I got help : I know now that my error is that I'm trying to use methods defined in a header file without having the corresponding source file in the project. So I am getting an "undefined symbol" error on theses methods, as you can see on the following screenshot. As I started my project in Energia IDE, I did some code using Energia's methods. Going on doing the project, I needed to add Free-RTOS. I never used Free-RTOS before so I took a demo project of Free-RTOS implementation for CC3200 as a base to do it. I succeeded to compile the demo project on my board. Also, I imported my Energia sketch in my CCS workspace and I was also able to build it and run it correctly on the board (via CCS). But then I tried to combine both project, and now I'm stuck with an issue. I added code from my Energia Sketch in the Free-RTOS demo project. As I am using Energia methods and constants such as digitalWrite or pinMode, I was not surprised that the IDE and the compiler couldn't find them. I investigated a bit to find out where these methods where defined and I found them in Energia.h. That's why I firstly tried to import this header only. Now that I have understood that I need the source file :), but I can't find it ! My last try was to look at the imports/symbols and file search paths of my imported Energia sketch in CCS (like the following) : - Imported Energia sketch project - Free-RTOS demo project (my project) I also read things about "lpcc3200_core" folder which was added when I imported the Energia Sketch. Maybe this is the core files that I need ? I'm still stuck and now I wonder if it's even possible to correctly import Energia framework this way, or if I should either choose TI-RTOS or write again my Sketch directly in C/C++. Thanks for reading me !
  4. Hi, I am using CC3200 LaunchXL for configuring LORA semtech 1272 over SPI Driver. I searched a lot example or reference for cc3200 for transmitting message using SPI but unable to get for Energia IDE. I have code for Arduino Lora implementation but unable to run it on Energia. Kindly help me as soon as possible Thanks and regards Rohit
  5. Hi everyone, I did a quick port of these two libraries to Energia on Stellaris. You can find them here: Note that I used digitalWrite() rather than messing with port registers. The speed doesn't seem too bad all the same. At the moment, I have only tested with hardware SPI. If you inspect the changes I had to make for Energia, it might help with porting further libraries to Stellaris. Cheers, Steve
  6. Hi All, I need to make ADC14 measurements in the multi mode at a sample rate of 8 kHz, but would like to use Energia's Serial and I2C functions. I have a stand alone driverlib routine that works fine, and Energia code that works fine with the Serial, and I2C, however, I am having difficulty integrating them. I noticed that the ADC14CTL0 register is changed from what my routine called in setup() did. I started reading the code in Energia/emt/src/ti/runtime/wiring/msp432/, and it appears that I may need to modify it to make this work, but before I go hacking, I want advice. Is there a good way to get Energia to leave the ADC14 to me, or is there a way to use Energia's ADC14 routines to do multi conversions at 8 kHz? I'm enclosing my code in case it is of use: extern "C"{ #include <copy2_adc14.h> }; // most launchpads have a red LED #define LED RED_LED //see pins_energia.h for more LED definitions //#define LED GREEN_LED // the setup routine runs once when you press reset: void setup() { Serial.begin(115200); // initialize the digital pin as an output. //pinMode(LED, OUTPUT); adc14_(); //delay(500); //MAP_ADC14_enableConversion(); startSampling(); } // the loop routine runs over and over again forever: void loop() { static int i=0; Serial.print(i++); Serial.println("Hello!"); //digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second //digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW // delay(1000); // wait for a second } And the header file: /* * adc14_.h * * Created on: May 12, 2017 * Author: frohro */ #ifndef COPY2_ADC14_H_ #define COPY2_ADC14_H_ /* DriverLib Includes */ #include <ti/devices/msp432p4xx/driverlib/driverlib.h> #include <ti/sysbios/family/arm/m3/Hwi.h> /* Standard Includes */ #include <stdint.h> #include <stdbool.h> #define SMCLK_FREQ 24000000 #define SAMPLE_FREQ 8000 //Timer_A Continuous Mode Configuration Parameter const Timer_A_UpModeConfig upModeConfig = // This DOES work { TIMER_A_CLOCKSOURCE_SMCLK, // SM Clock Source TIMER_A_CLOCKSOURCE_DIVIDER_1, // SMCLK/1 = 24MHz (SMCLK_FREQ/SAMPLE_FREQ), TIMER_A_TAIE_INTERRUPT_DISABLE, // Disable Timer ISR TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE, // Disable CCR0 TIMER_A_DO_CLEAR // Clear Counter }; /* Timer_A Compare Configuration Parameter */ const Timer_A_CompareModeConfig compareConfig = { TIMER_A_CAPTURECOMPARE_REGISTER_1, // Use CCR1 TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE, // Disable CCR interrupt TIMER_A_OUTPUTMODE_SET_RESET, // Toggle output but (SMCLK_FREQ/SAMPLE_FREQ) // Should be 8 kHz sample rate }; /* Statics */ static volatile uint_fast16_t resultsBuffer[UINT8_MAX]; static volatile uint8_t resPos; int adc14_(void); void ADC14_IRQHandler(void); void startSampling(void); #endif /* COPY2_ADC14_H_ */ and the C file to run the ADC14: /* * ------------------------------------------- * MSP432 DriverLib - v4_00_00_11 * ------------------------------------------- * * --COPYRIGHT--,BSD,BSD * Copyright (c) 2017, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ /* MSP432 ADC14 - Multiple Channel Sample without Repeat * * Description: In this code example, the feature of being able to scan multiple * ADC channels is demonstrated by the user a the DriverLib APIs. Conversion * memory registers ADC_MEM0 - ADC_MEM3 are configured to read conversion * results from A6, A12, A10, A8 respectively. Conversion is enabled and then sampling is * toggled using a software toggle. Repeat mode is not enabled and sampling only * occurs once (and it is expected that the user pauses the debugger to observe * the results). Once the final sample has been taken, the interrupt for * ADC_MEM3 is triggered and the result is stored in the resultsBuffer buffer. * * MSP432P401 * ------------------ * /|\| | * | | | * --|RST P4.7 |<--- A6 (Analog Input, Measured, Real) * | P4.1 |<--- A12 (Analog Input, Measured, Imaginary) * | P4.3 |<--- A10 (Analog Input, Reference Real) * | P4.5 |<--- A8 (Analog Input, Reference Imaginary) * | | * | | * * 4.1, 4.3, 4.5, 4.7 are the eventual pins needed. * * Author: Timothy Logan * This was modified by Rob Frohne to do multiple ADC at 8 kHz sample rate. ******************************************************************************/ #include <copy2_adc14.h> #define NUMBER_TIMER_CAPTURES 20 #define SAMPLE_LENGTH 128 /* static volatile uint_fast16_t timerAcaptureValues[NUMBER_TIMER_CAPTURES]; static volatile uint32_t timerAcapturePointer = 0; */ uint16_t refRe[SAMPLE_LENGTH]; uint16_t refIm[SAMPLE_LENGTH]; uint16_t measRe[SAMPLE_LENGTH]; uint16_t measIm[SAMPLE_LENGTH]; extern volatile bool doneADC; bool sendMeasurement = false; int numberFrequenciestoMeasure, frequencyIndex; float refSum, measSum; volatile bool doneADC = false; int adc14_(void) { /* Halting WDT */ WDT_A_holdTimer(); Hwi_Params params; // Register interrupt Hwi_Params_init(&params); Hwi_create(INT_ADC14, ADC14_IRQHandler, &params, 0); //Hwi_create(INT_TA0_N, TA0_N_IRQHandler, &params, 0); //Interrupt_enableSleepOnIsrExit(); resPos = 0; // Set to Vcore1 PCM_setCoreVoltageLevel(PCM_VCORE1); // Set to use DCDC //PCM_setPowerState(PCM_AM_DCDC_VCORE1); // Initializes Clock System /* These commented out because we need the Energia clock setup. The * data structures for the timer are adjusted accordingly. The time * between conversions may be four times as much as we had with these * parameters below, but this seems like the easiest way to make everything * play together for now. */ //FlashCtl_setWaitState( FLASH_BANK0, 2); //FlashCtl_setWaitState( FLASH_BANK1, 2); PCM_setPowerState( PCM_AM_DCDC_VCORE1 ); CS_setDCOCenteredFrequency( CS_DCO_FREQUENCY_24 ); //CS_setDCOFrequency(24000000); CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 );; CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); /* Initializing ADC (MCLK/1/1) */ ADC14_enableModule(); ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); // Configuring debugging pins as output for debugging... GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN5); GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); //Configuring GPIOs for Analog In GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN1 | GPIO_PIN3 | GPIO_PIN5 | GPIO_PIN7, GPIO_TERTIARY_MODULE_FUNCTION); // Configuring ADC Memory (ADC_MEM0 - ADC_MEM3 (A6, A12, A10, A8) with no repeat) // with internal 2.5v reference ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM3, true); // No repeat mode. ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A6, ADC_NONDIFFERENTIAL_INPUTS); ADC14_configureConversionMemory(ADC_MEM1, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A12, ADC_NONDIFFERENTIAL_INPUTS); ADC14_configureConversionMemory(ADC_MEM2, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A10, ADC_NONDIFFERENTIAL_INPUTS); ADC14_configureConversionMemory(ADC_MEM3, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A8, ADC_NONDIFFERENTIAL_INPUTS); /* Configuring Timer_A*/ Timer_A_configureUpMode(TIMER_A0_BASE, &upModeConfig); /* Configuring Timer_A0 in CCR1 */ Timer_A_initCompare(TIMER_A0_BASE, &compareConfig); /* Configuring the sample trigger to be sourced from Timer_A0 and setting it * to automatic iteration after it is triggered*/ ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); /* Enabling the interrupt when a conversion on channel 3 is complete*/ ADC14_enableInterrupt(ADC_INT3); //ADC14_enableConversion(); // Not needed because we enable it in .ino. /* Enabling Interrupts */ Interrupt_enableInterrupt(INT_ADC14); Interrupt_enableMaster(); /* Starting the Timer */ Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE); /* Going to sleep */ /* while (1) { PCM_gotoLPM0(); }*/ return 1; } void ADC14_IRQHandler(void) { uint64_t status; static int i = 0; //GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0); status = ADC14_getEnabledInterruptStatus(); ADC14_clearInterruptFlag(status); GPIO_toggleOutputOnPin(GPIO_PORT_P5, GPIO_PIN5); ADC14_disableConversion(); if(status & ADC_INT3) { //ADC14_disableConversion(); doneADC = false; ADC14_getMultiSequenceResult(resultsBuffer); measRe[i] = resultsBuffer[0]; measIm[i] = resultsBuffer[1]; refRe[i] = resultsBuffer[2]; refIm[i] = resultsBuffer[3]; //i=(i+1)%SAMPLE_LENGTH; if (i!=SAMPLE_LENGTH) { i++; //ADC14_enableConversion(); } else { i=0; doneADC = true; //ADC14_enableConversion(); } } ADC14_enableConversion(); } void startSampling(void) { ADC14_enableConversion(); // It is a mystery why I need to do this // instead of just calling ADC14_enableConversion() // from the .ino file! } Thanks, Rob
  7. Hello, I have an issue related to SoftwareSerial.h related header file. I place this header file in ..\energia-0101E0017\hardware\cc3200\libraries. But still I got following error: D:\..\energia-0101E0017\hardware\cc3200\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function 'virtual size_t SoftwareSerial::write(uint8_t)': D:\\..\\energia-0101E0017\hardware\cc3200\libraries\SoftwareSerial\SoftwareSerial.cpp:450:21: error: 'SREG' was not declared in this scope uint8_t oldSREG = SREG; ^ D:\..\energia-0101E0017\hardware\cc3200\libraries\SoftwareSerial\SoftwareSerial.cpp:451:7: error: 'cli' was not declared in this scope cli(); // turn off interrupts for a clean txmit ^ D:\..\energia-0101E0017\hardware\cc3200\libraries\SoftwareSerial\SoftwareSerial.cpp:455:26: error: 'XMIT_START_ADJUSTMENT' was not declared in this scope tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT); ^ D:\..\energia-0101E0017\hardware\cc3200\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function 'virtual void SoftwareSerial::flush()': D:\..\energia-0101E0017\hardware\cc3200\libraries\SoftwareSerial\SoftwareSerial.cpp:498:21: error: 'SREG' was not declared in this scope uint8_t oldSREG = SREG; ^ D:\..\energia-0101E0017\hardware\cc3200\libraries\SoftwareSerial\SoftwareSerial.cpp:499:7: error: 'cli' was not declared in this scope cli(); ^ So, please give me a solution. Regards, Pratik
  8. CCS 7.1.0, Energia 1.6.10E18, Windows 10 x64 Any scetch, even empty one generates the same set of errors concerning definite files:, IPAddress.cpp, MACAddress.cpp, main.cpp, WInterrupts.c: fatal error: Arduino.h: No such file or directory, fatal error: avr/pgmspace.h: No such file or directory, fatal error: Energia.h: No such file or directory fatal error: itoa.h: No such file or directory gmake: *** [xxx.o] Error 1 recipe for target xxx.o failed ending compilation as: Cannot build project. Referenced project 'CC3200-LAUNCHXL_core' contains build-errors. Separatelly, Energia IDE itself and CCS works fine. Path to Energia set correctly. Any help wanted.
  9. Hi, I'm trying to do a timerA initiated multiple channel conversion with the ADC14 in an MSP432. It seems that TI-RTOS wants to use all the TimerA modules. I believe this because I see the TAxR value stop. I also made a simple timer routine to blink the LED in the TA0 ISR, and it works sometimes and not others. I notice that there doesn't seem to be any drivers for TI-RTOS for the timers, and no example code for doing a multichannel convert triggered by TimerAx. I have bare metal code for driverlib that works perfectly, but when I put it into Energia, I get no interrupts, as the timer is stopped. I can fight with TI-RTOS, and keep starting the timer in my loop(), but of course it isn't sampling at the rate I want then. I am wondering if perhaps I change the Times_NumberofTimerDevices to be one less, if I could use TimerA3. What do you all think? See for example Timer.c below: /* * Copyright (c) 2014-2016, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * ======== Timer.c ======== * */ #include <xdc/std.h> #include <xdc/runtime/Error.h> #include <xdc/runtime/Assert.h> #include <xdc/runtime/Startup.h> #include <xdc/runtime/Types.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/family/arm/m3/Hwi.h> #include <ti/sysbios/family/arm/msp432/ClockFreqs.h> /* TODO: move this peripheral register definition to catalog? */ typedef volatile struct ti_catalog_msp432_peripherals_timers_TimerRegs { UInt16 control; UInt16 cctl_0; UInt16 cctl_1; UInt16 cctl_2; UInt16 cctl_3; UInt16 cctl_4; UInt16 cctl_5; UInt16 cctl_6; UInt16 count; UInt16 cc_compare_0; UInt16 cc_compare_1; UInt16 cc_compare_2; UInt16 cc_compare_3; UInt16 cc_compare_4; UInt16 cc_compare_5; UInt16 cc_compare_6; UInt16 expansion; UInt16 reserved[6]; UInt16 vector; } ti_catalog_msp432_peripherals_timers_TimerRegs; #include "package/internal/Timer.xdc.h" #define MC 0x0020 /* mode, control = continous up counting */ #define TxCLR 0x0004 /* clear timer counter */ #define CCIE 0x0010 /* compare interrupt enable */ #define CCIFG 0x0001 /* compare interrupt pending flag */ #define TSSEL 0x0100 /* source select = ACLK */ #define ID_MASK 0x00C0 /* input divider bit mask */ #define TIMER_CONTROL_START MC #define TIMER_CONTROL_CLEAR TxCLR #define TIMER_CONTROL_DEFAULT TSSEL #define TIMER_COMPARE_INTR_ENABLE CCIE #define TIMER_COMPARE_INTR_PENDING CCIFG #define TIMER_DELETED 0 #define BAD_TIMER_ID 1 #define NO_TIMER_AVAIL 2 #define NO_HWI_OBJ 3 #define BAD_PERIOD 4 #define READ_LATENCY 10 /* # MCLK cycles to allow for back-to-back read of count */ #define SYS_PERI_HALTCTL_REG 0xE004300C /* peripheral halt control reg */ #define REG(x) (*((volatile unsigned *)(x))) /* * ======== Timer_getAvailMask ======== */ UInt Timer_getAvailMask() { return (Timer_module->availMask); } /* * ======== Timer_getNumTimers ======== * Get number of timer peripherals available on the device. */ UInt Timer_getNumTimers() { return (Timer_numTimerDevices); } /* * ======== Timer_getStatus ======== * Get the FREE/INUSE status of the timer. */ Timer_Status Timer_getStatus(UInt timerId) { Assert_isTrue(timerId < Timer_numTimerDevices, NULL); if (Timer_module->availMask & (0x1 << timerId)) { return (Timer_Status_FREE); } else { return (Timer_Status_INUSE); } } /* * ======== Timer_getMaxTicks ======== */ UInt32 Timer_getMaxTicks(Timer_Object *obj) { return (0x0000FFFF / obj->period); } /* * ======== Timer_setAvailMask ======== */ Bool Timer_setAvailMask(UInt mask) { UInt i; UInt key; UInt tmpMask; key = Hwi_disable(); tmpMask = mask; for (i = 0; i < Timer_numTimerDevices; i++) { /* Check if mask is setting any currently used timer as available */ if ((tmpMask & 0x1) && (Timer_module->handles[i] != NULL)) { Hwi_restore(key); return (FALSE); } tmpMask = tmpMask >> 1; } Timer_module->availMask = mask; Hwi_restore(key); return (TRUE); } /* * ======== Timer_setNextTick ======== * Program the timer's interrupt threshold for the next tick. */ Void Timer_setNextTick(Timer_Object *obj, UInt32 ticks) { ti_catalog_msp432_peripherals_timers_TimerRegs *timer; UInt32 newPeriod = obj->period * ticks; UInt next; UInt previous; UInt now; /* get timer base address */ timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; previous = obj->prevThreshold; /* next is relative to savedCurrCount */ next = obj->savedCurrCount + newPeriod; /* set the compare threshold for next interrupt */ timer->cc_compare_0 = next; /* * MSP432 timers will only interrupt if the timer counts *to* the threshold. * So we must check to make sure that the threshold wasn't set too late - * if it was set late, the timer count will need to wrap before the next * interrupt is triggered. To avoid this, after writing the next * interrupt threshold, we read the current count, and if the interrupt * threshold was set too late per the current count, we again write * to the timer to trigger an immediate interrupt. * * For the cases where the 'next' threshold is more than the 'previous', * the timer will not wrap before the next target tick interrupt. This * creates three regions shown below (A, B, C), where the current 'now' * count will reside: * * FFFF | - * | B * |<----- next - * | A * |<----- previous - * | C * 0 | - * * A - 'now' is greater than equal to 'previous', and less than 'next': * this is the 'normal' region, where the threshold has been set before the * next threshold, and no adjustment is needed. * * B - 'now' is greater than equal to 'next': the threshold was set * late, trigger an interrupt now. * * C - 'now' is less than 'previous': the threshold was set late, trigger * an interrupt now. * * For the cases where the 'next' threshold is less than the 'previous', * the timer count is expected to wrap before the next tick interrupt. * This creates the three regions shown below (D, E, F), where the current * 'now' count will reside: * * FFFF | - * | D * |<----- previous - * | F * |<----- next - * | E * 0 | - * * D - 'now' is greater than equal to 'previous': this is a 'normal' * region, where the threshold has been set before the next threshold, * and no adjustment is needed. * * E - 'now' is less than 'next': this is another 'normal' region, * where the threshold has been set early enough, and no adjustment is * needed. * * F - 'now' is greater than or equal to 'next' and less than * 'previous': the threshold was set too late, trigger an interrupt now. */ /* get current timer count */ now = Timer_getCount(obj); /* if not expecting wrap thru zero ... */ if (next > previous) { /* case "B": now is greater than or equal to next, interrupt now */ if (now >= next) { timer->cctl_0 |= CCIFG; } /* case "C": now < previous, count has wrapped, interrupt now */ else { if (now < previous) { timer->cctl_0 |= CCIFG; } } } /* else, expecting wrapping thru zero ... */ else { /* case F: now is between next and previous, interrupt now */ if ((now < previous) && (now >= next)) { timer->cctl_0 |= CCIFG; } } } /* * ======== Timer_Module_startup ======== * Calls postInit for all statically-created & constructed * timers to initialize them. */ Int Timer_Module_startup(Int status) { Int i; Timer_Object *obj; if (Timer_startupNeeded) { for (i = 0; i < Timer_numTimerDevices; i++) { obj = Timer_module->handles[i]; /* if timer was statically created/constructed */ if ((obj != NULL) && (obj->staticInst)) { Timer_postInit(obj, NULL); } } } return (Startup_DONE); } /* * ======== Timer_startup ======== * Here after call to main(). Called from BIOS_start(). */ Void Timer_startup() { Int i; Timer_Object *obj; if (Timer_startupNeeded) { for (i = 0; i < Timer_numTimerDevices; i++) { obj = Timer_module->handles[i]; /* if timer was statically created/constructed */ if ((obj != NULL) && (obj->staticInst)) { if (obj->startMode == Timer_StartMode_AUTO) { Timer_start(obj); } } } } } /* * ======== Timer_getHandle ======== */ Timer_Handle Timer_getHandle(UInt id) { Assert_isTrue((id < Timer_numTimerDevices), NULL); return (Timer_module->handles[id]); } /* * ======== Timer_Instance_init ======== * 1. Select timer based on id * 2. Mark timer as in use * 3. Init timer obj using params * 4. Create Hwi if tickFxn != NULL * 5. Initialize timer * 6. Configure timer (wrt emulation, frequency, etc.) * 7. Set period * 8. Timer_start() * */ Int Timer_Instance_init(Timer_Object *obj, Int id, Timer_FuncPtr tickFxn, const Timer_Params *params, Error_Block *eb) { Int status; UInt key; Int i; Hwi_Params hwiParams; UInt tempId = 0xffff; if (id >= Timer_numTimerDevices) { if (id != Timer_ANY) { Error_raise(eb, Timer_E_invalidTimer, id, 0); return (BAD_TIMER_ID); } } key = Hwi_disable(); if (id == Timer_ANY) { for (i = 0; i < Timer_numTimerDevices; i++) { if ((Timer_anyMask & (1 << i)) && (Timer_module->availMask & (1 << i))) { Timer_module->availMask &= ~(1 << i); tempId = i; break; } } } else if (Timer_module->availMask & (1 << id)) { Timer_module->availMask &= ~(1 << id); tempId = id; } Hwi_restore(key); obj->staticInst = FALSE; if (tempId == 0xffff) { Error_raise(eb, Timer_E_notAvailable, id, 0); return (NO_TIMER_AVAIL); } else { obj->id = tempId; } if (params->clockSource == Timer_Source_ACLK) { obj->controlRegInit = 0x0100 | params->inputDivider; } else if (params->clockSource == Timer_Source_SMCLK) { obj->controlRegInit = 0x0200 | params->inputDivider; } else if (params->clockSource == Timer_Source_EXTERNAL) { obj->controlRegInit = 0x0000 | params->inputDivider; } else if (params->clockSource == Timer_Source_EXTERNAL_INVERTED) { obj->controlRegInit = 0x0300 | params->inputDivider; } else { return (NO_HWI_OBJ); } obj->runMode = params->runMode; obj->startMode = params->startMode; obj->period = params->period; obj->periodType = params->periodType; obj->arg = params->arg; obj->intNum = Timer_module->device[obj->id].intNum; obj->tickFxn = tickFxn; obj->prevThreshold = 0; obj->savedCurrCount = 0; obj->rollovers = 0; obj->synchronous = params->synchronous; if (params->extFreq.lo == 0) { if (params->clockSource == Timer_Source_ACLK) { obj->frequency.lo = ClockFreqs_ACLK; } else if (params->clockSource == Timer_Source_SMCLK) { obj->frequency.lo = ClockFreqs_SMCLK; } } else { obj->frequency.lo = params->extFreq.lo; } obj->frequency.hi = params->extFreq.hi; obj->inputDivider = params->inputDivider; obj->inputDividerExp = params->inputDividerExp; if (obj->tickFxn) { if (params->hwiParams) { Hwi_Params_copy(&hwiParams, (params->hwiParams)); } else { Hwi_Params_init(&hwiParams); } hwiParams.arg = (UArg)obj->id; if (obj->runMode == Timer_RunMode_CONTINUOUS) { if (params->nesting == TRUE) { obj->hwi = Hwi_create(obj->intNum, Timer_periodicNestStub, &hwiParams, eb); } else { obj->hwi = Hwi_create(obj->intNum, Timer_periodicStub, &hwiParams, eb); } } else { if (params->nesting == TRUE) { obj->hwi = Hwi_create(obj->intNum, Timer_oneShotNestStub, &hwiParams, eb); } else { obj->hwi = Hwi_create(obj->intNum, Timer_oneShotStub, &hwiParams, eb); } } if (obj->hwi == NULL) { return (NO_HWI_OBJ); } } else { obj->hwi = NULL; } Timer_module->handles[obj->id] = obj; Timer_initDevice(obj); if (obj->periodType == Timer_PeriodType_MICROSECS) { if (!Timer_setPeriodMicroSecs(obj, obj->period)) { Error_raise(eb, Timer_E_cannotSupport, obj->period, 0); Hwi_restore(key); return (BAD_PERIOD); } } status = Timer_postInit(obj, eb); if (status) { return (status); } if (obj->startMode == Timer_StartMode_AUTO) { Timer_start(obj); } return (0); } /* * ======== Timer_reconfig ======== * * 1. Init obj using params * 2. Timer_init() * 3. Configure timer (wrt emulation, frequency, etc.) * 4. Set period * 5. Timer_start() * */ Void Timer_reconfig (Timer_Object *obj, Timer_FuncPtr tickFxn, const Timer_Params *params, Error_Block *eb) { obj->controlRegInit = params->controlRegInit | params->inputDivider; obj->runMode = params->runMode; obj->startMode = params->startMode; obj->periodType = params->periodType; obj->prevThreshold = params->prevThreshold; obj->rollovers = 0; obj->savedCurrCount = 0; obj->synchronous = params->synchronous; obj->inputDividerExp = params->inputDividerExp; if (obj->periodType == Timer_PeriodType_MICROSECS) { if (!Timer_setPeriodMicroSecs(obj, params->period)) { Error_raise(eb, Timer_E_cannotSupport, params->period, 0); } } else { obj->period = params->period; } obj->arg = params->arg; obj->tickFxn = tickFxn; if (params->extFreq.lo) { /* (extFreq.hi is ignored) */ obj->frequency.lo = params->extFreq.lo; } Timer_postInit(obj, eb); if (obj->startMode == Timer_StartMode_AUTO) { Timer_start(obj); } } /* * ======== Timer_Instance_finalize ======== */ Void Timer_Instance_finalize(Timer_Object *obj, Int status) { UInt key; /* note: fall through in switch below is intentional */ switch (status) { /* Timer_delete() */ case TIMER_DELETED: /* setPeriodMicroSecs failed */ case BAD_PERIOD: Timer_initDevice(obj); if (obj->hwi) { Hwi_delete(&obj->hwi); } /* Hwi create failed */ case NO_HWI_OBJ: /* timer not available */ case NO_TIMER_AVAIL: /* invalid timer id */ case BAD_TIMER_ID: default: break; } key = Hwi_disable(); Timer_module->availMask |= (0x1 << obj->id); Timer_module->handles[obj->id] = NULL; Hwi_restore(key); } /* * ======== Timer_start ======== * * 1. Hwi_disable() * 2. Clear the counter * 3. Clear timer interrupt flag * 4. Set next compare threshold (per configured period) * 5. Enable timer interrupt * 6. Start timer * 7. Hwi_restore() * */ Void Timer_start(Timer_Object *obj) { ti_catalog_msp432_peripherals_timers_TimerRegs *timer; UInt key; timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; key = Hwi_disable(); /* reset timer counts */ timer->control |= TIMER_CONTROL_CLEAR; /* clear timer interrupt flag */ timer->cctl_0 &= ~TIMER_COMPARE_INTR_PENDING; /* zero previous threshold */ obj->prevThreshold = 0; /* set compare threshold for next interrupt */ timer->cc_compare_0 = obj->period; /* enable capture/compare 0 interrupts */ timer->cctl_0 |= TIMER_COMPARE_INTR_ENABLE; /* start timer */ timer->control |= TIMER_CONTROL_START; Hwi_restore(key); } /* * ======== Timer_stop ======== * * 1. Stop timer * 2. Disable timer interrupt * */ Void Timer_stop(Timer_Object *obj) { ti_catalog_msp432_peripherals_timers_TimerRegs *timer; timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; /* stop timer */ timer->control = obj->controlRegInit | obj->inputDivider; /* disable capture/compare 0 interrupts */ timer->cctl_0 &= ~TIMER_COMPARE_INTR_ENABLE; /* clear timer interrupt flag */ timer->cctl_0 &= ~TIMER_COMPARE_INTR_PENDING; } /* * ======== Timer_setPeriod ======== * * 1. Stop timer * 2. Set period value in timer obj * */ Void Timer_setPeriod(Timer_Object *obj, UInt32 period) { Timer_stop(obj); obj->period = period; } /* * ======== Timer_setPeriodMicroSecs ======== * * 1. Stop timer * 2. Compute counts * 3. Set new period value in timer obj * */ Bool Timer_setPeriodMicroSecs(Timer_Object *obj, UInt32 period) { Types_FreqHz freqHz; UInt32 counts; UInt32 freqKHz; Timer_stop(obj); Timer_getFreq(obj, &freqHz); freqKHz = freqHz.lo / 1000; if (Timer_checkOverflow(freqKHz, period/1000)) { return (FALSE); } else { counts = (freqKHz * period) / 1000; obj->period = counts; obj->periodType = Timer_PeriodType_COUNTS; return(TRUE); } } /* * ======== Timer_trigger ======== * * 1. stop timer * 2. write the period with insts * 3. start the timer. * */ Void Timer_trigger(Timer_Object *obj, UInt32 insts) { UInt key; /* follow proper procedure for dynamic period change */ key = Hwi_disable(); /* Force SMCLK for sweep timer */ obj->controlRegInit &= ~0x0100; /* clear ACLK bit */ obj->controlRegInit |= 0x0200; /* enable SMCLK */ Timer_stop(obj); Timer_setPeriod(obj, insts); Timer_start(obj); Hwi_restore(key); } /* * ======== Timer_getPeriod ======== */ UInt32 Timer_getPeriod(Timer_Object *obj) { return(obj->period); } /* * ======== Timer_getCount ======== */ UInt32 Timer_getCount(Timer_Object *obj) { ti_catalog_msp432_peripherals_timers_TimerRegs *timer; UInt first; UInt second; timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; /* if timer's source clock is synchronous to CPU: only read counts once */ if (obj->synchronous) { first = timer->count; } /* else, must do multiple reads to avoid possible spurious values */ else { /* read twice, expecting equal values, or within read latency */ do { first = timer->count; second = timer->count; } while ((first != second) && ((second - first) > READ_LATENCY)); } return (((UInt32) first) & 0xffff); } /* * ======== Timer_oneShotStub ======== */ Void Timer_oneShotStub(UArg arg) { Timer_Object *obj; obj = Timer_module->handles[(UInt)arg]; /* stop the timer (and disable this interrupt source) */ Timer_stop(obj); /* call the tick function */ obj->tickFxn(obj->arg); } /* * ======== Timer_oneShotNestStub ======== */ Void Timer_oneShotNestStub(UArg arg) { Timer_Object *obj; obj = Timer_module->handles[(UInt)arg]; /* stop the timer (and disable this interrupt source) */ Timer_stop(obj); /* enable interrupts to allow nesting */ Hwi_enable(); /* call the tick function */ obj->tickFxn(obj->arg); /* disable interrupts as unwind the ISR */ Hwi_disable(); } /* * ======== Timer_periodicStub ======== */ Void Timer_periodicStub(UArg arg) { Timer_Object *obj; ti_catalog_msp432_peripherals_timers_TimerRegs *timer; obj = Timer_module->handles[(UInt)arg]; timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; /* clear timer interrupt flag */ timer->cctl_0 &= ~TIMER_COMPARE_INTR_PENDING; /* for DYNAMIC, mode latch prevThreshold and detect rollovers */ if (obj->runMode == Timer_RunMode_DYNAMIC) { /* * If the current threshold is less than the prevThreshold * then a rollover has occurred. * * If the current threshold is equal to prevThreshold then the timer * count wrapped around and generated a new interrupt; increment * the rollover count to resume ticking. */ if (obj->prevThreshold >= timer->cc_compare_0) { obj->rollovers += 1; } /* save previous threshold value */ obj->prevThreshold = timer->cc_compare_0; } else { /* save previous threshold value */ obj->prevThreshold = timer->cc_compare_0; obj->savedCurrCount = timer->cc_compare_0; /* set next interrupt threshold; interrupt now if set too late */ Timer_setNextTick(obj, 1); } /* call the tick function */ obj->tickFxn(obj->arg); } /* * ======== Timer_periodicNestStub ======== */ Void Timer_periodicNestStub(UArg arg) { Timer_Object *obj; ti_catalog_msp432_peripherals_timers_TimerRegs *timer; obj = Timer_module->handles[(UInt)arg]; timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; /* clear timer interrupt flag */ timer->cctl_0 &= ~TIMER_COMPARE_INTR_PENDING; /* for DYNAMIC, mode latch prevThreshold and detect rollovers */ if (obj->runMode == Timer_RunMode_DYNAMIC) { /* * if the current threshold is less than the prevThreshold * then a rollover has occurred. */ if (obj->prevThreshold > timer->cc_compare_0) { obj->rollovers += 1; } /* save previous threshold value */ obj->prevThreshold = timer->cc_compare_0; } else { /* save previous threshold value */ obj->prevThreshold = timer->cc_compare_0; obj->savedCurrCount = timer->cc_compare_0; /* set next interrupt threshold; interrupt now if set too late */ Timer_setNextTick(obj, 1); } /* allow nesting of other interrupts ... */ timer->cctl_0 &= ~TIMER_COMPARE_INTR_ENABLE; Hwi_enable(); /* call the tick function */ obj->tickFxn(obj->arg); /* disable interrupts as unwind the ISR */ Hwi_disable(); timer->cctl_0 |= TIMER_COMPARE_INTR_ENABLE; } /* * ======== Timer_getExpiredCounts ======== * * This API is used by the TimestampProvider as part of retrieving a timestamp * using a timer and a tick counter. It returns the expired counts since the * last serviced timer interrupt. * * This API must be called with interrupts disabled; the TimestampProvider * must disable interrupts while retrieving the tick count and calling this * API. * * The TimestampProvider uses a 32-bit timer and 32-bit tick count to track * the timestamp. The tick count either comes from the Clock module or is * stored in the TimestampProvider's module state and incremented by an ISR * when the timer expires. * * For MSP432 we have 16-bit timers, and use a timer compare feature to * trigger an interrupt upon a specific threshold count being reached. The * timer counts can rollover (going thru zero), on the way to reaching the * next threshold. We need to accommodate this rollover as part of * determining expired counts. * * We also need to handle the case where there is a large period value used * for the timer, and the timer is ticking at a fast rate (e.g., the CPU * rate, via an SMCLK selection). For this case, it is possible that * interrupts are disabled before the timer reaches threshold, and then the * timer reaches the threshold count and asserts an interrupt, and then * continues to count upwards before it is read in this routine. If the * timer rolled past zero, then we need to know that there is an interrupt * pending, otherwise we'd report a low count, versus the period plus * that low count. * * To be sure to catch the interrupt, we sample the interrupt flag, read * the count, and then sample the interrupt flag again: * * intrFlag1 * count * intrFlag2 * * If intrFlag1 is set, then we know we've reached the period count, and * need to add it to the reported counts. If intrFlag2 is set, but * intrFlag1 wasn't, we know the timer just reached threshold, and simply * report the period count. * * If neither interrupt flag is set, we can then compute the expired counts by * comparing the count to the previous interrupt threshold (saved in the * timer object). If the current count is greater than or equal to the * previous threshold value, then we know there has been no counter rollover, * and the expired counts is simply: * * result = count - prevThresh * * If the current count is less than the previous threshold, then we know a * counter rollover has occurred since the last ISR. In this case, the * expired counts has to include those between the previous threshold and * zero, plus any counts after rolling past zero: * * result = (0 - prevTresh) + count * * Similar logic to compare the current count to previous threshold can * be used for the case where we know intrFlag1 has been set, and we * need to figure the counts to be added to the period counts. * */ UInt32 Timer_getExpiredCounts(Timer_Object *obj) { ti_catalog_msp432_peripherals_timers_TimerRegs *timer; UInt32 result32; UInt32 count32; UInt32 thresh32; UInt32 period32; UInt32 prev32; Bool intrFlag1; Bool intrFlag2; timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; intrFlag1 = timer->cctl_0 & TIMER_COMPARE_INTR_PENDING; count32 = Timer_getCount(obj) & 0xffff; intrFlag2 = timer->cctl_0 & TIMER_COMPARE_INTR_PENDING; prev32 = obj->prevThreshold & 0xffff; /* interrupt pending before read count? */ if (intrFlag1) { thresh32 = timer->cc_compare_0 & 0xffff; /* threshold for interrupt */ period32 = Timer_getPeriod(obj) & 0xffff; /* period count */ /* threshold reached; no wrap thru zero yet */ if (count32 >= thresh32) { result32 = (count32 - thresh32) + period32; } /* threshold reached; count has wrapped thru zero */ else { result32 = (0x10000 - thresh32) + count32 + period32; } } /* new interrupt now pending, when wasn't before read the count */ else if (intrFlag2) { result32 = Timer_getPeriod(obj) & 0xffff; /* return period count */ } /* interrupt threshold not reached; check if wrapped thru zero */ else if (count32 >= prev32) { result32 = count32 - prev32; } /* interrupt threshold not reached; count has wrapped thru zero */ else { result32 = (0x10000 - prev32) + count32; } return (result32); } /* * ======== Timer_getExpiredTicks ======== */ UInt32 Timer_getExpiredTicks(Timer_Object *obj, UInt32 tickPeriod) { UInt32 ticks; ticks = Timer_getExpiredCounts(obj) / tickPeriod; return (ticks); } /* * ======== Timer_getCurrentTick ======== * Uses 48 bits of precision. * at 32.768 KHz, that's 8,589,934,592 seconds, * or 272 years before tick would be miscalculated */ UInt32 Timer_getCurrentTick(Timer_Object *obj, Bool saveFlag) { UInt32 rollovers; UInt currCount; UInt32 tick; UInt32 s1; UInt r; currCount = Timer_getCount(obj); rollovers = obj->rollovers; if (currCount < obj->prevThreshold) { rollovers += 1; } s1 = rollovers / obj->period; /* upper 32 of 48 bits */ r = rollovers - s1 * obj->period; /* remainder of upper division */ tick = (((UInt32)r << 16) + currCount) / obj->period; /* lower 16-bits */ tick = ((UInt32)(s1 & 0xFFFF) << 16) + (tick & 0xFFFF); /* save for later use by Timer_setNextTick() */ if (saveFlag != 0) { obj->savedCurrCount = tick * obj->period; } return (tick); } /* * ======== Timer_getFreq ======== */ Void Timer_getFreq(Timer_Object *obj, Types_FreqHz *freq) { UInt divider; switch(obj->controlRegInit & ID_MASK) { case Timer_ID_1: divider = 1; break; case Timer_ID_2: divider = 2; break; case Timer_ID_4: divider = 4; break; default: divider = 8; break; } divider *= (obj->inputDividerExp + 1); freq->lo = obj->frequency.lo / divider; freq->hi = 0; } /* * ======== Timer_getFunc ======== */ Timer_FuncPtr Timer_getFunc(Timer_Object *obj, UArg *arg) { *arg = obj->arg; return (obj->tickFxn); } /* * ======== Timer_setFunc ======== */ Void Timer_setFunc(Timer_Object *obj, Timer_FuncPtr fxn, UArg arg) { obj->tickFxn = fxn; obj->arg = arg; } /* * ======== Timer_checkOverflow ======== */ Bool Timer_checkOverflow(UInt32 a, UInt32 b) { return ((b > 0) && (a > Timer_MAX_PERIOD/b)); } /* ======== Timer_initDevice ======== * * 1. Stop timer (set control registers back to default value) * 2. Disable timer interrupt * 3. Clear any pending interrupt * 4. Clear counters * */ Void Timer_initDevice(Timer_Object *obj) { ti_catalog_msp432_peripherals_timers_TimerRegs *timer; UInt key; timer = (ti_catalog_msp432_peripherals_timers_TimerRegs *) Timer_module->device[obj->id].baseAddr; key = Hwi_disable(); /* stop timer; set default control register */ timer->control = MC | obj->controlRegInit; timer->expansion = obj->inputDividerExp; /* clear timer interrupt flag */ timer->cctl_0 &= ~TIMER_COMPARE_INTR_PENDING; /* reset timer counts */ timer->control |= TIMER_CONTROL_CLEAR; /* freeze the timer when the CPU is halted */ REG(SYS_PERI_HALTCTL_REG) |= 1 << obj->id; Hwi_restore(key); } /* * ======== Timer_postInit ======== */ Int Timer_postInit (Timer_Object *obj, Error_Block *eb) { UInt key; key = Hwi_disable(); Timer_initDevice(obj); Timer_setPeriod(obj, obj->period); Hwi_restore(key); return (0); } And if you think this might be worth pursuing, I'd really like a pointer on how to rebuild the stuff to make this work. Thanks, Rob
  10. Hello Everybody, I am using a MSP430F5529 Launchpad with Energia IDE in order to measure the current flowing on the motor. But I have a problem with sampling rate. The current that I want to measure has a 22kHz frequency and I have a 10kHz sampling rate. I would like to have a 200kHz sampling frequency. I found in an other topic that the sampling rate can be reduce because of the serial.print. So, I stored my values in a array before displaying them. i have a better sampling (10kHz) but not enough. Could you tell me how can I improve the sampling rate ? Attached the sketch. Thank you. Sketch Current Measurement .txt
  11. Hi everyone, I am trying multitasking energia example provided in energia webpage as well as example available with energia IDE. ( However, the multitasking is not working. From the codes given in ( the section with setup/loop par is only operational while operations defined in setupGreenLed() / loopGreenLed() and setupRedLed()/loopRedLed() pairs are not executed. Kindly note that as mentioned each pair is declared as separate task. If multiple task panels does not contain standard setup/loop pair following error is generated: --------------------------------------------------- C:\Users\Tiwari\AppData\Local\Temp\build4973a9ae8611f59efc23ab687631bc5a.tmp/core\core.a(main.cpp.o): In function `main': C:\Users\Tiwari\AppData\Local\Energia15\packages\energia\hardware\cc3200\1.0.2\cores\cc3200/main.cpp:39: undefined reference to `setup' C:\Users\Tiwari\AppData\Local\Energia15\packages\energia\hardware\cc3200\1.0.2\cores\cc3200/main.cpp:42: undefined reference to `loop' collect2.exe: error: ld returned 1 exit status exit status 1 Error compiling for board CC3200-LAUNCHXL (80MHz). ------------------------------------------------------- In essence in multiple tasks atleast one of the task must be declared specifically using "setup/loop" pair and not just any unique pair like " setup_x/loop_x ". For reference I have added the Ino sketches. I am wondering is multitasking requires some specific jumper connections or settings prior to usage. Kindly suggest. Thank you
  12. Nick Gammon published an interesting post on using SPI on 16 MHz Arduinos to run WS2812 LEDs (aka neopixels) at: He also provides a link with a lot of information about the NRZ protocol used by the WS2812 and tolerances: The tolerances are actually quite a bit looser than what I previously believed. So, I set out to do something similar with Energia and LaunchPads running at different speeds. Spoiler alert: It works. The previously linked articles provide all the background so minimal information is repeated here. NRZ is a one wire protocol that transfers information to the LEDs by varying the length of the signal when high. A longer pulse is used for a 1, and a shorter one for a 0. The timing, with tolerances, is shown in the figure below. The length between pulses cannot exceed about 5 us and most everything else is pretty loose. The protocol is implemented using SPI which I find pretty clever. A byte is sent out with the SPI module with the proper length to represent the desired bit for the protocol. The following must be determined and set to do this: Set proper SPI clock speed using SPI.setClockDivider() in Energia Determine the proper byte to send by SPI.transfer() in Energia to represent a 0 or 1 bit For example, using the MSP430F5529: Clock speed is 25.6 MHz Setting the SPI clock divider to 4 gives a SPI clock of 6.4 MHz and since the SPI block executes in one cycle (Arduino executes in 2), each bit in the byte is equivalent to 156.25 ns. Therefore, to send a pulse indicating a "1", a byte equal to 0b1111000 could be used which gives 4x156.25 = 625 ns. This is in the acceptable range of 550 to 850 ns. Similarly, for a 0 an acceptable byte would be 0b11000000 or 312.5 ns. A similar process can be used to determine acceptable values for the MSP430G2553. The sketch below is a simplification of the library presented by Nick which and includes the modifications described above to run on both the G2553 and F5529. The preprocessor is used to set appropriate values for the clock divider and long and short bytes. The functions are very nearly the same as posted by Nick. Note that interrupts must be disabled before sending data and then reenabled manually after. /* * WS2812 display using SPI on various TI LaunchPads with Energia * * Connections: * LaunchPad LED Strip * --------- --------- * 3V3 5VDC * Pin 15 (MOSI) DIN * GND GND * * How to use: * ledsetup (); - Get ready to send. * Call once at the beginning of the program. * sendPixel (r, g, ; - Send a single pixel to the string. * Call this once for each pixel in a frame. * Each colour is in the range 0 to 255. Turn off * interrupts before use and turn on after all pixels * have been programmed. * show (); - Latch the recently sent pixels onto the LEDs . * Call once per frame. * showColor (count, r, g, ; - Set the entire string of count Neopixels * to this one colour. Turn off interrupts before use * and remember to turn on afterwards. * * Derived from NeoPixel display library by Nick Gammon * * With ideas from: * * Released for public use under the Creative Commons Attribution 3.0 Australia License * * * F Milburn November 2016 * Tested with Energia V17 and WS2812 8 pixel strip on launchpads shown below. */ #include <SPI.h> #if defined(__MSP430G2553) #define SPIDIV SPI_CLOCK_DIV2 // 16 MHz/2 gives 125 ns for each on bit in byte #define SPILONG 0b11111100 // 750 ns (acceptable "on" range 550 to 850 ns) #define SPISHORT 0b11100000 // 375 ns (acceptable "on" range 200 to 500 ns) #elif defined(__MSP430F5529) #define SPIDIV SPI_CLOCK_DIV4 // 25.6 MHz/4 gives 156.25 ns for each on bit in byte #define SPILONG 0b11110000 // 625 ns (acceptable "on" range 550 to 850 ns) #define SPISHORT 0b11000000 // 312.5 ns (acceptable "on" range 200 to 500 ns) #else #error This microcontroller is not supported #endif const unsigned int PIXELS = 8; // Pixels in the strip void setup (){ ledsetup(); } void loop (){ // Show a solid color across the strip noInterrupts(); // no interrupts while sending data showColor (PIXELS, 0xBB, 0x22, 0x22); // single color on entire strip interrupts(); // interrupts are OK now delay(1000); // hold it for a second // Show a different color on every pixel noInterrupts(); // no interrupts while sending data sendPixel(0xBB, 0x00, 0x00); // red sendPixel(0x00, 0xBB, 0x00); // green sendPixel(0x00, 0x00, 0xBB); // blue sendPixel(0xBB, 0xBB, 0xBB); // white sendPixel(0xBB, 0x22, 0x22); // pinkish sendPixel(0x22, 0xBB, 0x22); // light green sendPixel(0x22, 0x22, 0xBB); // purplish blue sendPixel(0x00, 0x00, 0x00); // pixel off interrupts(); // interrupts are OK now delay(1000); // hold it for a second } // Sends one byte to the LED strip by SPI. void sendByte (unsigned char { for (unsigned char bit = 0; bit < 8; bit++){ if (b & 0x80) // is high-order bit set? SPI.transfer (SPILONG); // long on bit (~700 ns) defined for each clock speed else SPI.transfer (SPISHORT); // short on bit (~350 ns) defined for each clock speed b <<= 1; // shift next bit into high-order position } // end of for each bit } // end of sendByte // Set up SPI void ledsetup(){ SPI.begin (); SPI.setClockDivider (SPIDIV); // defined for each clock speed SPI.setBitOrder (MSBFIRST); SPI.setDataMode (SPI_MODE1); // MOSI normally low. show (); // in case MOSI went high, latch in whatever-we-sent sendPixel (0, 0, 0); // now change back to black show (); // and latch that } // end of ledsetup // Send a single pixel worth of information. Turn interrupts off while using. void sendPixel (unsigned char r, unsigned char g, unsigned char { sendByte (g); // NeoPixel wants colors in green-then-red-then-blue order sendByte (r); sendByte (; } // end of sendPixel // Wait long enough without sending any bits to allow the pixels to latch and // display the last sent frame void show(){ delayMicroseconds (9); } // end of show // Display a single color on the whole string. Turn interrupts off while using. void showColor (unsigned int count, unsigned char r , unsigned char g , unsigned char { noInterrupts (); for (unsigned int pixel = 0; pixel < count; pixel++) sendPixel (r, g, ; interrupts (); show (); // latch the colours } // end of showColor The timing, when checked on a logic analyzer, checks out with the calculations above (hooray for math). The "gaps" between pulses are within tolerance and largely set by code overhead as well as the byte being sent. And here it is showing the strip lit up in one color. I tried this on several other LaunchPads I had handy and here is a summary: FR6989 - I had never noticed, but Energia defaults to 8 MHz. Doing the math, there isn't a good match to the WS2812 requirements without changing processor speed (which I did not try). MSP432 - there was behavior I couldn't explain, probably due to RTOS and I didn't pursue this for long. In summary, the method works although I did limited experimentation. It would be even easier to implement outside of Energia with full access to clocks. It was an interesting exercise but alternative methods have been posted here on 43oh with tuned assembler and having used those successfully in the past, I will probably continue to preferentially use them in the future.
  13. I have an mpu9250 module (accelerometer + gyro). Is there any sample code or tutorials on how to connect the two and have it work on energia?
  14. Hi, I'm trying send GPS (adafruit Ultimate GPS FeatherWing) coordinates to another location using XBees and then displaying GPS data on an LCD (Sharp 96 Booster Pack) using Energia. This involves 2 pairs of Xbees (4 total 2 different ranges), 3 MSP-EXP432P401R (Black Version), the GPS and the LCD. I wrote some code for the first MSP432 on getting GPS data and getting it to the XBee to transmit to another MSP432 (connected to 2 XBees). Although I haven't been able to test it (GPS and XBees aren't here yet) I feel like it will at least be close if not functional.GPStoXBEE.ino After writing the data to the XBee which should then transmit to it's paired XBee that the 2nd MSP432 is connected to. I then want to write the incoming data to the larger ranged XBee also connected to the 2nd MSP432 shown in the following code. XBEEtoXBEE.ino I think my method is kind of right but I won't get the correct output. I believe it will only be taking one char at a time every time the readXBee function is called. So how would I make it print the entirety of the GPS data if I don't know how long/what the data will be ahead of time? I just want to transmit exactly what I'm getting from the GPS itself. Lastly I have another longer ranged XBee connected to the 3rd MSP432 along with an LCD. I want to take the GPS data that is being received from the 2nd MSP432 and print it to the display. I edited the LCD example to get the following XBEEtoLCD.ino and it kind of works, I am able to print from the serial to the display but its only one character at a time every second and the char gets overwritten by the next char. How will can I change the code so that it will print what ever is in the serial in one go? Thanks in Advance
  15. Hi I'm new to using both the MSP-EXP432P401R (Black Version) and Energia. I want to attach a GPS (adafruit Ultimate GPS FeatherWing and an XBee to the micro-controller so I can send GPS data to another MSP432 micro-controller with an XBee. I see I can attach the GPS or XBee to the hardware uart pins 3.2(Rx) and 3.3(Tx) their listed as pins 3 and 4 respectively on the Energia Pin Map ( but where can I find two other hardware pins for attaching a second the second device? Or can I use some other pins (SPI or something) to have both items connected to the micro-controller?
  16. Hello, I am using msp430g2553 mcu and I interfaced that mcu with gsm sim900 successfully. Now I am facing some strange behavior in the code. When I write the loop as follows: void loop() { String buffer = readSIM900A(); String msgOn = buffer; String number1 = "8320389582"; //problem String number2 = "9106555707"; //problem String number3 = "9979933498"; //problem if (buffer.startsWith("\r\n+CMT: ")) { Serial.println(buffer); buffer.remove(0,12); buffer.remove(10); Serial.println(buffer); msgOn.remove(0,51); msgOn.remove(3); Serial.println(msgOn); if(((buffer==number1)||(buffer==number2)||(buffer==number3))&&((msgOn=="On")||(msgOn=="ON")||(msgOn=="on"))) { digitalWrite(led, HIGH); } } delay(100); } In the lines above commented with "problem": -> When I write String number1 = "8320389582"; //problem like this and when I use this for toggling led like this if(((buffer==number1)||(buffer==number2)||(buffer==number3))&&((msgOn=="On")||(msgOn=="ON")||(msgOn=="on"))) { digitalWrite(led, HIGH); } This doesnt work but instead when I use the code like if(((buffer=="+91963xxxx")||(buffer=="+91963XXXX")||(buffer=="+918753XXX"))&&((msgOn=="On")||(msgOn=="ON")||(msgOn=="on"))) { digitalWrite(led, HIGH); } This works and I can toggle the led. According to my understanding there is some compiler issue in this related to memory for local loop. Can anyone help me with this? I am attaching my code for reference. Thanks, Shailav prefinal.rar
  17. Hi All , I am using cc3200 launchpad and energia as IDE in my application . I wrote some code in that around 16 gpio of cc3200 so some of gpio are toggling automatically can anyone suggest me what modification I need to do ?
  18. Hello all ! Im going to cut straight to the matter. I was trying to follow this tutorial/project : Essentially i am using the CC3200 to take a picture and upload it. However the problem im already running into is the following : When i include the adafruit serial camera library i get prompted for <SoftwareSerial.h>. The Adafruit library in question ofcourse uses and needs the SoftwareSerial library. I cannot find any SoftwareSerial library for the CC3200 even though i have sufficient google skills. Using the SoftwareSerial library from the MSP430 obviously doesnt work because its not compatible. I also want to note that im using V17 Energia. This is because when i used the new board management feature in V18 it didnt create a cc3200 folder under "energia\hardware" and as such i had no libraries availible at all. HOWEVER using v17 of energia i now correctly have a cc3200 folder with its coherrent library folder. tldr; Cannot find any usable SoftwareSerial library for cc3200, pls help.
  19. My compact Lisp interpreter, uLisp, now supports the MSP430F5529 and MSP430FR5969 LaunchPads. As well as supporting a core set of Lisp functions, uLisp includes Arduino/Energia extensions, making it ideal as a control language for the MSP430. For more information see
  20. I finished up my first Energia project, a template library for the Bosch BMP085 temperature and pressure sensor. It uses I2C and supports temperature in Celsius and pressure in Pascal. I connected the GY-80 breakout commonly found on eBay, but it should also work with most other BMP085 breakouts, like the ones from Adafruit or Sparkfun. Note that I had to patch Energia to make 1-byte read work on MSP430G2553 with Rev1.5 LaunchPad. I also had to remove the LED2 jumper, probably due to too weak I2C pull-up. Update: Tested on LaunchPad 1.5 with MSP430G2553, StellarPad Rev A and Arduino R3. Energia requires patches 226 and 235 in twi.c for I2C to work properly on MSP430G2553 Updates: - Tested with Energia 0101E0010 with MSP430G2553 and F5529, no more I2C patches needed. - Tested with BMP180 and Software I2C - Fixed I2C for Energia 0101E0016 by removing ugly hacks from the past from the library code. Tested only with MSP430G2553
  21. Hello all! So, this is happening on BOTH my Ubuntu 16.04 AND Windows 8.1 systems. This is for a TM4C1294NCPDT. To reduce potential variables, I've reverted to using the EK-TM4C1294XL Development Board. To reproduce: Fresh install of CCSv7.1, Fresh install of Energia 18. Open CCSv7, Create a new workspace, select 'Project > New Energia Sketch', Energia Version set to 18, select 'Built-in Examples > 01.Basics > Blink.ino', selected device: 'LaunchPad (Tiva C) w/ tm4c129 (120MHz), select 'Finish'. Right Click 'Blink" project in the Project Explorer, select "Build Project'. Project builds fine. Push F11 (or select 'Debug Blink' from the toolbar). Code is uploaded, but the debug 'Resume' button is grayed out. LED does not blink. Note: 'Blink' runs fine in the Energia IDE itself. What happened in the update to CCSv7? I'm taking a shot in the dark here, but I think the memory map is b0rked. If I disable "On a program load or restart" in the 'Debug > Auto Run and Launch Options' and then attempt to debug, CCS starts the debugger at "void ResetISR(void) {" in startup_gcc.c. See attached image for disassembly view. I think (IIRC) that the two ldr calls in assembly are usually right below that 'push', but my memory ain't what it used to be. Anyhow, if I try to 'Step Into' with F5, I immediately get a dreaded "No source available for "0xfffffffe" ... So, any idea what the hell happened? This shoots me dead until this is resolved... I figured TI would at least test Energia GCC debugging before releasing v7, though I do tend to err with my assumptions quite often. If you need anything, just holler. EDIT: For posterity, here's my TI E2E forum post on the same:
  22. Hi everybody, >>> UPDATE - Made "proper" Energia Library out of it. Now with proper named methods/class members<<< >>> UPDATE 2 - Added "keywords.txt" file for syntax highlighting, added comments to "Mfrc522.cpp" file explaining methods (thanks to Grant) - Added example to read cards contents of block 1 <<< >>> UPDATE 3 - You need to apply the USCI SPI fix proposed by Spirilis (post #22) in the following thread: , otherwise the card reader won't work! <<<< I wanted to share my results with the MF RC522 RFID reader. I found an article from Grant Gibson ( where he used a cheap reader from eBay to read Mifare cards. ( The command set and technical aspects of the MFRC522 chip can be found in the datasheet: I have ported the example to Energia. Very simple by removing all Chinese comments and replacing uchar with unsigned chars. After these changes it works like a charm. Just connect the following lines: MOSI LP -> Pin 3 of the module MISO LP -> Pin 4 of the module PIn 1.3 LP -> Pin 1 of the module (SS) Pin 2.2 LP -> Pin 7 of the module (RST) Pin 1.5 LP -> Pin 2 of the module (SCK) GND LP -> Pin 6 of the module VCC LP -> Pin 8 of the module Pin 5 is not connected. Included is the sketch ( I used. Now onto opening doors and paying electronically! Kind regards, Eelco
  23. Hello everyone !! I have a small problem and it is the following: First I'm simulating sensors with approximate random's values, and I need to upload this data to pubnub and freeboard as monitoring platform, the problem I have is that in pubnub I find the values updated in real time, What happens, is that when I upload to freeboard are not updated, they take a fixed number. I am hesitating in the way of storing them, I think it is not appropriate. I have the well-linked accounts between pubnub and freeboard. Greetings. MR this is my code !! #include <SPI.h> #include <WiFi.h> #include "PubNub.h" #include <aJSON.h> #define NUM_CHANNELS 4 // How many analog channels do you want to read double randomDouble(double min, double max, int numCasas){ long _min = min * pow(10, numCasas) + 0.1; long _max = max * pow(10, numCasas) + 0.1; return (double) random(_min, _max) / pow(10, numCasas) ; } int sn=0; char pubkey[] = "***"; char subkey[] = "***"; char channel[] ="***"; char uuid[] = "***"; // your network name also called SSID char ssid[] = "***"; // your network password char password[] = "***"; static int keyIndex = 0; void setup() { Serial.begin(115200); randomSeed(analogRead(0)); PubNub.begin(pubkey, subkey); PubNub.set_uuid(uuid); Serial.println("PubNub set up"); } void loop() { double Freq = randomDouble(10.71, 10.79, 2)+1839755.00; double voltage_1 = randomDouble(0.82, 0.88, 2); double temperature = randomDouble(18.30, 20.00, 2); double vol = randomDouble(3.10, 3.29, 2); double data[] = {Freq, voltage_1, temperature, vol}; PubSubClient *client; // create JSON objects aJsonObject *msg, *dataReadings; msg = aJson.createObject(); aJson.addItemToObject(msg, "DataReading", dataReadings = aJson.createObject()); // get latest sensor values then add to JSON message for (int i = 0; i < NUM_CHANNELS; i++) { String Channel = String(data[i]); char charBuf[Channel.length()+1]; Channel.toCharArray(charBuf, Channel.length()+1); double Values = data[i]; aJson.addNumberToObject(dataReadings, charBuf, Values); } // convert JSON object into char array, then delete JSON object char *json_String = aJson.print(msg); aJson.deleteItem(msg); // publish JSON formatted char array to PubNub Serial.print("publishing a message: "); Serial.println(json_String); PubNub.publish(channel, json_String); free(json_String); delay(500); }
  24. Hello, I am working on cc3200MOD Controller.This controller we use in our product. I am developing a code in Energia v.15. and I load a program using USB to TTL device using UART0. But during loading program following error message occur: erase file completed Downloading file "/sys/mcuimg.bin" with size 4064 .Download complete DEBUG cc3200prog.c:2623: write failed DEBUG cc3200prog.c:2629: write failed DEBUG cc3200prog.c:2635: write failed DEBUG cc3200prog.c:2641: write failed So, Please tell me the solution. Regards, Pratik
  25. Hello, After installing E18, and getting the TivaC board package with packages manager, when I try to upload a program into the Tiva-C board I get the following error: fork/exec /home/can/.energia15/packages/energia/tools/arm-none-eabi-gcc/4.8.4-20140725/bin/arm-none-eabi-g++: no such file or directory Error compiling for board LaunchPad (Tiva C) w/ tm4c123 (80MHz). If I go the the mentioned directory, I can see that the arm-none-eabi-g++ executable exists by: $ file arm-none-eabi-g++ arm-none-eabi-g++: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/, for GNU/Linux 2.6.8, stripped I have no /lib/ on my system. It used to be we needed to install a package named ia32libs on ubuntu systems. But unfortunately on ubuntu 16.04 64, I could not find this package. And here is my uname -a Linux daredevil 4.4.0-62-generic #83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux Any ideas / recomendations / help greatly appreciated, Best, C.