1 2 3 Previous Next

Embedded

227 posts

Get to know the Embedded Developer...

This is a monthly series featuring embedded developers of the ARM Connected Community.


Jens Bauer.png


Name: jensbauer

Company: GPIO

Job Title: Design Engineer

Location: Herning, Denmark

 

Developer History

Before GPIO, I've been working for a number of different companies where I've soldered PCBs using reflow, wave and hand-soldering (both SMT and leaded boards) - plus I've assembled high-end audio equipment. I've been a software developer since 1983, and have programmed several different kinds of microprocessors and microcontrollers. With GPIO, I mainly design and lay out PCBs, prototype them, test and revise them - on occasion I find myself writing some software and firmware too.

 

How did this all start?

I believe it was the Sinclair ZX Spectrum that caught my attention. I still have it on my desk, right next to me, and it's still in use.

 

First Project

Well, I guess the first design I did for GPIO is the mini game-console, which is capable of running Boulder Dash on a VGA screen. This project was meant as a tutorial for those who want to learn how to make a microcontroller show information on a standard monitor.

 

What is your best product?

I'm afraid it's a product which is not released yet, and unfortunately I can't say much about it. However, it's ARM-based, and it's for developers - but until then, the best product will probably be the breadboard JTAG-module. It's a very simple space-saving adapter that allows the developer to connect a JTAG programming/debug-adapter to a device on the breadboard. The adapter takes care of pull-up and pull-down resistors, so the developer can focus on the fun stuff, and it can also be used with SWD.

 

Can you talk about any current projects?

A couple of products will be using ARM-based microcontrollers from NXP. Those two products are the major products GPIO will release in the near future. Other products include tools for developers (engineers and hobbyists alike), such as simple space-saving adapters that makes it easier for the developer to quickly wire up a solderless breadboard.

 

What is your motto ?

It's all about making the right connections, whether circuits, business or people.

 

Favorite New Tool

OpenOCD 0.8.0 and JTAG-lock-pick Tiny 2, definitely and both highly recommended tools. Apart from that, I've just ordered a Logic Analyzer, which I expect I will spend some quality-time with.

 

Favorite Gadget

You'd probably expect me to say "my cell phone". Well no, I don't have a cell phone, nor do I have a tablet. Is a solderless breadboard a gadget? Well, it is probably a small OLED display I bought from buy-display.com; they're quite impressive and works well with a LPC microcontroller.

 

Most Useful Resource

ARM's Infocenter for getting information on the Cortex-M instruction set and clock-cycles. The ARM Connected Community, LPCware.com and then Texas Instruments for anything top-notch finesse. Then of course, Datasheets and User's Manuals as PDF files downloaded locally, so if the net is down, they're still reachable.

 

Best Tips for a Beginner Developer

Buy low-cost stuff! If it doesn't work, you didn't lose more than a few pennies. If it works, you'll be grateful for what it can do even though it didn't cost much. For programming, don't rush things, be thorough in writing your code. Make it your object (goal) to find bugs and errors in your code, not to implement new features. Read your code more than once, hunt for bugs, even where it seems there are none. Use precision when you code.

 

For PCB-layout, know one thing, you will always have at least one error on your first version of a PCB after submission, no matter how many times you've re-checked - but check your PCBs, first on-screen by following each trace, one-by-one and don't cheat. It takes a long time, but it's worth it. Check your hole sizes - are they big enough for the leaded components? Print out your PCB 1:1 and place components on the paper, and check each component type. Yes, these are basics, but they're more important than any other advice I can give. Also assume you will need to modify your PCB. Make extra pin holes and exposed vias, so in an emergency, you can solder some straps or green-wire the board. Make breakable connections in areas you're not completely sure and also make some room for zero-ohm resistors. If possible, make a few options for each PCB and make your boards universal.

 

Which PCB Manufacturer do you use?

JACO. I recommend them, especially for low volumes - they offer good service, at low prices and high quality.

 

Future of Expertise

I will be looking into Cortex-A after the Cortex-M products have been launched. Most likely, this will be Cortex-A9 and perhaps a couple of faster models as well.

 

Something About Yourself That Many Don’t Know…

I've caused a few major changes just by telling large companies what I think they should do. A couple of examples: I caused a large company to manufacture computers in more than one colour. They also adopted a glass-like user-interface, which I suggested them. Years later, I became the reason their logo is no longer upside down - but, all the thanks go to Mr. Gilbert and Steven Glass who took the time to listen.

 

A while back, I pushed Opera Software into making a Mac version as their previous Mac-team gave up. So I told them, "well, I want that browser, no matter if I have to make it myself." After having pushed Opera Software into this, I had to pull a fellow with me to Norway and we worked there for three and a half years - this was in 1997/1998. When MacOpera started to become a usable browser, I had to leave the company. Easter eggs in Opera were strictly prohibited and I managed to sneak a Space-Invaders game into the browser. The code used less than 1KB memory and was written in C - even my fellow programmer didn't see what I did, until more than a year had passed.

 

 

Previously Featured Embedded Developers

Embedded Developer Feature: Paul Beckmann, Founder of DSP Concepts

Embedded Developer Feature: James Langbridge, Author of Professional Embedded ARM Development

Embedded Developer Feature: Colin Walls, Embedded Software Technologist at Mentor Graphics

Embedded Developer Feature: Jacob Beningo, Certified Software Development Professional

PatternAgents has just released a OSHW JTAG Adapter for the STM32 Discovery development boards, which allows the internal ST-LINK/V2 USB to JTAG on these boards to be used to hack and program other devices easily. It supports both the standard 20 pin JTAG cables as well as the smaller 10 Pin JTAG cables.

 

http://www.patternagents.com/projects/JTAG20M-STLV2F.html

 

JTAG20M-STLV2F_DiscM0_Cable10.png

 

JTAG20M-STLV2F_DiscM0_Cable20.png

 

They have also released a "mini" version which just supports just the smaller 10 Pin JTAG cables.

http://www.patternagents.com/projects/JTAG10M-STLV2F.html

 

If your JTAG programmer has only the smaller 10 Pin JTAG cables, and you need the larger 20 Pin cable version, they have an adapter for that also.

http://www.patternagents.com/projects/JTAG20F-JTAG10M.html

 

You can download the gerber files from the PatternAgents Github repo and order your own PCB boards from OSHPark .

 

Happy Hacking from PatternAgents!

 

best regards,

Tom Moxon

@PatternAgents

As microcontrollers and microcontroller systems like Arduino enable so many projects, "leveling up" to an ARM board can be very beneficial for new ideas. When the task is to interact with many different hardware, a SoC can enable very quick prototyping almost Arduino style in a new area.

 

I'm very new at VIA, and coming from the Taipei Hackerspace, I wanted to do a project for our Maker Clup to check our hardware, the Springboard, and hopefully earn some maker credit too.

 

From a Springboard, webcam, screen, keyboard, and a thermal printer, I've put together a Thermal Printer Photobooth (nicknamed MonoBooth = monochrome + photobooth).

monobooth1.jpg

It was a half-day project, most of the time spent troubleshooting the communication with the thermal printer. Hopefully I can improve on that with time, drawing on the expertise of our engineers in the Maker Club. In the end got it working, with a very interface on Debian Linux, running PyGame for the webcam control.

monobooth3.jpg

It's probably the geekiest photoprint I've ever had:

monobooth4.jpg

Probably should make a box for it, and hang up an "Available for (geeky) parties" sign.

 

I'm really looking forward to making more projects on single board computer, Springboard is already a lot of fun! Compared to using a desktop for a project like this, or even a laptop, there are a lot of cables, but the total amount of "stuff" a setup needs can be so much less.

 

The detailed writeup of the photobooth is on the VIA Springboard blog, where all the future maker projects will be as well.

A standard job interview. We've been through all the little details; yes, I'm British, I live in France, I like digital photography and here is a list of previous clients with recommendations. Then he asks the question, "Are you an ARM Accredited Engineer?". No, I'm not. Up until now, not many people have actually asked me for that. I'll admit, I didn't take the time to take the exam, but I did write a book on ARM processors. "But that doesn't mean you are an ARM Accredited Engineer". No, indeed, but forgive my insistence, I wrote a book on ARM processors, I had the honour of having one of ARM's well known trainers re-read the book (and correct some mistakes), and it is listed on ARM's website. "Yes, but still, that doesn't guarantee that you know ARM processors and microcontrollers". I think my jaw dropped at that point.

This just goes to show how vital the accreditation program is. The client refused to accept my credentials, and preferred something put in place by the ARM team; a certification. A piece of paper, signed at the bottom, saying yes, this person knows what he is talking about. It doesn't matter what I wrote, and it doesn't matter what I did. There again, he does have a point, sort of. In a strange way, I actually preferred his answer. Oh well, I wrote the book, now it is time to take the exam, I suppose. Has anyone had a similar experience?

MetaWear - Production Ready Wearables in 30 Minutes or Less! by MbientLab Inc.


front.png


MetaWear solves the unique problems faced by entrepreneurs, engineers, and designers working on wearable devices.  It includes a diverse set of sensors enabling a broad application space, in a form factor fit for wearing.  An ARM+BLE System on Chip delivers smartphone connectivity and application functionality with world class efficiency.  Unlike traditional development boards, MetaWear is cost, form, and feature optimized for production, allowing developers to seamlessly migrate from prototype to user trials to production.  A set of rich mobile APIs and example apps encapsulates hardware functionality for software minded engineers, reducing the time, cost, and skill sets required for development.


The MetaWear board is tiny, measuring in at 26mm x 17mm.  It is the perfect size for a wearable pendant, motion tracker, or haptic feedback device.  It is compatible with miniature Lithium chemistry batteries, and includes charge circuitry and a micro USB port for charging.  The boards will ship with a tiny battery made cheap by mass market traditional bluetooth headsets.  However, unlike bluetooth headsets, the combination of an ARM Cortex-M0 core and Bluetooth LE enable multi-week and even multi-month battery life depending on the application.

 

A major problem for designers and early stage companies is getting from the initial idea to a first prototype.  For a wearable product, a custom circuit board is often required due to the size constraints, which can take months of development time.  With MetaWear, development can skip straight to mechanical and industrial design.  Leveraging the mobile APIs, software developers can begin app development and integration immediately.  When a market and customers are found, MetaWear can be sourced at production volume, and integrated into the end product.  MbientLab provides design and certification support for companies ready to go into production.


The ARM core in MetaWear delivers best in class energy performance among BLE SoC designs.  The vibrant development community and well designed toolchain means better products can be developed faster.  ARM delivers true competitive advantage to its developers.


metawearcircuits.png


Hardware Features

  • Nordic BLE SoC with ARM Cortex-M0
  • 256KB Flash and 8KB RAM.
  • Bluetooth Low Energy stack and MetaWear Firmware pre-loaded
  • Micro USB rechargeable Lithium Ion battery
  • 2 analog/digital I/O pins and I2C for extensions
  • 3-axis Accelerometer
  • Ultra Bright RGB LED
  • Coin Vibrator Motor
  • 4KHz Buzzer
  • High Current MOSFET Driver (mutually exclusive with vibrator)
  • Temperature Sensor
  • Micro push-button

 

Firmware Features

  • Android and iOS sample MetaWear App to get started
  • Documentation on Github
  • Simple API calls to control peripherals and sensors
  • Programmable LED Light Sequences
  • Programmable Vibration Sequences
  • Accelerometer Event Callbacks (Freefall, Tapping, Threshold Detection, Orientation)
  • Push Button Callbacks to Trigger App Events
  • Wireless Firmware Updates (OTA)
  • ANCS Stack (Apple Notifications)
  • Power Optimized for Long Battery Life


MetaWear is the ultimate platform for wearables, made possible by ARM.


I recently presented a session at EE Live! on USB 3.0, which proved quite popular. There were a number of questions and discussion about what is wrong with USB [mainly the connectors] and where it is going in the future. Of course, the question of USB 3.1 came up …

My class included very little information on USB 3.1 because the standard is not yet finalized. It is slated for late 2014 and there is enough industry/user pressure for me to believe that this schedule will work. However, in this more informal context, I am happy to chat [and speculate] about USB 3.1...

To read the rest of this entry, visit the Colin Walls blog on Mentor Embedded.

USB3.1.jpg

There are many topics in the C language that often confuse developers but the use of the static keyword seems to be one of the more common.  One of the points of confusion is how static affects variables that are local and variables that are global.  In each instance the static keyword has a different effect on where the data is stored and how it persists throughout the life of the program.  There are three primary uses for the static keyword; local variable in a function, global variable in a module and a function in a module.  In this post we will examine all three uses and how they affect not only where variables are stored but also the use of static can increase code quality. 

 

In general, static is a storage class specifier that can be applied to any data type.  While static has many definitions, the definition that best applies to all three uses is that static tells the compiler to make the variable or function limited in scope while allowing it to persist throughout the life of the program.  This allows static to be used to encapsulate or hide variables from the rest of the program to prevent inadvertent access. The developer is then able to strictly control how variables are accessed within a module which is considered good programming practice.

 

When a variable is declared within a function without the use of static, the variable is considered to be an automatic variable.  Automatic variables are created and stored on the stack (or within a CPU register) and destroyed when the function returns.  If a developer wanted the variable within the function to retain its value between calls, the variable would be declared as static.  In this case, the variable would no longer be stored on the stack but would instead be stored in the global memory space; however, even though the variable itself is stored in global space the compiler enforces a local scope on the variable causing it to only be visible within that function!  Other functions within the module will be unaware that the variable exists.  Not only will the variable retain its value throughout the life of the program, the static variable will also only be initialized the first time the function is called. 

 

Defining a variable within the global scope of a module (but not global within the context of the entire program) implicitly declares the variable to be static.  This causes the variable to be defined within the global memory space while enforcing the concept of limiting the scope of the variable to the module.  It’s always a good idea to explicitly declare these variables as static to remind yourself that they have a module scope and are not automatic variables.  Good programming practice indicates that a variable should be declared within the most local, applicable scope.  Therefore, if the variable is only used within a single function then the more appropriate location to declare the variable may be within the function itself rather than the module scope.  Static variables declared at the module level are initialized only once during the C copy down that occurs when the processor is being initialized.

 

Static can also be applied to a function within a module.  By default, functions are implicitly declared as extern. This means that if a function is defined within a c file and not prototyped within a header file, the compiler will still be able to link to the function (with perhaps a few warnings to the developer).  In order to only make a function usable within a single module, the developer can place the static keyword before the function declaration.  This will effectively hide the function from the external world and protect the use of that function and its variables. 

 

The use of the static keyword has many uses.  Its most effective use is to limit the scope of variables defined within a module or function.  Through the use of static, variables and functions can be hidden from the external program, resulting in behavior that is similar to the use of private and public in more modern object oriented languages.

A recently-discovered bug in OpenSSL’s implementation of the TLS Heartbeat Extension makes it possible for malicious attackers to potentially recover the private keys and sensitive data that should normally be secured by SSL/TLS. The vulnerability has been recorded as CVE-2014-0160.

 

The purpose of this note is not to gloat over a competing projects problems, as some others have done, but rather to inform our user base.  The OpenSSL team and their supporters have done a good job on getting the bug fixed as well as informing their users.  We want to be the first to note that secure coding is not for the faint of heart, because it is a specialized expertise.  Building cryptography and the protocols on top of it is a difficult expertise to practice.

 

We want to assure our users and customers that CyaSSL and wolfSSL products are NOT affected by the Heartbleed bug in any way.  We are a clean room implementation of SSL/TLS, and did not employ any of OpenSSL's code base, which many others have done.  We should also note that the bug is not a protocol level bug that effects all SSL/TLS implementations. This was a bug specific to OpenSSL’s implementation of the TLS Heartbeat Extension.  This bug existed in OpenSSL for over two years, with vulnerable versions including OpenSSL 1.0.1 - 1.0.1f (inclusive).

 

Interested parties can learn more about this bug in OpenSSL at the following links:

 

http://heartbleed.com/

https://www.openssl.org/news/secadv_20140407.txt

CVE -CVE-2014-0160

 

For additional information or questions about CyaSSL, please contact wolfSSL at info@wolfssl.com.

chrisconlon

CyaSSL 2.9.4 Released

Posted by chrisconlon Apr 10, 2014

wolfSSL has released CyaSSL 2.9.4, which is now available for public download. Release 2.9.4 includes important Security Fixes for issues found by Ivan Fratric of the Google Security Team and Suman Jana with security researchers at UT Austin and UC Davis.  CVE details to be posted today for issues with memory corruption, null pointer deference, out of bound read, and unknown certificate extensions.  All users should upgrade immediately.

 

This release also includes sniffer fixes for corrupted Jumbo Frames, ARM thumb mode assembly fixes, XCode 5.1 support, PIC32 MZ hardware support, a sample I/O pool, and FIPS mode for algorithms including AES, 3DES, SHA-1, SHA-2, HMAC, and RSA.


CyaSSL 2.9.4 can be downloaded from the wolfSSL download page.

colinwalls

How was EE Live! for you?

Posted by colinwalls Apr 9, 2014

As I mentioned last week, I have just been to EE Live! in San Jose, California. Having arrived home a little while ago – 22 hours door to door, with baggage taking a little longer – I am pondering my impressions of this year’s event …

Starting off with the positives. What I saw of the conference was buzzing. There were lots of classes available, covering all aspects of embedded development. My 2 sessions were well attended and seemed to be well received with plenty of questions and comments. I also spent some time on our booth in the trade show. The vast majority of visitors, with whom I spoke, were very relevant to our business area – not the kind of event where I have to continually explain what an embedded system is all about!

Notwithstanding the vibrancy of the conference, the trade show had contracted again...

To read the rest of this blog, visit the Colin Walls blog on Mentor Embedded

EELive.jpg

For 3 years, my Mac has been very, very, very (and I mean very, very, very) sluggish.

Typing on the keyboard would give me approximately 1 character per second.

Sometimes I even had to resort to using my laptop, because it was so painfully slow.

 

This changed recently. Not by changing to a different computer, not by re-installing the operating system (which I tried a few times, but it did not help).

-But why did it happen then ?

Well, it all started a few days ago, my ISP shut down my internet connection for maintenance. My Mac froze completely, because I had mounted a network drive, and it suddenly disappeared while I had documents open.

I could not open my programming IDE, because it remembers what files i had open in the project last time, and it kept trying to open those files that were not accessible.

After having my internet connection back a few hours later, I decided to look at my DNS setup in my D-Link DIR-655 router.

So I thought: "Something is called 'Advanced DNS', it's disabled, might be a good idea to set up some local DNS; how do I enable it ?"

I started searching for "DIR 655 Advanced DNS" and after reading about it a little, I decided that it might not be just yet.

But I did notice that D-Link had a firmware upgrade available for my router.

 

I decided to upgrade my firmware, because the changelog said something about a "DNS fix".

 

After doing so, my PowerMac has been running like if it was brand new.

 

So this is a practical example on why it is a good idea to use an ARM based microcontroller in a device, for instance a router:

 

If there is an error, you can fix it and provide firmware upgrades easily.

Of course, it's possible with other microcontrollers as well, but if you use ARM, it's even easier, because there are plenty of different MCU vendors, thus there are plenty of example-code, because each vendor provides example code for how to do things, and there's usually at least one Linux distribution available for each Cortex-A (sometimes also for Cortex-M) MCU out there.

And since there are so many Linux distributions available, there are solutions available for most problems that have been through the times.

 

Firmware upgrade saves you money, because you don't have to have 200 people working in your support department, in order to service your customers. The customers nowadays often have internet and can download firmware upgrades and upgrade their products themselves, and it can be done safely, without the fear of the device never working again, if it was turned off during an upgrade.

There has been a lot of hype and buzz around network function virtualization (NFV) and software-defined networking (SDN), and I must admit that it can be a bit confusing; especially if you take your eye off the communications market for a second because this space is evolving that rapidly!

 

To this point, Freescale just announced their new ARM® Cortex®-A57-based QorIQ LS2 family of devices targeting virtualized networking with an architectural approach that addresses this dynamic communications environment.

 

If you are wondering what virtualized networking is all about, then consider a world where all that your customers want to buy is a commodity item! Innovation around SDN and NFV is all about that concept; making networking equipment appear as a general-purpose and interchangeable appliance. Without a doubt, this solves some very real and interesting technical and business problems at the network system level. However, there is still an expectation that competitive SDN and NFV capable devices will deliver unique features and best-in-class performance with power efficiency.

 

How do you deal with commoditization versus differentiation, and how do you make a product meet the demands of an industry-wide strategy whilst remaining competitive?

 

Of course you’ll need software programmability, and ARM’s technology is at the heart of this trend with the ARM Cortex-A57 processor designed for compute intensive 64-bit applications – but you will also need significant innovation at the SoC level. For instance, what datapath functions do you accelerate; what are the required I/O and memory configurations; what is the right arrangement and interconnect of processors; and what about system visibility and the correct abstraction?

 

It is ARM’s ecosystem partners that deliver this innovation, and Freescale’s announcement is a great example of how our combined technologies are helping drive the industry towards this next-generation vision of software-defined and virtualized networking.

Raspberry Pi founder, Eben Upton, visited the ARM offices where he told us about the new Raspberry Pi Compute Module - a tiny low-cost embedded computer targeting industrial applications. I managed to get a quick video interview with him too (see below).

 

It was real a privilege to meet Eben. He gave insights into Raspberry Pi's continuing mission in education, some of his favorite space-based projects, and how Raspberry Pi has become an unexpected hit in industrial computing applications. With over 2.5 million boards enabling innovation and education across the world, I am certainly proud that Raspberry Pi is ARM based.

 

 

Raspberry Eye in the Sky footage courtesy Dave Akerman

 

 

 

Raspberry Pi Compute Module Specifications:

 

Untitled.png

  • Low cost, low power embedded computer
  • The same Raspberry Pi SoC (Broadcom BCM2835 based on the ARM1176JZFS processor)
  • 4GB Flash Memory on board (equivalent to the SD card in the original Pi).
  • A standard DDR2 SODIMM edge connector
  • A unit cost of around $30 in batches of 100
  • A tiny 6.76cm  x 3cm form factor

 

More information: Raspberry Pi Compute Module: new product! | Raspberry Pi

The Batteryless Energy Harvesting Remote Control can be taught Infra-red codes and then repeat them. This post explains the way in which this was achieved.

Learning Infrared codes

 

The circuit uses an Infra-red demodulator. The commands from an existing device are fed into the demodulator. The output of the demodulator is connected to an input pin on the MCU. The software is rather simple; it “guesses” which protocol is being sent. This is done by measuring the mark and space time of the received signal and applying a set of rules to determine the protocol. The flowchart below outlines the basic process.

 

 

The code utilizes the programmable interval timer (PIC) to determine the on and off time for the sample.

 

        PIT_configure();
        PIT_setInterupt(1);    
        PIT_resetVal();

        while(irDetector());                                                //wait until an IR signal is detected.

        PIT_start();                                                        //Start the programmable interval timer.

                do
                {
                    while(irDetector())                                          //Start with on time
                    {
                        if(PIT_readValS() > 5) break;                               //Break after 5 seconds of not changing.
                    }

                    diff_times[i] = PIT_readVal();                                //Store current counter value.
                    if(PIT_readValS() > 5) break;
                    PIT_resetVal();                                               //Reset to 0.
                    if(diff_times[i] > largest) largest = diff_times[i];          //Set new largest time where appropriate   
                    i++;

                    while(!irDetector())                                                                                    //Repeat for off time
                    {
                        if(PIT_readValS() > 5) break;
                    }

                    diff_times[i] = PIT_readVal();
                    if(PIT_readValS() > 5) break;
                    PIT_resetVal();
                    if(diff_times[i] > largest) largest = diff_times[i];
                    i++;


                } while(i < SAMPLE_LENGTH);
                num_samples = i;
                PIT_setInterupt(0);
                PIT_stop();
                PIT_powerDown();


 

The time of the initial high and initial low is then determined, as is the mark and space time:

 

    j=0;

        for(i=0;i<num_samples;i++)
                {
                    if(diff_times[i] >= (largest-(largest/100)))                
                        {
                            start_locat[j] = i;
                            if(j>0)
                            {
                                temp+= (start_locat[j] - start_locat[j-1]);
                            }
                            j++;
                            if(j>4) break;
                        }
                }

                    average_bits = start_locat[0]/2;
                    start_time_high = diff_times[1];                                   //determine the initial time high
                    start_time_low = diff_times[2];                                    //determine the initial time low 
                    temp = 5;
                    j = 25;
                    mark_time = largest;
                    for(i=temp;i<=j;i++)
                    {
                        if(diff_times[i] < mark_time) mark_time = diff_times[i];         //determine mark time.
                        if(diff_times[i] > space_time) space_time = diff_times[i];       //determine space time.
                    }


 

A different decoding algorithm is required for each type of protocol. The data is decoded by looking at each time difference and comparing it with the documented mark space ratios for the protocol determined. Some protocols are based on Manchester coding in which a slightly different decoding process is required. Example of decoding algorithms can be seen below:

 

/*----------------------RC-5 DECODE---------------------------------*/
                if((start_time_high >= 700 && start_time_high <= 950)
                    &&(start_time_low >= 700 && start_time_low <= 950)
                    &&(mark_time >= 700 && mark_time <= 950)
                    )
                {
                        device_learnt = RC5;
                    mark_time = 889;

                    space_time = 1778;

                    j=1;                    
                                        j=0;
                    for(i=1;i<start_locat[0];i++)
                    {
                        if(diff_times[i] >= (700) && diff_times[i] <= (950))
                        {
                            data_code |= (0x1<<j);
                            j++;
                        }

                        else if(diff_times[i] >= (1400) && diff_times[i] <= (1900))
                        {
                            data_code |= (0x0<<j);
                            j++;
                        }

                        else
                        {
                            break;
                        }
                    }

                }

/*----------------------NEC/LG/JVC DECODE---------------------------------*/
                else if((start_time_high >= 8000 && start_time_high <= 10000)
                    &&(start_time_low >= 1500 && start_time_low <= 5000)
                    &&(mark_time >= 450 && mark_time <= 600)
                    &&(space_time >= 1400 && space_time <= 2500))
                {
                        
                    
                        mark_time = 560;
                        space_time = 1690;
                    
                    j=0;
                    for(i=4;i<67;i+=2)
                    {
                        if(diff_times[i] >= (mark_time-(mark_time*0.25)) && diff_times[i] <= (mark_time+(mark_time*0.25)))
                        {
                            data_code |= (0x1<<j);
                            j++;
                        }
                        else if(diff_times[i] >= (space_time-(space_time*0.25)) && diff_times[i] <= (space_time+(space_time*0.25)))
                        {
                            data_code |= (0x0<<j);
                            j++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    if(j==16) device_learnt = JVC;
                    else device_learnt = NEC;
                    
                }
                    
/*----------------------SONY DECODE---------------------------------*/
            else if((start_time_high >= 2300 && start_time_high <= 2500)
                    &&(start_time_low >= 500 && start_time_low <= 700)
                    &&(mark_time >= 500 && mark_time <= 700)
                    &&(space_time >= 1100 && space_time <= 1300))
                {
                        
                    
                        mark_time = 600;
                        space_time = 1200;
                    
                    j=0;
                    for(i=start_locat[0]+3;j<20;i+=2)
                    {
                        if(diff_times[i] >= (mark_time-(mark_time*0.25)) && diff_times[i] <= (mark_time+(mark_time*0.25)))
                        {
                            data_code |= (0x1<<j);
                            j++;
                        }
                        else if(diff_times[i] >= (space_time-(space_time*0.25)) && diff_times[i] <= (space_time+(space_time*0.25)))
                        {
                            data_code |= (0x0<<j);
                            j++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    
                    if(j==12) device_learnt = SONY_12;
                    else if(j==15) device_learnt = SONY_15;
                    else device_learnt = SONY_20;
                    
                }
                
/*----------------------SAMSUNG DECODE---------------------------------*/
                else if((start_time_high >= 4400 && start_time_high <= 4600)
                    &&(start_time_low >= 4400 && start_time_low <= 4600)
                    &&(mark_time >= 450 && mark_time <= 550)
                    &&(space_time >= 1500 && space_time <= 1700))
                {
                        device_learnt = SAMSUNG;

                    mark_time = 560;
                    space_time = 1690;
                    j=0;
                    for(i=start_locat[0]+4;j<32;i+=2)
                    {
                        if(diff_times[i] >= (mark_time-(mark_time*0.25)) && diff_times[i] <= (mark_time+(mark_time*0.25)))
                        {
                            data_code |= (0x1<<j);
                            j++;
                        }
                        else if(diff_times[i] >= (space_time-(space_time*0.25)) && diff_times[i] <= (space_time+(space_time*0.25)))
                        {
                            data_code |= (0x0<<j);
                            j++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    
                }
                else 
                {
                    device_learnt = UNKNOWN;
                }



 

Replaying learned codes

 

To replay the learned Infra-red data, an IR LED, which was connected to a PWM pin on the MCU, was used. Because the protocol has been determined, we can look up the correct mark space times and start conditions that need to be transmitted. This has the advantage of reducing any error encountered when learning the infra-red codes.

 

/*---------------REPLAY NEC/LG-----------------*/
if(command.device_id==NEC)
{    
    PIT_resetVal();
    PIT_start();
    PWM_for_time(9000);
    Delay_usRun(4500);
    for(i=0;i<32;i++)
    {
            PWM_for_time(560);
            bit_mask = 1 << i;
             bit = command.ir_code & bit_mask;
          bit >>= i;
        if(bit == 0x0) 
            {
                Delay_usRun(1690);
            }
        else if (bit == 0x1)
            {
                Delay_usRun(560);
            }

    }
    PWM_for_time(560);
    while(PIT_readVal() < 110000);
    
    for(i=0;i<5;i++)
    {        
        PIT_resetVal();
        PIT_start();
        PWM_for_time(9000);
        Delay_usRun(2250);
        PWM_for_time(560);
        while(PIT_readVal() < 110000);
    }
}

/*---------------REPLAY JVC-----------------*/
if(command.device_id==JVC)
{    
    PIT_resetVal();
    PIT_start();
    PWM_for_time(8400);
    Delay_usRun(4200);
    while(TSI_button_held())
    {
    for(i=0;i<16;i++)
    {
            PWM_for_time(526);
            bit_mask = 1 << i;
             bit = command.ir_code & bit_mask;
          bit >>= i;
        if(bit == 0x0) 
            {
                Delay_usRun(1574);
            }
        else if (bit == 0x1)
            {
                Delay_usRun(524);
            }

    }
    PWM_for_time(526);
    while(PIT_readVal() < 55000);
    PIT_resetVal();
    PIT_start();
    }
}


/*---------------REPLAY SAMSUNG-----------------*/
if(command.device_id==SAMSUNG)
{    
    PIT_resetVal();
    PIT_start();
    PWM_for_time(4500);
    Delay_usRun(4500);
    PWM_for_time(560);
    for(i=0;i<32;i++)
    {
            bit_mask = 1 << i;
             bit = command.ir_code & bit_mask;
          bit >>= i;
        if(bit == 0x0) 
            {
                Delay_usRun(1690);
            }
        else if (bit == 0x1)
            {
                Delay_usRun(560);
            }
        PWM_for_time(560);

    }
    while(PIT_readVal() < 108000);
}

/*-----------REPLAY RC5-----------------*/
if(command.device_id==RC5)
{    
    PIT_resetVal();
    PIT_start();
    j=0;
    for(i=0;j<27;i++)
    {
            bit_mask = 1 << i;
             bit = command.ir_code & bit_mask;
          bit >>= i;
        if(bit == 0x1) 
            {
                PWM_for_time(889);
                j++;
            }
        else if (bit == 0x0)
            {
                PWM_for_time(1778);
                j+=2;
            }
            
            i++;
            bit_mask = 1 << i;
             bit = command.ir_code & bit_mask;
          bit >>= i;
        if(bit == 0x1) 
            {
                Delay_usRun(889);
                j++;
                
            }
        else if (bit == 0x0)
            {
                Delay_usRun(1778);
                j+=2;
            }

    }
    while(PIT_readVal() < 114000);

}


 

The IR LED needs to be pulsed at 38KHz for the mark time and turned off for the space time. The way this was achieved is shown in the code below:

 

/*------------------------------------------------------------------------------
  PWM the IR led at 38Khz for a time given in us
 *------------------------------------------------------------------------------*/
/*__INLINE*/ void PWM_for_time(int time_us)
{
    uint32_t curTicks;
  curTicks = PIT_readVal();
  while ((PIT_readVal() - curTicks) < (time_us))
    {
        FPTD->PDOR |= (1UL << 7);
        Delay_usRun(11);
        FPTD->PDOR &= ~(1UL << 7);
        Delay_usRun(11);

    }
    FPTD->PDOR &= ~(1UL << 7);
}


 

The codes need to be stored in a more permanent place than RAM in case the remote control is powered off. Using EEPROM, which usually connects to the Microcontroller via I2C or SPI would have increased the power consumption of the circuit. Instead flash memory was used. Carrying out a procedure called in application programming allows you to save data into the flash memory. More information on writing data to flash can be found in Writing Data To Flash During Program Execution With The Freescale KL25z Series.


The next development step was Batteryless Energy Harvesting Remote Control Power Regulation With The ARM Cortex-M0+

This article explains how we wrote data to flash during program execution when developing the batteryless energy harvesting remote control. This remote control used an MCU from the Freescale KL25z series. The MkL25Z128VLK4 was used. Please be aware that, if done incorrectly, this can kill your MCU.

Defining a region in memory to store the data

 

The starting point for flashing data is to define a memory region to store the data in. At this point it is necessary to look at the memory map for the device to see where the flash is located and if there are any protected/reserved regions in it. If we look at the Freescale MkL25z series reference manual we can see that the regions specified in the example code below are suitable to store the data.

 

/*------------------------------------------------------------------------------
  Data stores for eink frame buffer and IR codes. 
    Volatile to prevent compiler optimisation
 *------------------------------------------------------------------------------*/
volatile ir_command device_1[45] __attribute__((at(0x09000)));
volatile ir_command device_2[45] __attribute__((at(0x0A000)));
volatile ir_command device_3[45] __attribute__((at(0x0B000)));
volatile ir_command device_4[45] __attribute__((at(0x0C000)));
volatile char frame_buff_store[176][33] __attribute__((at(0x0D000)));
volatile int page __attribute__((at(0x0C500)));
volatile int device __attribute__((at(0x0C504)));
volatile int signed tv_locat[6] __attribute__((at(0x0C800)));
volatile int signed dvd_locat[6] __attribute__((at(0x0CF00)));


 

These regions have been defined as global variables. The regions usually have to be long word aligned.

 

In the energy harvesting remote control example we defined regions for the infra-red commands that the remote control could “learn”. We also defined regions for the frame buffer, for the page and for the device so that the e-ink display could be altered accordingly. We added regions for the Television and the DVD player locations, these used accelerometer and magnetometer values to determine where the remote was pointing. If pointing at the television, the device would automatically switch to the Television User Interface.

 

Using Memory View in Keil Debugger

 

The next stage of the process is to test whether it is safe to flash the regions chosen. Memory View in Keil Debugger is excellent for this.  Look at the 1 KB after the region defined for the data. This region should be blank and unchanging. If it is not it may be necessary to look at the scatter file to see what is next to it.

 

Once you are happy that you are not going to corrupt something by erasing the block of flash, it is time to erase the flash. For a successful erase to occur, and to ensure that the core does not lockup and reset, it is essential that nothing else is going to use the flash during these operations.

 

Erasing the block of Flash

 

This is achieved by placing the code to execute the flash commands into the on-board RAM for execution. To do this you need to right-hand click on the file you are using to write data to flash, and selecting options.  You then need to look at the memory assignment section at the bottom of the page and change the ‘Code / Const’ to a RAM region on your MCU. This will ensure that every time your application starts this section of code is copied into the RAM for execution.

 

The important registers for the MkL25Z series are the FCCOB registers and, as can be seen in the reference manual, these are numbered 0-B. The FSTAT register is needed to determine if the FCCOB registers are free to use.

 

/*------------------------------------------------------------------------------
  Erase the flash block containing the sector
 *------------------------------------------------------------------------------*/
int flash_EraseSector(long int sector)
{
    int temp1,temp2,temp3;

    //Dividing the sector address into the 3 bytes before starting to fill the FCCOB
  //registers reduces the risk of the operation being corrupted:

            temp1 = (sector << 8);
            temp1 = temp1 >> 24;
    
            temp2 = (sector << 16);
            temp2 = temp2 >> 24;
    
            temp3 = (sector << 24);
            temp3 = temp3 >> 24;
    
    //Wait until the command complete instruction is cleared indicate the FCCOB registers
  //are available:

            while(((FTFA->FSTAT)&(1UL << 7))==0x00);
    
    //Clear any previous errors from the last operation:
    
            if(!((FTFA->FSTAT)==0x80))
                    {FTFA->FSTAT = 0x30;}

            FTFA->FCCOB0 = 0x09;     // 0x09 is the instruction code for erase
            FTFA->FCCOB1 = temp1;    // Load the segment address into registers
            FTFA->FCCOB2 = temp2;
            FTFA->FCCOB3 = temp3;

            FTFA->FSTAT = 0x80;         // Writing a 1 to bit 7 of the FSTAT register launches 

            // Wait for command completion:

            while(((FTFA->FSTAT)&(1UL << 7))==0x00);

    return 1;

}


The example code above shows exactly how we did the erase for the MkL25Z series. This function is called from another handler function also running directly from RAM to reduce the risk of core lockup. The handler function is shown below. A delay is required between calling the handler function and carrying out flash commands to prevent core lockup. In the example code below this was achieved with a simple for loop.

 

/*------------------------------------------------------------------------------
  Write a page and device to flash memory.
 *------------------------------------------------------------------------------*/
void flash_memory_tv_loc(signed int ax,signed int ay,signed int az,signed int hx,signed int hy,signed int hz)
{
    int j;
    for(j=0;j<10000;j++); //delay
    flash_EraseSector((int)&tv_locat);
    for(j=0;j<100;j++);
    flash_writeLongWord((int)&tv_locat[0],ax);
    flash_writeLongWord((int)&tv_locat[1],ay);
    flash_writeLongWord((int)&tv_locat[2],az);
    flash_writeLongWord((int)&tv_locat[3],hx);
    flash_writeLongWord((int)&tv_locat[4],hy);
    flash_writeLongWord((int)&tv_locat[5],hz);

}


 

 

Writing data to Flash

 

The final part of writing data to flash is the write itself. This is very similar to erasing but with a different instruction code. The example code shows how this is achieved for the MkL25Z series.

 

/*------------------------------------------------------------------------------
  Write a long word to an erased flash block
 *------------------------------------------------------------------------------*/
int flash_writeLongWord(long int locat,long int value)
{
        int temp1,temp2,temp3,temp4,temp5,temp6,temp7;

            temp1 = (locat << 8);
            temp1 = temp1 >> 24;
            temp2 = (locat << 16);
            temp2 = temp2 >> 24;
            temp3 = (locat << 24);
            temp3 = temp3 >> 24;
            temp4 = value >> 24;
            temp5 = (value << 8);
            temp5 = temp5 >> 24;
            temp6 = (value << 16);
            temp6 = temp6 >> 24;
            temp7 = (value << 24);
            temp7 = temp7 >> 24;


            while(((FTFA->FSTAT)&(1UL << 7))==0x00);    

            if(!((FTFA->FSTAT)==0x80))
                    {FTFA->FSTAT = 0x30;}

            FTFA->FCCOB0 = 0x06;    //0x06 is instruction code for write long word.

            FTFA->FCCOB1 = temp1;
            FTFA->FCCOB2 = temp2;
            FTFA->FCCOB3 = temp3;
            FTFA->FCCOB4 = temp4;
            FTFA->FCCOB5 = temp5;
            FTFA->FCCOB6 = temp6;
            FTFA->FCCOB7 = temp7;

            FTFA->FSTAT = 0x80;

            while(((FTFA->FSTAT)&(1UL << 7))==0x00);

        return 1;
}


 

As can be seen, more of the FCCOB registers are required, when compared with an erase, because the location and the value must be specified.The instruction code for writing a long word is 0x06. The instruction code for an erase is 0x09. These can be looked up in the reference manual.

 

If you have problems with core lockup, check all the pointers for the functions/data you’re using to make sure they’re in RAM.

 

 

The next development step was Infra-Red Code Learning And Repeating For The Batteryless Energy Harvesting Remote Control.

Filter Blog

By date:
By tag: