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 Fmilburn in MSP430 Wearable with Radio   
    Well whatever you use, 2.4GHz is best due to PCB antenna size. It is a shame the CC26xx series is too expensive since its high sensitivity would help make the distance even with sketchy small PCB antennas.
     
    Also for nRF stuff, I wouldn't bet on those actually making 10m at 2Mbps, but it should at 250Kbps. The issue is the human body and how it may reflect/refract RF as the wearer moves around.
  2. Like
    spirilis got a reaction from jpnorair in How to program a CC1310F64RHBT in Energia   
    Without having any way of seeing your breadboard adapter socket soldering job and where the passives are, my first assumption is you probably did something wrong with the chip's layout; FYI this isn't a chip you can casually "solder to an adapter" and expect it to work.  It has several passives including an inductor, multiple values of decoupling capacitors, a 24MHz XTAL without load caps (load caps are internal) along with a 32.768KHz XTAL with load caps that are expected (earlier revisions of the CC1310 chip couldn't run without the 32.768KHz XTAL).  I've been successful in rolling my own boards by designing them from scratch but closely following the layout decisions demonstrated by TI's own reference designs.
  3. Like
    spirilis reacted to Fred in CCS for $9.99   
    I had the opposite. Licence sent immediately but launchpad took 4 weeks to ship. If anything, it looks like CCS7 might not need a licence at all. That might explain why they're being given away so readily.
  4. Like
    spirilis got a reaction from jazz in My time with the Renesas RX   
    Update-
     
    After playing with C++ templates in e2studio and GNURX, I ended up tracking down a nasty bug in the compiler that turned out not to be a compiler bug, but rather, an idiotic set of defaults in the GNURX project generator's default linker script configuration.  Learned quite a bit with that wild goose chase...
    (Or as a coworker software developer told me, "It's every programmer's favorite pastime to blame the compiler!")
     
    e2studio (Eclipse) has a graphical interface for configuring the ld sections, and one option you can do per section category is "KEEP" .... in reality GNU ld linker scripts allow freeform use of KEEP() for individual sub-sections included within a section, but the Eclipse GUI-ified ld configuration tool only lets you apply KEEP to the whole section.  Looking at a genuine RedHat Newlib ldscript is helpful in figuring out what should be forcibly "kept".
     
    As it turns out, in order to use C++ properly with inheritance and virtual functions, the C++ compiler uses something called "Virtual Tables" to perform at-runtime indirection of function calls (so that a pointer of a parent class type pointing to a subclass's memory contents will correctly run the subclass version of a function, rather than the parent class's version of a function, without necessarily knowing what the subclass type is at compile-time).  This requires a few pieces of plumbing- the virtual table itself (often starting with _ZTV in the verbose mangled symbol name) and the init function that loads the correct vtable addresses into each static instance of a class, typically called _GLOBAL_sub_I_<objectname>.
     
    The _ZTV virtual table symbol and type information is typically part of the .rodata section, i.e. .rodata._ZTVMyTemplateASDF or whatever, whereas the _GLOBAL_sub_I_<objectname> is part of the .init_array section.  However neither of these are necessarily referenced explicitly from the C init runtime routines (the GLOBAL initializer has a pointer loaded inside the __init_array section), so the linker (with -Wl,--gc-sections) will gladly garbage-collect them from the binary*, resulting in C++ objects that aren't correctly initialized (VPTR's stored as a hidden class member in the bss-initialized space which is all 0x00's) and with the vtable being used to look up function addresses, the CPU will go off into lala land (PC branching to 0x00000000 at the beginning of SRAM) when you execute an overridden subclass function.
     
    * - Something about this explanation doesn't quite feel right, as I would imagine with the GLOBAL init function's pointer present in __init_array it shouldn't see any reason to garbage collect it, but this is what I've seen with the GNURX toolchain builds.  Perhaps the problem is that this array is only referenced via some ldscript-provided pointers during the C init runtime routines.
     
    To alleviate this, .init, .fini and .rodata should have KEEP() around their symbols (or certain ones of them in the case of .rodata but I just have the whole section wrapped in KEEP) to ensure they aren't garbage-collected.
     
    Strange quirk, you can tell not many Renesas customers use C++ since this was never caught before.  I recall a video of a Renesas DevCon talk doing a call of hands of who uses C++ .... maybe 1 hand in the crowd went up.  Wouldn't be shocked if they never bothered with virtual functions either.
     
    I happen to think these 32-bit chips are perfect for this kind of work, as I previously stated, so I'm all about fixing the bugs if they're not too heinous.
     
    So here's my current "checklist" on starting a C++ application with Renesas e2studio + KPIT GNURX:
     
    Open Project Preferences > C/C++ build
    1. Compiler Miscellaneous options - enable -fdata-sections and -ffunction-sections
    2. Compiler user-defined: Add -fno-exceptions and -fno-rtti
    3. Library Generator user-defined compiler settings: Add -fno-exceptions and -fno-rtti
    4. Include paths - add the src folder of the project itself so I can reference my .h files with <> and not just ""
    5. Linker Sections - for .init, .fini and .rodata, expand the "Advanced" section on the right side and check the KEEP option
      ** after doing this and hitting "Apply", go back into the project settings and make sure these actually got set; seen many projects misbehave b/c the setting didn't "stick" for some reason... maybe hitting "Ok" without hitting "Apply" inside the linker settings section isn't good enough
    6. Linker Miscellaneous - enable -Wl,--gc-sections
    7. Library Generator > Other Options - set Optimization type to "Code size optimization" (-Os) or whatever else
    8. Compiler > Object - set Optimization level to "Code size optimization" (-Os) or whatever else
  5. Like
    spirilis got a reaction from jazz in My time with the Renesas RX   
    Must be the fall weather (no, it's been hot), or maybe some gripes I've seen with TI's msp430-elf-gcc lately, but I'm taking a fresh look at the Renesas RX stuff.  First a sniff test...
     
    Current release of GNURX (v15.01-SP1) seemed to ship without libstdc++ for the no-fpu-libs variant of newlib, which is problematic for running C++ on any RX100 or RX200 series.  However, opening a ticket at kpitgnutools.com - they responded overnight that they reproduced the problem and a fix is forthcoming soon.  That's good to know the support is responsive for the free compiler.  The previous GNURX v14.03 release has libstdc++ in no-fpu-libs so I can compile with that for now.
     
    RX chips seem to be quite available at DigiKey, although prices are a bit high.  Avnetexpress has fewer chips in stock than I ever saw before, but that might simply mean that more customers use DigiKey now, as evidenced by the multitude of chips digikey actually have in stock.
     
    Renesas' e2studio IDE has come along, up to version 4 now.  No surprises there.
     
    Newer chips released since my last jaunt with the architecture include the RX100 series, now with 3 generations - RX110, RX111, RX113.  These would compete roughly with the MSP432 I guess (32-bit ULP 1.8-3.6V).
    RX200 seemed like an ugly duckling of the line but they do have an RX23T line for motor control... and the existing RX210 parts have newer generations (e.g. "revision C" vs "A").
     
    RX600 has a new RX64M which I don't know much about... and there's the newer RX700 with an "RXv2" arch which I know nothing about yet.  Parts look to be available but expensive for those newer parts.  Any MCU > $10 starts to bug me for some reason...
     
    For the RX210, there's a 0.65mm pitch 80-pin part available at digikey and orderable through avnet, the R5F52108CDFF which looks promising for large hobby type projects.  That's a non-FPU, 50MHz, 512K flash/64K SRAM part.  The nice thing about RX200 series is the 1.62-5.5V voltage range supported, so this can support 5V projects powered directly by a USB charger sans regulator, and work with 5V LCD hardware too.  OTOH, they don't include any CAN, which bugs me.  Only 1 SPI and 1 I2C port seems out of proportion relative to the pin count of the chip too.
     
    RX631 has a 48-pin LQFP part (R5F5631PCDFL $5.47 @ avnet no stock sans CAN, R5F5631PDDFL $8.44 in stock @ avnet with CAN) which is promising for non-battery powered (say, USB charger w/ regulator or buck) IoT type of crap.  RX63N is available with native Ethernet of course, but I suspect nowadays built-in Ethernet MAC isn't the bees knees as much; using smaller chips communicating with a WiFi transceiver over SPI or UART is in vogue.  Even using a smaller chip with a Wiznet W5500 or similar as an Ethernet co-processor would be easier to integrate from the software standpoint IMO than working out an install of lwip or uip or whatever into a 63N.
     
    Anyway, this is just a 1 day revisit for now... I am probably going to do more with my RX210 board soon for fun including porting a project I've called "AbstractWiring" over to it so I can use Arduino libs with the chip.  I think these RX chips, similar to ARM, are perfect for ambitious C++ based projects.
     
    Also very thankful I dumped all the information I did into this thread, and it's still around... useful info to have (e.g. the YRPBRX210 board schematics which I couldn't find at first)
  6. Like
    spirilis got a reaction from jazz in My time with the Renesas RX   
    Since I got the RX62N demo board mentioned in the other thread (viewtopic.php?f=33&t=3109) ... I decided it's time to do this shit. Get my feet wet and start the journey. (I also got the Stellaris LaunchPad, geez, too many complicated 32-bit toys to play with!!)
     
    Edit: Highly recommend RX newcomers hit up this document: http://renesasrulz.com/renesas_products/rx/m/mediagallery/140.aspx
    Very quickly gets you up to speed with some of the high-level concepts in the chip's hardware that you may bang your head against.  Further detail is found in the 2000-page Hardware User's Manual.
     
     

    I'm just going to dump my thoughts and processes in here so maybe RX n00bs can follow the footsteps (like a trained monkey) and get something out of it... or at least get their foot in the door.

    Ok, so first entry. What have I done so far-
    1. Installed HEW, SEGGER J-Link drivers from the CD. I don't have GNURX on my Windows netbook yet but the Renesas compiler still has 50 days left on its eval.
    2. Started HEW, created a new application project, no frills

    What it's provided me is a project with a crapton of pre-populated .c and .h files:


    TBH this confused me quite a bit at first, but I have an idea why it produces so many. Iodefine.h is basically your processor-specific I/O register manifest, like the and requisite msp430g2553.h, msp430fr5739.h, etc. that MSPGCC et al use. In Renesas HEW land, this .h file is included in your project.

    Most of the other .c files provide basic stuff that you might want to customize--intprg.c defines all the Interrupt Vectors, so when you want to change it you go in there, find the interrupt vector you want to change and toss your code in its place. Sounds like a lot of project "sugar" to me--to throw everything out there for professionals who want the rusty innards mapped out already in .c and .h files.

    The only one I care about right now though, is Test1.c, the designated home of main().

    The default Test1.c has some C++ #ifdef's for some reason but since I didn't care, I pared it all down to just this:

    /***********************************************************************/ /* */ /* FILE :Test1.c */ /* DATE :Sat, Sep 29, 2012 */ /* DESCRIPTION :Main Program */ /* CPU TYPE :RX62N */ /* */ /* This file is generated by Renesas Project Generator (Ver.4.53). */ /* NOTE:THIS IS A TYPICAL EXAMPLE. */ /* */ /***********************************************************************/ #include "iodefine.h" void main(void) { PORTD.DDR.BIT.B5 = 1; // PD5 = Output PORTD.DR.BIT.B5 = 0; // DR = Output register while(1) ; }

    Note that #include "iodefine.h" isn't put in there by default, you have to add that or else the PORT* SFR structs & unions won't exist and the compiler will throw an error.

    I wanted to light up an LED so I got the port ID by:
    1. Looking at the YRDKRX62N user manual, found by going Start->All Programs->Renesas->YRDKRX62N->User manual (at the bottom), in chapter 6 it talks about the "user circuitry" on the board, 6.3 explains the LEDs. I don't like how they don't tell you the I/O ports in there, just the "LED4", "LED5" etc. labels on the silkscreen, but they do explain that LED4 is MCU pin#81.
    2. Resolve MCU pin#81 to the requisite PORT -- open the RX62N series Hardware Manual, found in that same folder in the Start menu. Section 1.4 has the pinout for the 100-pin LQFP chip, which is what this board contains--pin 81 is PD5, aka PORTD5.

    From perusing some of that college textbook by Dr. James Conrad which uses this chip, I recall seeing that I/O ports are referenced with a struct of unions, e.g. PORTD.DR.BIT.B5 = 1 sets a single bit in the DR (output data) register, but PORTD.DR.BYTE = 0x20 would achieve the same thing (and set everything else in that port to 0). There's a PORTD.DDR, PORTD.DR, PORTD.PORT that we care about; DR is the output, PORT is the input, DDR sets the direction for the port.

    I'm guessing the LEDs on this board have their anodes connected to +Vcc and the cathodes connect to the RX62N processor, hence why setting the DR bit to "0" lights it up (I tried "1" first and that didn't work.)

    After plugging in the USB Mini cable to the SEGGER J-Link Lite onboard, go to Debug->Debug Sessions, set the Current session to the SEGGER one, tell it the right parameters (this is an RX62N processor, EXTAL is running at 12MHz btw; CPU runs at 96MHz, I think that's to maintain proper clocking for the USB host/OTG/device peripheral) and get it going.

    Be sure to "Connect" to the debugging session (check near the bottom of the Debug menu) if it's not already connected, then from the Build menu, select "Build All". This should compile everything--including doing a custom recompile of the standard C library to account for any user-configured changes like altered compiler optimization, Endianness (yes this CPU can run Little-Endian OR Big-Endian, it's your choice), etc. It'll finally give you the option to upload the code to the board, hit Yes, then once it's done, from the Debug menu hit Reset-Go.

    With the code I posted above, LED4 (in the motor-looking ring of LEDs on the demo board) lights up green near the top of the ring.

    Next task: Figure out the Timers, and get this baby blinking!
  7. Like
    spirilis reacted to jpnorair in CC13xx Application Integration Survey   
    Answering some of my own questions (for posterity):
     
    Turns out that all I need to do to port most TI-RTOS drivers to another OS is to provide an interface to five headers.  So that's good news for Energia-MT.
     
    Here's a link, describing more.  You can see the driver support matrix, but scroll down to the "Driver Ports" section to see the specific method for attacking a port job.  I tip my hat to TI, they did a nice thing, here.
    Drivers: TI-RTOS Full Driver API Reference
  8. Like
    spirilis reacted to jpnorair in CC13xx Application Integration Survey   
    Hey folks:
     
    I've been working on CC13xx for some time now, porting OpenTag and various other new stuff to it.  I'm not using TI-RTOS -- too clunky.  As usual (for those who know me), I've pushed the RF to the limit and it is shaping up to be a formidable LPWAN/LAN option.
     
    Anyway, I'm trying to decide how I want to enable 3rd party applications.  NuttX is one option, but someone (or I) will need to port that, too.  Energia/MT might be another option -- we'll still need to port that.  I'd be happy to take any information on this topic.  What would be best?
     
    1. Network processor with another MCU for application FW
    2. NuttX
    3. Energia-MT
    4. Something else
  9. Like
    spirilis reacted to Fred in Logic Analyzers   
    You'll find a use for it soon enough.
  10. Like
    spirilis reacted to carlb in NewHaven displays 15% off on OLED boards   
    Cheaper, but not nearly cheap enough IMO. All displays are around $30. The monochrome ones (all 2.x inch) are similar, and cost a little a bit less if they have a lower resolution mainly. Color versions are the same price but are much smaller (1.x inch instead of the 2.x inch).
     
    Meanwhile, you can get great LCD modules for dirt cheap. For example, a 3.5" 320x480 color LCD (ILI93xx chipset, with HC595's to use it via SPI) and a resistive touch panel (with generic XPT2046 touch controller, which also uses SPI), for which you can find plenty of example code all-around the web... $10 on ebay (dirt cheap because they're mass-produced and sold for the Raspberry Pi), in single quantity, with free shipping too. 
  11. Like
    spirilis reacted to Rickta59 in Basic MSP430 GPIO Macros   
    I think that is probably a gcc only optimization (forcing always_inline). I'm not sure if you can do that with the ti version.
     
    What I find interesting about discussions like this is that I'm often wrong about what feels true in my gut and what is actually true.  I'm sure I'm hampered by the fact I've been doing 'C' code now since 1982. I have a bag of personal biases that are often wrong with today's more capable compilers.  Lucky for all of you, optimization technology has come a long way since the days of the pdp 11
     
    -rick
  12. Like
    spirilis reacted to chicken in Basic MSP430 GPIO Macros   
    In my project, I use a few basic macros for GPIO. The goal is, that I can easily redefine pin assignment in a central location without compromising performance or code size.
     
    The macros (gpiomacros.h):
    // MSP430 gpio macros #define GPIO_SEL(port) P ## port ## SEL #define GPIO_DIR(port) P ## port ## DIR #define GPIO_OUT(port) P ## port ## OUT #define GPIO_IN(port) P ## port ## IN #define GPIO_IS_INPUT(port,pin) { GPIO_SEL(port) &= ~(pin); GPIO_DIR(port) &= ~(pin); } #define GPIO_IS_OUTPUT(port,pin) { GPIO_SEL(port) &= ~(pin); GPIO_DIR(port) |= (pin); } #define GPIO_IS_PERIPHERAL_IN(port,pin) { GPIO_SEL(port) |= (pin); GPIO_DIR(port) &= ~(pin); } #define GPIO_IS_PERIPHERAL_OUT(port,pin) { GPIO_SEL(port) |= (pin); GPIO_DIR(port) |= (pin); } #define GPIO_SET(port,pin) { GPIO_OUT(port) |= (pin); } #define GPIO_CLEAR(port,pin) { GPIO_OUT(port) &= ~(pin); } #define GPIO_READ(port,pin)  ( GPIO_IN(port) & (pin) ) In a central configuration file (e.g. hardware.h) I assign pins like this:
    // Pin assignment #define LED1_PIN BIT1 #define LED1_PORT 6 #define LED2_PIN BIT0 #define LED2_PORT 1 And then in the code I interact with GPIO like this:
    // Setup LEDs GPIO_IS_OUTPUT(LED1_PORT, LED1_PIN); GPIO_IS_OUTPUT(LED2_PORT, LED2_PIN); // Turn off LEDs GPIO_CLEAR(LED1_PORT, LED1_PIN); GPIO_CLEAR(LED2_PORT, LED2_PIN); The macros are resolved in two steps:
    1. Higher level "functions" define the commands. E.g. GPIO_SET(), GPIO_IS_OUTPUT(), ..
    2. Lower level macros used within those functions translate port, pin to a register. E.g. GPIO_IN(), GPIO_SEL(), ..
     
    The end result is code like you would write when directly working with the GPIO registers. E.g. P2OUT &= ~BIT0; Note that this translation is done by the C pre-processor before the code is compiled.
     
    This all works fine and dandy, with the exception of port J. Port J doesn't have a SEL register, which breaks the 1st half of the GPIO_IS_OUTPUT and GPIO_IS_INPUT macros. I currently work around this by adding special GPIO_IS_OUTPUT/INPUT_J macros, but then the main code needs to include some logic to invoke the proper macro.
    #if (LED2_PORT == J) GPIO_IS_OUTPUT_J(LED2_PORT, LED2_PIN); #else GPIO_IS_OUTPUT(LED2_PORT, LED2_PIN); #endif Any ideas, how I could include a condition inside macros, that checks whether the port is J, and if so excludes the GPIO_SEL command?
     
    And yes, I could probably use C++ templates with identical results and an easy workaround for port J, but I'd like to avoid migrating my plain old C project.
     
    Edit: Added a few missing parentheses, thanks to Rickta59 for spotting that
  13. Like
    spirilis reacted to dubnet in Logic Analyzers   
    Weighing in.... I purchased the 8 channel Saleae a while back when they offered the 43oh community a $25 discount. Didn't have a use for it at the time but since then it has saved me significant time and a lot of aggravation. The hardware is excellent but I feel the major strength is in their software. Overall, it is a superb product that I would highly recommend to anyone.

    However, the clones that leverage the Saleae software concern me. If everyone were to buy these clones then Saleae would likely go under or have to invest money in their hardware/software to block the hardware clone vendors. They would probably have to add crypto to the hardware which, in turn, would increase the cost of their product to all their customers.

    Perhaps I am in the minority anymore, but I don't buy knockoff hardware even though in the short term the lower pricing can be very attractive. In the long term I would be supporting companies that can take a product that has already been engineered by someone else, offer little to no support, typically use substandard components, and then sell it at a much lower cost. Adding to that I would be supporting the economies of countries that are potentially hostile to us.
     
    EDIT:  Should have read @@zeke 's post first as what I was surmising is real time reality:
     
     
     
  14. Like
    spirilis reacted to yyrkoon in Logic Analyzers   
  15. Like
    spirilis reacted to yyrkoon in Logic Analyzers   
    If I went by what I wanted, and not what I felt I needed. I'd actually probably build my own beaglelogic cape. Since you can't seem to buy them anywhere. They've apparently been tested, and made working with sigrok.
     
    @@spirilis Don't get me started on shop related stuff . . . heh. We've pretty much got everything. For everything. Our air tank for instance is 100gal . . . and you guys probably don't want me to go on. Car lift, wood shop, Machine shop, soon to be PCB fab . . .
  16. Like
    spirilis got a reaction from yyrkoon in Logic Analyzers   
    I am happy I used a couple opportunities (when I had more surplus cash than originally budgeted) to buy these kinds of tools... a Saleae Logic16 about 3yr ago, and a DS1054z this past July. Cause I hear @@yyrkoon 's dilemma, it's a pain to have the need for these tools while one is constrained on cash.
     
    Moral of the story: Sometimes it *does pay* to make seemingly frivolous investments in quality tools when you don't appear to need them. It's a gamble every time but certain tools are worth having. Like my 22gal air compressor in the garage, it's not strictly necessary for DIY car work but oh does it make certain situations palatable to deal with.
  17. Like
    spirilis got a reaction from yyrkoon in UART - Sending 3 bytes per start/stop bit sets.   
    yeah, I can imagine you don't need the timer for output, since the CPU can time its execution as needed based on interrupts or polling a timer and just manually flip the GPIO.
  18. Like
    spirilis got a reaction from yyrkoon in UART - Sending 3 bytes per start/stop bit sets.   
    yep-
    (Page 3, Device Pinout)

    See how (in the 20-pin variant) pin 9 says "P2.1/TA1.1" ... Timer_A1 CCR#1 is its alternate function (with P2SEL |= BIT1, P2SEL2 &= ~BIT1)
     
    Also P2DIR needs configuring (P2DIR &= ~BIT1) to make it an input (CCI):
    (page 51, Port 2 schematics)

  19. Like
    spirilis got a reaction from yyrkoon in UART - Sending 3 bytes per start/stop bit sets.   
    The idea is to have the RX pin just happen to be one of the pins with a Timer_A association capable of doing capture, preferably a TA0.1 or TA0.2 or TA1.1 or TA1.2 type of thing.  Not sure if it would work with TA0.0 or TA1.0.  Then you can use the timer to capture the moment of transition for that pin which should assist in detecting pulses.
     
    I've never written a software UART myself so I'm not sure what all is involved, but that one little piece I do know.  It might also be beneficial to have the TX pin going to another TA0.[1+] or TA1.[1+] pin too for output but I'm not 100% sure.
  20. Like
    spirilis got a reaction from Rei Vilo in My time with FreeRTOS on the TM4C   
    Loved the edX/UT Austin RTOS & Bluetooth course (mostly about RTOS, one token lab on bluetooth by dipping your toes into the TI NPI protocol for configuring a CC2650 running a special network processor firmware from afar, but not terribly deep into bluetooth or BLE itself)
     
    For the most part, RTOS's aren't rocket science (although I guess they are used in a lot of rockets), the main criticism I have is TI's TI-RTOS is a convoluted pain in the ass due to its superstructure being based on that "XDC" stuff which adds layer upon layer upon layer upon layer of crap.  Definitely over-engineered beyond comprehension.  Like anything though, you can live with it if you put enough time in...
     
    An RTOS at a high level involves several key features:
     
    1. Multiple managed stacks which delineate separate threads of execution (since registers are pushed onto the stack using native instructions, and return addresses also get stored on the stack, the stack is the essence of the logical concept of a "thread").  From here on "task" refers to a thread (which has its own stack and a Task Control Block (TCB) entry in the scheduler's linked list).
     
    2. The multiple tasks are switched between in a preemptive manner, not cooperative--cooperative multitasking is possible of course but does not support the "real time" nature of a system, i.e. it does not support guaranteed minimum latency & jitter constraints for specific operations--this preemptive task switching typically involves a timer but can also involve innate operations, e.g. "posting" a semaphore is an event that might make a real-time constrained task eligible for execution thus it should run code that checks whether the scheduler should be executed to preempt the current task which posted the semaphore.  Generally hardware interrupts of some type drive the context switch, that is, the act of "halting" the current thread and finding another thread to execute.
     
    3. OS-managed semaphores, the exact data structure is not necessarily provided by the OS but there must be a "post" and "pend" function where, at some point, an attempt to "pend" on a semaphore puts the task doing the pending into a blocked state.  The edX RTOS course had an "OS_Signal" (post) and "OS_Wait" (pend) function which took a pointer to an int32_t, any time the semaphore value went negative, the current task was blocked (in its Task Control Block, we had a field "blocked" which was a pointer to the exact int32_t semaphore that blocked us).  When OS_Signal was run from another running task, if the semaphore became <=0 after incrementing it, a code routine would check all the Task Control Blocks to see if anyone was pending on it, and if so, unblock it & perform a context switch.  Only 1 would be unblocked for any 1 run of OS_Signal, and it was first-come first serve.  There are probably other considerations that needed to be made here.
     
    4. Priority system for tasks.  Real-time constraints necessarily requires that certain tasks have precedence over others, such that a scheduler can make a simple and deterministic decision to execute a real-time task exactly when it becomes eligible for execution, to the exclusion of lower-priority tasks without any ambiguity.  A common idiom is that a hardware interrupt might either handle some of the real-time execution itself (interrupts are, in a sense, impromptu "tasks" borrowing the current stack temporarily) but usually it just posts a semaphore that the real-time handler task is waiting on; after the interrupt completes the context switch will be forced right away, ensuring the high-priority now-eligible-for-execution real time task is switched to without any intermission by the previous task that was running before the interrupt occurred.
     
    5. A "softer" but typical requirement is that tasks must be able to sleep, that is, become ineligible for execution for some time.  This sleep operation causes immediate preemption (context switch) with a timer in the system maintaining the countdown for each sleeping thread and making it eligible for execution when a sleeping thread's timer reaches 0.  The alternative to such a managed sleep is to busy-wait until the timeslice finishes; this may be satisfactory but it's fundamentally a waste of CPU resources.
     
    Beyond this, an RTOS may provide other facilities as needed e.g. File systems, Network drivers, coherent date & time with timezone interpretation, logging, whatever.  The basic RTOS task concept provides a neat platform for assembling more complex software layers and since the semaphore system is used to synchronize tasks in an ad-hoc manner, a variety of complex communication methods can arise e.g. managed FIFO ring buffers, mailboxes & queues, etc.  It's important to logically separate the "core RTOS" features from the "extras and/or fluff" that any particular RTOS solution offers.  FreeRTOS for the most part is a barebones RTOS without the fluff, so that you may implement the fluff from scratch in a manner appropriate to your specific platform.  Obviously there are pros & cons with that approach.
     
    An interesting idiom we learned in the edX course is the concept of circular DSP signal buffers.  This is a type of ring buffer where the "head" pointer location is only updated by the producer, e.g. the hardware interrupt collecting ADC data or whatever, and the whole buffer is read by any other tasks as needed.  Sort've a dynamic write-once, read-many concept where the buffer is read in its entirety each time it's "consumed"--as would be the case with many DSP algorithms (FIR, IIR filters et al).  DSP-optimized processors typically include hardware supported circular buffers to make the addressing within these extremely simple, otherwise a number of CPU cycles are expended every time the circular buffer is written to which can affect the amount of CPU time available to process the data.
     
    Anyway, lots more to talk about, for now I am diving into CC1310 work to get a personal star network IoT system up and running (now that I have 5 end nodes built + a Raspberry Pi CC1310 hat), but eventually I'd like to tinker with some more FreeRTOS examples for the purpose of this thread.
  21. Like
    spirilis got a reaction from Fmilburn in My time with FreeRTOS on the TM4C   
    As an addendum, I suspect the MSP430's interrupt features such as the ability to determine return LPM status (__bic_SR_register_on_exit()) and its small size firmly plants the MSP430 in the realm of that which doesn't need an RTOS and where an RTOS is probably not desirable.  Its small size and specific feature sets make it optimal for simpler systems where "real time constraints" are enforced either by peripheral features or by individual interrupts, and the main execution thread is the lowest-priority "idle" task.  The use of volatile variable flags (semaphores if you will) to synchronize features inside your main execution thread can be used to run background post-processing operations off a while() loop inside your main(), after which an LPM mode is entered to save power.
  22. Like
    spirilis got a reaction from Fmilburn in My time with FreeRTOS on the TM4C   
    Loved the edX/UT Austin RTOS & Bluetooth course (mostly about RTOS, one token lab on bluetooth by dipping your toes into the TI NPI protocol for configuring a CC2650 running a special network processor firmware from afar, but not terribly deep into bluetooth or BLE itself)
     
    For the most part, RTOS's aren't rocket science (although I guess they are used in a lot of rockets), the main criticism I have is TI's TI-RTOS is a convoluted pain in the ass due to its superstructure being based on that "XDC" stuff which adds layer upon layer upon layer upon layer of crap.  Definitely over-engineered beyond comprehension.  Like anything though, you can live with it if you put enough time in...
     
    An RTOS at a high level involves several key features:
     
    1. Multiple managed stacks which delineate separate threads of execution (since registers are pushed onto the stack using native instructions, and return addresses also get stored on the stack, the stack is the essence of the logical concept of a "thread").  From here on "task" refers to a thread (which has its own stack and a Task Control Block (TCB) entry in the scheduler's linked list).
     
    2. The multiple tasks are switched between in a preemptive manner, not cooperative--cooperative multitasking is possible of course but does not support the "real time" nature of a system, i.e. it does not support guaranteed minimum latency & jitter constraints for specific operations--this preemptive task switching typically involves a timer but can also involve innate operations, e.g. "posting" a semaphore is an event that might make a real-time constrained task eligible for execution thus it should run code that checks whether the scheduler should be executed to preempt the current task which posted the semaphore.  Generally hardware interrupts of some type drive the context switch, that is, the act of "halting" the current thread and finding another thread to execute.
     
    3. OS-managed semaphores, the exact data structure is not necessarily provided by the OS but there must be a "post" and "pend" function where, at some point, an attempt to "pend" on a semaphore puts the task doing the pending into a blocked state.  The edX RTOS course had an "OS_Signal" (post) and "OS_Wait" (pend) function which took a pointer to an int32_t, any time the semaphore value went negative, the current task was blocked (in its Task Control Block, we had a field "blocked" which was a pointer to the exact int32_t semaphore that blocked us).  When OS_Signal was run from another running task, if the semaphore became <=0 after incrementing it, a code routine would check all the Task Control Blocks to see if anyone was pending on it, and if so, unblock it & perform a context switch.  Only 1 would be unblocked for any 1 run of OS_Signal, and it was first-come first serve.  There are probably other considerations that needed to be made here.
     
    4. Priority system for tasks.  Real-time constraints necessarily requires that certain tasks have precedence over others, such that a scheduler can make a simple and deterministic decision to execute a real-time task exactly when it becomes eligible for execution, to the exclusion of lower-priority tasks without any ambiguity.  A common idiom is that a hardware interrupt might either handle some of the real-time execution itself (interrupts are, in a sense, impromptu "tasks" borrowing the current stack temporarily) but usually it just posts a semaphore that the real-time handler task is waiting on; after the interrupt completes the context switch will be forced right away, ensuring the high-priority now-eligible-for-execution real time task is switched to without any intermission by the previous task that was running before the interrupt occurred.
     
    5. A "softer" but typical requirement is that tasks must be able to sleep, that is, become ineligible for execution for some time.  This sleep operation causes immediate preemption (context switch) with a timer in the system maintaining the countdown for each sleeping thread and making it eligible for execution when a sleeping thread's timer reaches 0.  The alternative to such a managed sleep is to busy-wait until the timeslice finishes; this may be satisfactory but it's fundamentally a waste of CPU resources.
     
    Beyond this, an RTOS may provide other facilities as needed e.g. File systems, Network drivers, coherent date & time with timezone interpretation, logging, whatever.  The basic RTOS task concept provides a neat platform for assembling more complex software layers and since the semaphore system is used to synchronize tasks in an ad-hoc manner, a variety of complex communication methods can arise e.g. managed FIFO ring buffers, mailboxes & queues, etc.  It's important to logically separate the "core RTOS" features from the "extras and/or fluff" that any particular RTOS solution offers.  FreeRTOS for the most part is a barebones RTOS without the fluff, so that you may implement the fluff from scratch in a manner appropriate to your specific platform.  Obviously there are pros & cons with that approach.
     
    An interesting idiom we learned in the edX course is the concept of circular DSP signal buffers.  This is a type of ring buffer where the "head" pointer location is only updated by the producer, e.g. the hardware interrupt collecting ADC data or whatever, and the whole buffer is read by any other tasks as needed.  Sort've a dynamic write-once, read-many concept where the buffer is read in its entirety each time it's "consumed"--as would be the case with many DSP algorithms (FIR, IIR filters et al).  DSP-optimized processors typically include hardware supported circular buffers to make the addressing within these extremely simple, otherwise a number of CPU cycles are expended every time the circular buffer is written to which can affect the amount of CPU time available to process the data.
     
    Anyway, lots more to talk about, for now I am diving into CC1310 work to get a personal star network IoT system up and running (now that I have 5 end nodes built + a Raspberry Pi CC1310 hat), but eventually I'd like to tinker with some more FreeRTOS examples for the purpose of this thread.
  23. Like
    spirilis reacted to zeke in Questions on SFP transceivers in hobbyist projects.   
    Oh!  
     
    <fires up Altium>
     
    I guess that means that there's a chance that I could beat you to the punch then!
     
    ;-)
  24. Like
    spirilis reacted to yyrkoon in UART - Sending 3 bytes per start/stop bit sets.   
    Another thing I found rather comical today when talking to a person I know.
     
    Him: "What do you mean you can't bit-bang gpio serial from Linux user space? . . ."
     
    To which I mentioned that the lowest guaranteed latency of any API call under Linux is not very deterministic at all. At best, we're talking 10's of milliseconds using an RT enabled kernel. Worse case it can be as high as 100's of milliseconds.
     
    He then pulls up the ominous google search page . . .
    Him: "Well, you obviously do not know what you're talking about, because here is a guy doing exactly that on an rPI using Python . . ."
     
    At which point I had to leave the conversation. As any programmer knows that first, bit-banging *anything* is going to be CPU intensive by comparison. Then the more CPU you're using, the less deterministic your code will end up being. Passed that . . . Python ? Really ?! We're talking about a serial interface that needs to be at least reasonably deterministic. At least to the point where you're able fulfill your baud rate, and then act on that data. Python for a couple of reasons is not up to that task. First, while Python *could* potentially be compiled into native code . . . Python is an interpreted language. It's going to be comparatively a lot slower than C, depending on the task, it'll use a lot more CPU doing so, and while being huge, again in comparison. Lastly, as far as scripting language performance goes . . . Python often is the worst. Even Javascript( googles V8 engine / Nodejs ) routinely gives it a beating performance wise. That, and I do not even consider Javascript / Nodejs very performant. Often times, it is fast enough, but I'd honestly never consider using it for driver code . . .
     
    Granted there are a few caveats of course. Using mmap() along with /dev/mem could potentially speed things up greatly. But you're still going to be using CPU cycles to get where you want. Also while writing such an app, you'd have to be very careful which system calls you made. Something such as a single printf() call, could cripple the application. Cutting performance drastically. Threading, and Semaphores would also be out of the question. Especially on a single CPU core system such as the beaglebone black.
     
    In my own case, I won't be just fulfilling my baud rate expectation with enough leg room to act on that data. There will be a multi GPIO, PWM, and MQTT system in place. That is, in addition to the "bit-bang" serial code. If, in fact I have to truly bit-bang serial at all. Using SPIDev for this purpose looks promising, thanks Rick ! Not to mention I always have a couple of PRU's to fallback on, for which they were built specifically for this sort of situation. Bit-banging. . .
     
    The moral of my story here ? Simply that just because something *may* be possible. It does not mean that this *something* is a good idea.
  25. Like
    spirilis reacted to USWaterRockets in UART - Sending 3 bytes per start/stop bit sets.   
    Why don't you just set up a timer interrupt and implement the fancy 16/24 bit UART using software running in the interrupt?
     
    If you're using 1200baud, that's 1 bit every 833uS. On a MSP430 running at 8MHz, that's one interrupt every 6000 clock cycles (8000000/1200 = 6000). If your interrupt routine takes an average of 100 cycles to complete, you're using 1.5% of the CPU cycles for the UART (((1200 * 100) / 1000) = 0.015).
     
    Recall that the original MSP430 LaunchPad shipped with the MSP430G2231 which does not have a hardware UART peripheral, so all the serial port examples for it were using a bit bang driver. It should be very trivial to look through the existing examples for software UARTs for the LaunchPad and find one you like that you should then be able to modify the bit counter to send 16 or 24 bits instead of 8.
×
×
  • Create New...