Jump to content
43oh

spirilis

Members
  • Content Count

    3,399
  • Joined

  • Last visited

  • Days Won

    146

Reputation Activity

  1. Like
    spirilis got a reaction from abecedarian in My time with FreeRTOS on the TM4C   
    Picking this forum for a blog thread on learning the "ropes" of FreeRTOS.  TM4C123 launchpad is my learning board for now, using CCSv6 under Windows, latest FreeRTOS and the GNU GCC compiler that ships with CCS (Linaro).
     
    From a fresh download of FreeRTOS, I finally have a working example (not relying on "importing" a CCS example and modifying it - you learn more this way).  Here's main.cpp with all the init + task code:
    /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include <timers.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" void UsrSW1_Monitor(void *); int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)) ; MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD); if (pdTRUE != xTaskCreate(UsrSW1_Monitor, "Pushbutton_Monitor", 48, NULL, 3, NULL)) { // Crash due to insufficient heap memory? MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2); // Illuminate R+B for purple while(1) ; } //xTaskCreate(NullTask, "Nothing", 48, (void *)1, 4, NULL); vTaskStartScheduler(); // If FreeRTOS ever exits, illuminate orange (R+G) MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_3); while(1) ; return 0; } void BlinkyTask_LEDBlink(void *pvParams) { unsigned int whichLed = (unsigned int)pvParams; uint8_t whichBit = 1 << whichLed; uint8_t currentValue = 0; while (1) { currentValue ^= whichBit; MAP_GPIOPinWrite(GPIO_PORTF_BASE, whichBit, currentValue); vTaskDelay(250 / portTICK_RATE_MS); } } void UsrSW1_Monitor(void *pvParams) { uint16_t inputShifter = 0; bool inputLatched = false; const uint32_t USR_SW1 = GPIO_PIN_4; // PF4 uint8_t whichLed = 1; xTaskHandle blinkerTask; // Start blinker task with current whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } while (1) { // Poll USR_SW1 GPIO - active LOW if (MAP_GPIOPinRead(GPIO_PORTF_BASE, USR_SW1)) { inputShifter <<= 1; } else { inputShifter <<= 1; inputShifter |= 1; } // Test if button has been pressed or released if ( !inputLatched && (inputShifter & 0xF0) == 0xF0 ) { // Rotate LED whichLed++; if (whichLed > 3) { whichLed = 1; } // Kill blinker task vTaskDelete(blinkerTask); // Switch off all LEDs MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0); // Start new blinker task with new whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } // Latch button press so we don't re-trigger until button has been released inputLatched = true; } if ( inputLatched && (inputShifter & 0xFF) == 0 ) { inputLatched = false; // un-latch USR_SW1 } // Wait 10ms before checking again vTaskDelay(10 / portTICK_RATE_MS); } } Result: Red LED blinks, left pushbutton toggles to blue & green and back to red.  Pressing & holding the pushbutton switches the LED but only once, as the pushbutton task "latches" it.
     
    The technique of debouncing a pushbutton using periodic polling + bit shifts and logic tests was something I saw on hackaday recently - http://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/
    I didn't use the same test values but it doesn't matter...
     
    Using polling instead of interrupt for the pushbutton is definitely one of those things that is easy & practical only if using an RTOS.
  2. Like
    spirilis got a reaction from zeke in My time with FreeRTOS on the TM4C   
    Ok, diversion into a small project.  Getting FreeRTOS working in CCS on a TM4C123 LaunchPad from ground zero.  With screenshots.  More of a noob guide or hand-holding for folks using CCS who want to get started quickly.
     
    Step 1: Create a new CCS project using the GNU GCC compiler.  Ours is called "rtosnull"

     
    With the project created, we are now going to import FreeRTOS first.  Right-click on the project, and make a New folder:

     
    Call it "FreeRTOS".  Now we'll import the necessary FreeRTOS files into this folder:
     
    Right-click on the new FreeRTOS folder, then go Import > Import...

     
    Use Import from File System:

     
    Navigate to your unzipped copy of the latest FreeRTOS source code:

     
    Selecting "Source" and hit OK, you can now peruse the directory structure and choose which files you want to import.  Supposedly "co-routines" aren't used much and we don't need readme.txt, so deselect them.  It's not a problem if you include them though.  On the left side, underneath Source, be sure the entire "include" directory is selected - although you can go in there and uncheck the croutine.h file too.  Or not, it won't hurt anything.

     
    Expand "Source" on the left pane though, and start walking the directory structure down.  In particular we need to choose which of the "portable" folder contents we want - the Memory Manager (Source / portable / MemMang) and the main "port" (Source / portable / GCC / ARM_CM4F in our case).  Within MemMang we're going to select heap_2.c which is a reasonable malloc/free manager for our purposes:

     
    Underneath Source / portable / GCC, go into ARM_CM4F and choose everything (it's only 2 files):

     
    Make sure to UN-CHECK the "Create top-level folder" option in this window, then hit Finish to import all your FreeRTOS files.
     
    The FreeRTOS files should now be in your project under that FreeRTOS directory:

  3. Like
    spirilis got a reaction from zeke in I'm struggling with the CC3200   
    On this subject - I admit I am not sure why someone would use a CC3200 either.  I don't find it particularly attractive.  Its MCU is a jack-of-few-trades-master-of-absolutely-none Cortex-M4 implementation, the analog integration sucks (see @@Rei Vilo 's complaints about the ADC's max voltage and burning out I/O pins), its memory implementation is an odd mix of MCU addressable memory (SRAM) and non-addressable flash (external Serial SPI flash) unlike other MCUs with on-board flash... I don't like it.  I do use the CC3100 from time to time even though it's expensive but that's because frankly I think it's a better chip than the ESP8266 in that it has firmware-built-in webserver, mDNS, SSL (server-socket or client-socket).  The CC3200 is basically "oh, I don't need much, just something functional as a basic MCU so I don't need to pull another one in to connect to the CC3100 which is the whole point of what I'm after".  It is expensive though.  Not a big deal for one-off projects.
     
    Or maybe I should say, ESP8266 changed the game by making cheap MCU WiFi possible *at all*, and now that pandora's box is open, the entire market sentiment has shifted.  Bear in mind before TI's CC3xxx series, the only options were things like Wiznet's WiFi which had a group buy here ... and IIRC the per-chip price was something like $25 or $35 right?  So TI's CC3100/3200 is best viewed as a (superior featured) contender stuck in the paradigm of >$20 wifi MCU modules right at the cusp of ESP8266's disruptive onslaught.  So now with the upcoming ESP32 leapfrogging all the competing vendors' next step, it'll be interesting to see how TI responds.
  4. Like
    spirilis got a reaction from zeke in I'm struggling with the CC3200   
    Varies.  FreeRTOS doesn't exactly provide drivers for a chip's peripherals, what they do provide are validated "ports" for various processors (in the Demo section and Source/portable sections of their download).  This provides the "portable" sections that target a particular arch, which includes the Scheduling, Interrupt handling and Memory Management primitives.  The vendor might provide drivers though.  TI does seem to have an "osi" abstraction library for use with their CC3200 and possibly others which intends to provide RTOS-or-non-RTOS agnostic abstraction of certain functions, but I don't know a whole lot about it.  I do know BLE-Stack uses it for the CC26xx devices (even the older CC2540 8051-based BLE chip used it in its code).
     
    For TI Hercules, HALCoGen provides the drivers for you as a customizable driverlib.
     
    So it varies.  The FreeRTOS folks don't take on this responsibility themselves though.
  5. Like
    spirilis got a reaction from zeke in My time with FreeRTOS on the TM4C   
    RTOS concurrency and communications peripherals.  How about we take 2 tasks and have them both spam the SPI peripheral on the Tiva with output?
     
    main.c:
    /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #include "driverlib/ssi.h" // for SPI #include <string.h> // for strlen() void Task_SPI_Transfer(void *); int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); // SSI2 on PB4/PB6/PB7 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // Need this to configure PB for SSI usage while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_SSI2)) ; while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)) ; // Configure PB4, PB6, PB7 as SSI pins MAP_GPIOPinTypeSSI(GPIO_PORTB_BASE, (GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_7) ); /* Sadly, it's not just enough to configure GPIO pins for the correct peripheral. You also have to set a register called GPIOPCTL for these. * * Register 22: GPIO Port Control (GPIOPCTL), offset 0x52C * The GPIOPCTL register is used in conjunction with the GPIOAFSEL register and selects the specific * peripheral signal for each GPIO pin when using the alternate function mode. Most bits in the * GPIOAFSEL register are cleared on reset, therefore most GPIO pins are configured as GPIOs by * default. When a bit is set in the GPIOAFSEL register, the corresponding GPIO signal is controlled * by an associated peripheral. The GPIOPCTL register selects one out of a set of peripheral functions * for each GPIO, providing additional flexibility in signal definition. */ MAP_GPIOPinConfigure(GPIO_PB4_SSI2CLK); MAP_GPIOPinConfigure(GPIO_PB6_SSI2RX); MAP_GPIOPinConfigure(GPIO_PB7_SSI2TX); // Init SSI2 MAP_SSIClockSourceSet(SSI2_BASE, SSI_CLOCK_SYSTEM); // System CPU clock used MAP_SSIConfigSetExpClk(SSI2_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 8000000, 8); // 8MHz SPI, mode 0, 8 bits MAP_SSIEnable(SSI2_BASE); // SPI peripheral is now live. // Two EQUAL PRIORITY tasks will continously duke it out trying to send SPI data. // Prototype for xTaskCreate: // BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, // const char * const pcName, // uint16_t usStackDepth, // void *pvParameters, // UBaseType_t uxPriority, // TaskHandle_t *pvCreatedTask); xTaskCreate(Task_SPI_Transfer, "Task1", 32, "The quick brown fox", 4, NULL); xTaskCreate(Task_SPI_Transfer, "Task2", 32, "bluehash runs a great forum", 4, NULL); vTaskStartScheduler(); // Start FreeRTOS! while(1) ; // Shouldn't get here. return 0; } void Task_SPI_Transfer(void *pvParameters) { const char *str = (const char *)pvParameters; const size_t slen = strlen(str); size_t i = 0; while (1) { // Wait for SPI peripheral to stop transmitting while (MAP_SSIBusy(SSI2_BASE)) ; // Stuff the FIFO full while (MAP_SSIDataPutNonBlocking(SSI2_BASE, str[i]) > 0) { i++; // Note: do not be tempted to use "str[i++]" in the while() statement for this. It will increment 'i' even if the call fails. if (i >= slen) { i = 0; } } } } After capturing 100ms of the output, my Saleae Logic16's software did a protocol analysis of the SPI data and after mangling it a bit with GNU awk, here's what it looks like (apostrophes are meant to be spaces):
    b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u Besides the endless accolades it provides for @@bluehash, of note is that you can tell when the RTOS tick "task switch" occurred:
     
    b l u e h a s h ' r u n s ' a ' g r e a t ' f T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n
     
    Now that's no good!  Even if the point was to spam the SPI bus with data, doing so in coherent blocks/sentences would be preferable.  Those sentences could be coherent blocks of data or control information for an Ethernet peripheral, SPI-attached radio (CC3100, nRF24L01+, etc) or who knows.  Having the data cut in the middle of a logically-contiguous block could cause corruption (especially if separate SPI Chip Select lines are used - but - the task never had a chance to complete its SPI I/O and then deselect the intended peripheral's SPI CS line before the next task goes to town).  Moreover, electrical problems/short circuits could result if multiple SPI slave devices try driving the MISO line due to more than 1 having their Chip Select line selected.  How do we manage this in an RTOS environment?
     
    One way is using Mutual Exclusion - mutex's - and having a common mutex for an SPI peripheral.  Another way, would be a "gatekeeper" task - a task specifically designed to perform SPI communication on everyone else's behalf, using RTOS queues to pass the buffers back and forth.  This gatekeeper task would take a single request off the queue, then run it to completion, returning the results in a private queue encapsulated inside the request for the original caller to digest - all the while, NOT reading from the queue so that other tasks attempting to use the SPI bus will halt.  I am going to try the Mutex idea first, then the gatekeeper task.
  6. Like
    spirilis reacted to tripwire in My time with FreeRTOS on the TM4C   
    This is where it gets really interesting! Any RTOS can turn out a clean-looking led blinking program. The true test is how it deals with shared resources. I'm looking forward to the next few posts!
  7. Like
    spirilis reacted to Rei Vilo in My time with FreeRTOS on the TM4C   
    I've used a semaphore to manage the access of several task to a Serial port. See Galaxia - Semaphore.
  8. Like
    spirilis got a reaction from bluehash in My time with FreeRTOS on the TM4C   
    RTOS concurrency and communications peripherals.  How about we take 2 tasks and have them both spam the SPI peripheral on the Tiva with output?
     
    main.c:
    /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #include "driverlib/ssi.h" // for SPI #include <string.h> // for strlen() void Task_SPI_Transfer(void *); int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); // SSI2 on PB4/PB6/PB7 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // Need this to configure PB for SSI usage while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_SSI2)) ; while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)) ; // Configure PB4, PB6, PB7 as SSI pins MAP_GPIOPinTypeSSI(GPIO_PORTB_BASE, (GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_7) ); /* Sadly, it's not just enough to configure GPIO pins for the correct peripheral. You also have to set a register called GPIOPCTL for these. * * Register 22: GPIO Port Control (GPIOPCTL), offset 0x52C * The GPIOPCTL register is used in conjunction with the GPIOAFSEL register and selects the specific * peripheral signal for each GPIO pin when using the alternate function mode. Most bits in the * GPIOAFSEL register are cleared on reset, therefore most GPIO pins are configured as GPIOs by * default. When a bit is set in the GPIOAFSEL register, the corresponding GPIO signal is controlled * by an associated peripheral. The GPIOPCTL register selects one out of a set of peripheral functions * for each GPIO, providing additional flexibility in signal definition. */ MAP_GPIOPinConfigure(GPIO_PB4_SSI2CLK); MAP_GPIOPinConfigure(GPIO_PB6_SSI2RX); MAP_GPIOPinConfigure(GPIO_PB7_SSI2TX); // Init SSI2 MAP_SSIClockSourceSet(SSI2_BASE, SSI_CLOCK_SYSTEM); // System CPU clock used MAP_SSIConfigSetExpClk(SSI2_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 8000000, 8); // 8MHz SPI, mode 0, 8 bits MAP_SSIEnable(SSI2_BASE); // SPI peripheral is now live. // Two EQUAL PRIORITY tasks will continously duke it out trying to send SPI data. // Prototype for xTaskCreate: // BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, // const char * const pcName, // uint16_t usStackDepth, // void *pvParameters, // UBaseType_t uxPriority, // TaskHandle_t *pvCreatedTask); xTaskCreate(Task_SPI_Transfer, "Task1", 32, "The quick brown fox", 4, NULL); xTaskCreate(Task_SPI_Transfer, "Task2", 32, "bluehash runs a great forum", 4, NULL); vTaskStartScheduler(); // Start FreeRTOS! while(1) ; // Shouldn't get here. return 0; } void Task_SPI_Transfer(void *pvParameters) { const char *str = (const char *)pvParameters; const size_t slen = strlen(str); size_t i = 0; while (1) { // Wait for SPI peripheral to stop transmitting while (MAP_SSIBusy(SSI2_BASE)) ; // Stuff the FIFO full while (MAP_SSIDataPutNonBlocking(SSI2_BASE, str[i]) > 0) { i++; // Note: do not be tempted to use "str[i++]" in the while() statement for this. It will increment 'i' even if the call fails. if (i >= slen) { i = 0; } } } } After capturing 100ms of the output, my Saleae Logic16's software did a protocol analysis of the SPI data and after mangling it a bit with GNU awk, here's what it looks like (apostrophes are meant to be spaces):
    b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f o r u m b l u e h a s h ' r u n s ' a ' g r e a t ' f T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n ' f o x T h e ' q u Besides the endless accolades it provides for @@bluehash, of note is that you can tell when the RTOS tick "task switch" occurred:
     
    b l u e h a s h ' r u n s ' a ' g r e a t ' f T h e ' q u i c k ' b r o w n ' f o x T h e ' q u i c k ' b r o w n
     
    Now that's no good!  Even if the point was to spam the SPI bus with data, doing so in coherent blocks/sentences would be preferable.  Those sentences could be coherent blocks of data or control information for an Ethernet peripheral, SPI-attached radio (CC3100, nRF24L01+, etc) or who knows.  Having the data cut in the middle of a logically-contiguous block could cause corruption (especially if separate SPI Chip Select lines are used - but - the task never had a chance to complete its SPI I/O and then deselect the intended peripheral's SPI CS line before the next task goes to town).  Moreover, electrical problems/short circuits could result if multiple SPI slave devices try driving the MISO line due to more than 1 having their Chip Select line selected.  How do we manage this in an RTOS environment?
     
    One way is using Mutual Exclusion - mutex's - and having a common mutex for an SPI peripheral.  Another way, would be a "gatekeeper" task - a task specifically designed to perform SPI communication on everyone else's behalf, using RTOS queues to pass the buffers back and forth.  This gatekeeper task would take a single request off the queue, then run it to completion, returning the results in a private queue encapsulated inside the request for the original caller to digest - all the while, NOT reading from the queue so that other tasks attempting to use the SPI bus will halt.  I am going to try the Mutex idea first, then the gatekeeper task.
  9. Like
    spirilis got a reaction from yyrkoon in My time with FreeRTOS on the TM4C   
    Picking this forum for a blog thread on learning the "ropes" of FreeRTOS.  TM4C123 launchpad is my learning board for now, using CCSv6 under Windows, latest FreeRTOS and the GNU GCC compiler that ships with CCS (Linaro).
     
    From a fresh download of FreeRTOS, I finally have a working example (not relying on "importing" a CCS example and modifying it - you learn more this way).  Here's main.cpp with all the init + task code:
    /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include <timers.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" void UsrSW1_Monitor(void *); int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)) ; MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD); if (pdTRUE != xTaskCreate(UsrSW1_Monitor, "Pushbutton_Monitor", 48, NULL, 3, NULL)) { // Crash due to insufficient heap memory? MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2); // Illuminate R+B for purple while(1) ; } //xTaskCreate(NullTask, "Nothing", 48, (void *)1, 4, NULL); vTaskStartScheduler(); // If FreeRTOS ever exits, illuminate orange (R+G) MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_3); while(1) ; return 0; } void BlinkyTask_LEDBlink(void *pvParams) { unsigned int whichLed = (unsigned int)pvParams; uint8_t whichBit = 1 << whichLed; uint8_t currentValue = 0; while (1) { currentValue ^= whichBit; MAP_GPIOPinWrite(GPIO_PORTF_BASE, whichBit, currentValue); vTaskDelay(250 / portTICK_RATE_MS); } } void UsrSW1_Monitor(void *pvParams) { uint16_t inputShifter = 0; bool inputLatched = false; const uint32_t USR_SW1 = GPIO_PIN_4; // PF4 uint8_t whichLed = 1; xTaskHandle blinkerTask; // Start blinker task with current whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } while (1) { // Poll USR_SW1 GPIO - active LOW if (MAP_GPIOPinRead(GPIO_PORTF_BASE, USR_SW1)) { inputShifter <<= 1; } else { inputShifter <<= 1; inputShifter |= 1; } // Test if button has been pressed or released if ( !inputLatched && (inputShifter & 0xF0) == 0xF0 ) { // Rotate LED whichLed++; if (whichLed > 3) { whichLed = 1; } // Kill blinker task vTaskDelete(blinkerTask); // Switch off all LEDs MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0); // Start new blinker task with new whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } // Latch button press so we don't re-trigger until button has been released inputLatched = true; } if ( inputLatched && (inputShifter & 0xFF) == 0 ) { inputLatched = false; // un-latch USR_SW1 } // Wait 10ms before checking again vTaskDelay(10 / portTICK_RATE_MS); } } Result: Red LED blinks, left pushbutton toggles to blue & green and back to red.  Pressing & holding the pushbutton switches the LED but only once, as the pushbutton task "latches" it.
     
    The technique of debouncing a pushbutton using periodic polling + bit shifts and logic tests was something I saw on hackaday recently - http://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/
    I didn't use the same test values but it doesn't matter...
     
    Using polling instead of interrupt for the pushbutton is definitely one of those things that is easy & practical only if using an RTOS.
  10. Like
    spirilis reacted to jazz in GPIO state when programming with SBW   
    If SBW / JTAG master execute target device RESET (SBW / JTAG command, not related to changing RESET pin state) then all pins (except SBW / JTAG) will have after device RESET state (input without pulling).
     
    SBW / JTAG master also can put target device under SBW / JTAG control and execute target device flashing without RESET command. In this case pin states will be untouched.
  11. Like
    spirilis got a reaction from zeke in My time with FreeRTOS on the TM4C   
    TivaWare examples usually have a lot of #include's.  This looks like a decent minimal list for doing sysctl configuration (e.g. system clock and enabling peripherals) and GPIO:

     
    The TARGET_IS_TM4C123_RB1 #define we put in the project's symbols enables correct use of the MAP_ and ROM_ version of the various driverlib calls.  Proof is in driverlib/rom.h:
    //***************************************************************************** // // Macros for calling ROM functions in the ADC API. // //***************************************************************************** #if defined(TARGET_IS_TM4C123_RA1) || \ defined(TARGET_IS_TM4C123_RA3) || \ defined(TARGET_IS_TM4C123_RB1) || \ defined(TARGET_IS_TM4C123_RB2) || \ defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) #define ROM_ADCSequenceDataGet \ ((int32_t (*)(uint32_t ui32Base, \ uint32_t ui32SequenceNum, \ uint32_t *pui32Buffer))ROM_ADCTABLE[0]) #endif #if defined(TARGET_IS_TM4C123_RA1) || \ defined(TARGET_IS_TM4C123_RA3) || \ defined(TARGET_IS_TM4C123_RB1) || \ defined(TARGET_IS_TM4C123_RB2) || \ defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) #define ROM_ADCIntDisable \ ((void (*)(uint32_t ui32Base, \ uint32_t ui32SequenceNum))ROM_ADCTABLE[1]) #endif rom_map.h wraps those calls in MAP_ prefixes so that if it's discovered that a certain Tiva silicon release had a bug in its ROM driver code, updated TivaWare editions may choose to use a source-compiled version of the driverlib function instead of the ROM_ version.  We'll use MAP_ for all our driverlib calls.  There is one exception IIRC, I think it's IntRegister(), that can never use the ROM version but we aren't going to touch it during this example.
     
    Note that the exact TARGET define, e.g. TARGET_IS_TM4C123_RB1, should actually be doctored to coincide with the exact silicon you're using.  RB2 is the very latest revision as of March 2016, but if you're building this for an earlier release of the Tiva chip, it might be prudent to investigate the actual CPU revision you're running (see the chip's datasheet - should be gleaned from reading the markings on the chip but you can figure this out programmatically) and use the correct TARGET_IS_TM4C123_Rxy setting.  (I actually think mine is older than RB1, but it's not a big problem for this example).  Anyway, the available versions can be found by examining driverlib/rom.h and then look at the Tiva chip's datasheet + errata sheet for more details on versions, bugs, etc.
     
    Here's our original main.c, reworked to use TivaWare just to properly configure the CPU clock:
    /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" void NullTaskFunc(void *); // prototype so we can include it in main while the code is underneath int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); // Prototype for xTaskCreate: // // BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, // const char * const pcName, // uint16_t usStackDepth, // void *pvParameters, // UBaseType_t uxPriority, // TaskHandle_t *pvCreatedTask); if (pdTRUE != xTaskCreate(NullTaskFunc, "Null Task", 32, NULL, 4, NULL)) { while (1) ; // Oh no! Must not have had enough memory to create the task. } vTaskStartScheduler(); // Start FreeRTOS! // Should never get here since the RTOS should never "exit". while(1) ; return 0; } // Our RTOS "task" - does absolute jack squat void NullTaskFunc(void *pvParameters) { while (1) { vTaskDelay(10000); // With this task always delaying, the RTOS Idle Task runs almost all the time. } } This configures the PLL with correct crystal speed, enabling the crystal oscillator, to land us at 80MHz.
     
    Note that in main.c, if you forgot to include stdbool.h, some of the driverlib .h files will complain:

     
    Also, driverlib imports a file called "epi_workaround_ccs.s" which won't compile under GCC, so we should delete it:

     

     
    Now it builds correctly:

     
    Our FreeRTOS project thus far doesn't do anything visibly different from the last time we built it, besides the CPU clock running at the correct frequency, so we'll skip running it for now.  Next, we're going to create another task that blinks an LED, and I'll include logic analyzer output validating the cadence of the blink.
  12. Like
    spirilis got a reaction from pine in My time with FreeRTOS on the TM4C   
    Picking this forum for a blog thread on learning the "ropes" of FreeRTOS.  TM4C123 launchpad is my learning board for now, using CCSv6 under Windows, latest FreeRTOS and the GNU GCC compiler that ships with CCS (Linaro).
     
    From a fresh download of FreeRTOS, I finally have a working example (not relying on "importing" a CCS example and modifying it - you learn more this way).  Here's main.cpp with all the init + task code:
    /* * main.c */ #include <FreeRTOS.h> #include <task.h> #include <timers.h> #include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" void UsrSW1_Monitor(void *); int main(void) { MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)) ; MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD); if (pdTRUE != xTaskCreate(UsrSW1_Monitor, "Pushbutton_Monitor", 48, NULL, 3, NULL)) { // Crash due to insufficient heap memory? MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2); // Illuminate R+B for purple while(1) ; } //xTaskCreate(NullTask, "Nothing", 48, (void *)1, 4, NULL); vTaskStartScheduler(); // If FreeRTOS ever exits, illuminate orange (R+G) MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_3); while(1) ; return 0; } void BlinkyTask_LEDBlink(void *pvParams) { unsigned int whichLed = (unsigned int)pvParams; uint8_t whichBit = 1 << whichLed; uint8_t currentValue = 0; while (1) { currentValue ^= whichBit; MAP_GPIOPinWrite(GPIO_PORTF_BASE, whichBit, currentValue); vTaskDelay(250 / portTICK_RATE_MS); } } void UsrSW1_Monitor(void *pvParams) { uint16_t inputShifter = 0; bool inputLatched = false; const uint32_t USR_SW1 = GPIO_PIN_4; // PF4 uint8_t whichLed = 1; xTaskHandle blinkerTask; // Start blinker task with current whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } while (1) { // Poll USR_SW1 GPIO - active LOW if (MAP_GPIOPinRead(GPIO_PORTF_BASE, USR_SW1)) { inputShifter <<= 1; } else { inputShifter <<= 1; inputShifter |= 1; } // Test if button has been pressed or released if ( !inputLatched && (inputShifter & 0xF0) == 0xF0 ) { // Rotate LED whichLed++; if (whichLed > 3) { whichLed = 1; } // Kill blinker task vTaskDelete(blinkerTask); // Switch off all LEDs MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0); // Start new blinker task with new whichLed value. if (pdTRUE != xTaskCreate(BlinkyTask_LEDBlink, "Blinker", 32, (void*)whichLed, 4, &blinkerTask)) { // Crash due to insufficient heap memory? Halt scheduler and hold all RGB LEDs to white. vTaskSuspendAll(); MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); while(1) ; } // Latch button press so we don't re-trigger until button has been released inputLatched = true; } if ( inputLatched && (inputShifter & 0xFF) == 0 ) { inputLatched = false; // un-latch USR_SW1 } // Wait 10ms before checking again vTaskDelay(10 / portTICK_RATE_MS); } } Result: Red LED blinks, left pushbutton toggles to blue & green and back to red.  Pressing & holding the pushbutton switches the LED but only once, as the pushbutton task "latches" it.
     
    The technique of debouncing a pushbutton using periodic polling + bit shifts and logic tests was something I saw on hackaday recently - http://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/
    I didn't use the same test values but it doesn't matter...
     
    Using polling instead of interrupt for the pushbutton is definitely one of those things that is easy & practical only if using an RTOS.
  13. Like
    spirilis reacted to cde in The excitement of ordering parts on Ebay   
    Mifare classic hasn't been compatible with most galaxy phones from the S4 generation and up. Mifare classic is basically broken out the box by NXP, and since they don't license out, all the phones with broadcom NFC radios can't access them.
  14. Like
    spirilis reacted to roadrunner84 in Neural network code   
    You need to buy a controller with the DWIM module built in, choose any of the MSP430G7xxx chips and you'll be fine.
  15. Like
    spirilis got a reaction from chicken in The excitement of ordering parts on Ebay   
    Worst I've had so far is I bought about 10 NFC tags off aliexpress that were mifare compatible but... my Samsung Galaxy Note 5 won't read/write from them.  Unsupported.  Oh well, only cost me $2 plus free shipping from China (that still blows my mind...)
  16. Like
    spirilis reacted to cubeberg in The excitement of ordering parts on Ebay   
    Bought a set of NRF24L01 boards - awesome price. When they came there were no passives on the board - just the chip (there was a Hackaday article about it at some point). Thankfully I was able to get a refund.
  17. Like
    spirilis got a reaction from zeke in My time with FreeRTOS on the TM4C   
    Running the RTOS project:

     
    CCS Debug mode should initialize the ICDI debugger and upload the code, then immediately try running the firmware while breakpointing at main():

     
    Go ahead and hit the play button to continue running (without stepping):

     
    Then after a second or two, try interrupting it to see where it ends up stopped:

     

    And voila, we ended up in the middle of one of its internal cleanup functions spawned off the idle task.  At least we're not off in lala land or FaultISR(), instead we're running a validly configured RTOS.  Now this completes the basic FreeRTOS setup, in the next installment (to be continued soon), I'll import TivaWare's driverlib and start doing something useful.  Note that at this stage, FreeRTOS still thinks it's SysTick'ing off an 80MHz clock (due to our current FreeRTOSConfig.h contents) but it's doing no such thing because the CPU is running at the default power-on speed, which is something like 16MHz or 4MHz or whatever.  So all vTaskDelay's are woefully inaccurate right now.  This will be remedied once we use TivaWare driverlib to configure the main clock.
  18. Like
    spirilis reacted to chicken in The excitement of ordering parts on Ebay   
    That's what I get for being a cheapskate:

     
    Arguably, the listing does not specify the orientation of the connector. But the picture on the listing, even though out of focus, still shows vertical connectors.
    http://www.ebay.com/itm/131607709750
     
    The seller didn't answer yet, so I still assume it was a genuine mix-up.
    [Edit: It was a mix-up, the seller will send me replacements.]
     
    What were your predictable sourcing mishaps?
  19. Like
    spirilis reacted to dpharris in ESP32, a challenge to the CC3200?   
    Thanks.
     
    This is what I know about the ESP32: 
     
    At the moment there is a beta-board out to the developers.  This contains the ESP31, which is a preliminary version of the ESP32.  It does not implement a complete set of peripherals.  
     
    The ESP32 is expected relatively soon (months?) and will include al the peripherals, including CAN.   This looks like a nice chip with many expanded features over the ESP8266, including more sockets.  There are plans for a compatible Arduino-IDE for it.  
     
    There is a forum at http://www.esp32.com, but it is pretty quiet.  
  20. Like
    spirilis got a reaction from tripwire in ESP32, a challenge to the CC3200?   
    Fwiw I found out recently looking at the footprint & datasheet, TI's certified modules don't actually include an antenna (for the CC3100MOD and presumably CC3200MOD).  You still have to provide the antenna and balun.  TI's wiki mentions it's still "certified" if you follow the antenna layout guidelines in the datasheet, but in any case it's not a "simple" solder & play part (though it's probably not hard to add the antenna piece to your board).
     
    ESP32 substantially steps up the game.  WiLink-like dual protocol support but in an MCU, with double the SRAM of the CC3200, built-in Ethernet MAC and CAN.  The working temperature range seems larger too, that's closer to what TI bills for automotive grade parts IIRC...
    Speaking of which, I wonder if this is an automotive play on Espressif's part?  CAN, Ethernet, WiFi, decent MCU, wide temperature range, touch sensor support... Hmm...
  21. Like
    spirilis got a reaction from yyrkoon in I'm struggling with the CC3200   
    Varies.  FreeRTOS doesn't exactly provide drivers for a chip's peripherals, what they do provide are validated "ports" for various processors (in the Demo section and Source/portable sections of their download).  This provides the "portable" sections that target a particular arch, which includes the Scheduling, Interrupt handling and Memory Management primitives.  The vendor might provide drivers though.  TI does seem to have an "osi" abstraction library for use with their CC3200 and possibly others which intends to provide RTOS-or-non-RTOS agnostic abstraction of certain functions, but I don't know a whole lot about it.  I do know BLE-Stack uses it for the CC26xx devices (even the older CC2540 8051-based BLE chip used it in its code).
     
    For TI Hercules, HALCoGen provides the drivers for you as a customizable driverlib.
     
    So it varies.  The FreeRTOS folks don't take on this responsibility themselves though.
  22. Like
    spirilis got a reaction from yyrkoon in I'm struggling with the CC3200   
    On this subject - I admit I am not sure why someone would use a CC3200 either.  I don't find it particularly attractive.  Its MCU is a jack-of-few-trades-master-of-absolutely-none Cortex-M4 implementation, the analog integration sucks (see @@Rei Vilo 's complaints about the ADC's max voltage and burning out I/O pins), its memory implementation is an odd mix of MCU addressable memory (SRAM) and non-addressable flash (external Serial SPI flash) unlike other MCUs with on-board flash... I don't like it.  I do use the CC3100 from time to time even though it's expensive but that's because frankly I think it's a better chip than the ESP8266 in that it has firmware-built-in webserver, mDNS, SSL (server-socket or client-socket).  The CC3200 is basically "oh, I don't need much, just something functional as a basic MCU so I don't need to pull another one in to connect to the CC3100 which is the whole point of what I'm after".  It is expensive though.  Not a big deal for one-off projects.
     
    Or maybe I should say, ESP8266 changed the game by making cheap MCU WiFi possible *at all*, and now that pandora's box is open, the entire market sentiment has shifted.  Bear in mind before TI's CC3xxx series, the only options were things like Wiznet's WiFi which had a group buy here ... and IIRC the per-chip price was something like $25 or $35 right?  So TI's CC3100/3200 is best viewed as a (superior featured) contender stuck in the paradigm of >$20 wifi MCU modules right at the cusp of ESP8266's disruptive onslaught.  So now with the upcoming ESP32 leapfrogging all the competing vendors' next step, it'll be interesting to see how TI responds.
  23. Like
    spirilis got a reaction from bluehash in Avnet Free Shipping through 4/1   
    (pasting from email-)
     
    Avnet has started counting down the days to the launch of our new digital portal
  24. Like
    spirilis got a reaction from pallisi in CC3200 and external ADCs, SPI or I2C?   
    MAX31855 is a great thermocouple ADC that you talk to via digital SPI bus.
    Beware one thing with it however, there is no way to switch it "off" so it uses less power... so you may have to design a level-shifted/transistor-switched power domain for it that the MCU can switch on/off if you want to isolate its power draw during periods of "ultra low power" budget.
  25. Like
    spirilis got a reaction from yyrkoon in I'm struggling with the CC3200   
    @@zeke I'm over halfway through the standard Cortex-M3 book (printed out), which is similar to my RX600 copy I bought years ago... It's a fairly light introduction to the RTOS features and some of the gotchas, actually quite concise for an intro I think.
     
    Perusing the prerelease of the Mastering the FreeRTOS Real Time Kernel book - it's a rewrite of the prior book's generic version but with what appears to be more conceptual depth.  Also a new feature "Event Groups" I don't think was covered by the prior book (although I'm not all the way through it yet, maybe it was).  Kinda nice seeing a walkthrough on how to get a new project started - either from an existing demo (i.e. what you should remove), or from scratch with the source files (and what each source file is for).
×
×
  • Create New...