RTOS w/Dictionary

RTOS with a Dictionary is standard in any system I build.

Most people will think FreeRTOS or a similar thread shifter then we say “RTOS” on embedded, but the hard reality is that most embedded systems are “barebone” and run some version of a round robin scheduler. Myself I do the same – I install FreeRTOS if I need to, but I still run a Linear Scheduler on top of FreeRTOS, Linux or Windows because they scale better than needing a stack for every thread.

Another major issue is that a linear scheduler can switch tasks with ca 10us in between, while any task shifter struggle with the same since they are depending in interrupts. You are welcome to try interrupts 10,000 times a sec (100us) and see what happens. You will be using a lot of CPU power on that interrupt alone – depending on MCU.

But, what about the OS part of any RTOS? An OS is more that just multi-tasking – it is your eco-system with library functions you can safely access in any module and expect to exist on any system you use.

  • Clock – RTC and ETC is a must
  • Signals and Timers
  • Message Queues
  • Standard API functions/framework.

Myself I also include a mechanism called a Dictionary that is an index over variables and tables that I use as API between modules. In a well designed system my dictionary will be the only module that can access all parts of a system and it consist of a generic part that is extended with an index table containing pointers to variables and tables I want to access.

One of the standard functions are Persistent Memory that is handled by the Dictionary.

Another critical function is entity integrity then dealing with protocols like CAN and Modbus. These protocols are capable of sending you a single parameter in a message, meaning that your system can start operating on incomplete data unless you have a mechanism ensuring integrity over a set of variables. The most used technique is a low cost CRC.

But mentioning CAN, Modbus and other protocols they all access the same variables making it very convenient to build these protocols on top of a dictionary.

Or to make it simple – a well designed dictionary will simplify your system dramatically and reduce the total usage of flash/ram if you have a complex system.

CLI and Configuration is another feature. Will all API variables accessible through a central dictionary it becomes ease to implement a CLI with set/get functions, and since CLI is USB/TCP or serial ports they can be scripted as well.

The last trick I often use is the HMI that mirror the dictionary on a PC that again is linked 1:1 with components or entities on the screen. This allows me to focus on gadgets and with a few lines of code I have fancy UI that can visualize or edit variables/tables on multiple embedded devices.

FreeRTOS or any thread shifter can be added with a few lines of code if I need them, most often I don’t.

As for modules I have a strict requirement that any module – collection of embedded C++ code – can be dropped into any project with only 2-3 lines of code since they use a standard API and OS definition that I can duplicate on any system embedded, Linux or Windows.

Added functionality like Redundancy or distributed systems is basically added dictionary functionality.

One advice is to use #ifdef to exclude/include entire modules. GCC is very good at excluding code that is not used, but this is the only time I recommend #ifdef and a custom config.h that manage this.

 

ECU – Dual Ethernet

I am using KSZ8863RLL to achieve dual Ethernet, This is a 3 port switch and it basically just replace the LAN8742. The MCU will just see an ordinary Ethernet not realizing that it is a switch. My initial idea was to re-use the ECU main board with minimal changes, but I underestimated the amout of extra components needed + many of the pins need a strap since they have one purpose during boot and another during operation. The result is that with 0603 components I run out of space, I can start pushing trancient caps to the back side, but I also have 2 cm space left on the right side so I can push the MCU to right and re-route the entire board. What I can’t move is the M connectors because they are aligned with the sub-boards, but I can move MCU w/components and route more to the right to free space for dual Ethernet.

The schematics on this is not 100% yet – I have found 2 good references that I am using, but it is a fiddle then you want to reduce components. I am using a trick to strap Ethernet to RESET as it power up so that it don’t boot before the MCU wants it to. I will also use a 2nd 3.3V PSU that can be switched on/off for this. I preffer to leave all components on top layer, but I will consider putting straps and trancient caps on the bottom. It is an interesting routing experimen, so will be interesting to see if I get this working. TBH the complexity on this is at the level where I expect I will need two PCB runs – actually I always do.

Ethernet 100Mbit vs 1000Mbit

As mentioned in my previous entry I started with 100Mbit, considered 1000Mbit and reversed to 100Mbit. The reasons to stick to a more conservative 100Mbit are many:

  • Cost for 100Mbit is ca 1/4th of cost for 1000Mbit.
  • Very few PLC type systems support 1000Mbit on daisy chain designs.
  • And the hard fact is that a 10Mbit system is sufficient for the signaling used in most configurations.
  • Complexity on routing increased dramatically.

All in all I concluded that the benefits of having 1000Mbit was to small to justify the extra cost and risk.

AI Messed Up

I use AI a lot in both electronic design and coding and it mostly provides very good assistance. But, it sometimes messes up completely. This is something you must be aware of.

I started by selecting KSZ8863 as a 3-port Ethernet switch. Talking to AI I ended up with a more modern 1000Mbit version, but after a discussion I reverted to a 100Mbit version and tried LAN9354. I noticed that KiCAD symbols was difficult to find so managed to get AI to code one for me and so far so good – except that the symbols I got was first for a RJ45 and secondly for a different chip – utterly waste of time. I wasted far more time trying to get AI to do the job than it took me manually.

And then I cleared the thread and asked for the most used and reliable option and ended back with KZS8863 – AI admitted it had very little source on LAN9354 so it was less reliable.

The AI’s are getting better, but you need to remember that they are a mirror of what is available on the net and can only precent info available – and they currently mess up on regular basis. I will still recommend using them to speed things up asking them to provide information, but you need to use your own head to double-check and make decitions. This is not the first time I waste time with an AI. A good practice is to start new, blank threads and ask similar questions – you might get different answers simply because it is different solutions and if it start messing up you need to investigate it’s sources.

Profinet Circle

The ilustration below focus of how you daisy chain Profinet (or Ethercat) using a dual ethernet device and optionally create a fully redundant circle.

This design has some popularity in classic PLC designs, but it comes with some pros and cons:

Pros

  • It is easy to connect device to device at 100Mbit and even 1Gbit speed.
  • Low collision rate even with a high number off devices.
  • Fully redundant as it will still function if a cable or device break.
  • No extra SW except config on the device.
  • Supported by “plug & play” components.
  • No need for a Ethernet Switch.

Cons

  • More expensive Ethernet interface per node.
  • Latency increase with number of nodes in the chain.

As each node act as a switch it typically take 25us to forward a message, so with 10 nodes chained you get 250u latency end to end. Profinet RT uses layer 2 MAC protocol to be faster than TCP/UDP, but it is only in the local net and still suffer this latency issue.

If you have any experience communicating with aPLC you will know that it typically iterate on 1ms and slows down the loop as more code is added, so any signals with less than 1ms latency is basically a 1 ms latency. And 1ms is actually very fast in a good design, so this extra low latency numbers are most often of no value. Higher bandwidth compared to CAN is of value assuming you need it + it is easier to (less work) to code a Ethernet system.

Dual Ethernet cost ca 5.- USD extra and save you the Switch, meaning it save some space. More important is actually the option to interract in a Profinet network if you want to communicate with a Siemens PLC or similar + the nodes can offer full redundancy through various schemes.

Code for a minimal Profinet RT modul is less than 100 lines of C code.

Dual 10/100/1000 Mbit Ethernet Main

This is an early draft of the Dual 10/100/1000 Mbits Ethernet Main. I decided to use a 1Gbit switch and the reference schematic don’t have many passive components so this should be ok. From a SW perspective we still have the same board as ECUMain. I will look into providing an alternative for the M12-5 used as PSU connector maybe. I am not sure I can manage a M12-4 version for Ethrnet due to the extra components needed thought. We will see. I think this board will be awesome as you can attach 5 custom IO ports and link the boards with a simple Ethernet cable to get a larger, distributed system. And this supports full redundancy designs as well.

2 x Ethernet

This is an old mock-up for a dual Ethernet module. The design is simple as it is a 3-port Ethernet Switch with 2 external PHY’s and one internal RMII port, so the MCU just run lwIP using a RMII port as before and it is in effect a switch so you can connect modules in a chain on Ethernet.

What I consider is to upgrade my 3xCAN (below) with a variant that has 2 x RJ45 Ethernet ports. That way I get a fast Ethernet link between boxes. These switches are also Profinet/Ethercat capable so we could have a lot of fun. The second change I consider is to replace the 3 x CAN ports with more generic IO ports. I already have a separate CAN module, RS485 module and can easely add a RS232 module. STM32H5xx has the same FDCAN as H723. But, the daisy chained Ethernet basically need a 3 port switch to work – yes I can daisy chain in SW, but that add latency. Another observation is that LAN8742 below have a lot of passive components making the Ethernet Phy occupy a lot of space. The 3 port switches require far less space in total.

To achieve this I will need to move SD-Card and SPI-Flash to make space for 2 x RJ45. I probably can move the MCU a bit right specially as I am about to drop the 3 x CAN ports. I would like to keep SD-Card at left, but that will require some trickery.

The objective of this change is to be able to daisy chain PLC boxes using Ethernet without an Ethernet switch + it opens for better Profinet/Ethercat support. The second objective is to open for more generic usage by freeing fixed CAN ports. And then do the same on the more generic ECU Mainboard.

New ECU Main

It is a while since I designed this ECU Main board and to my shame I admit that I did not even assemble the first version because the solutions and SW is the same as for the 3 x CAN board. I am considering requesting new PCB’s now as soon as I am finished with the 3 x CAN. The first version have received a few upgrades and corrections, but I will review the design one more time.

I instantly spot a few mechanical concerns:

  • The SWD is a bit tight to the pin header so it might be difficult to mount. This also reminds me that I need an optimized adapter to replace the old ones. They have worked great, but I want to optimize the space they use. e I need to move the SWD a bit down.
  • The second is if it is room for a M12 on the right-top corner after I moved the DC/DC. I think I have checked that before, but I will re-check it.
  • The last I see is the density of the four leds if I am to lead light to surface.

This new version have a NMEA2000 CAN/Power connector at top-left. PSU voltage is 8-36V so it cover both 12V and 24V and have 6(7) expansion ports free. The connector that is a bit troublesome here is the USB connector, but that is for development primarely.

Another learning lesson is that I should focus on one board at the time. I often order a bunch of boards to save P&P, but end up not even assembling all of them due to lack of time. That will change as I get my PnP machine going and get some experience using stensils – or simply get a factory to assemble boards.

At precent I need to get Ethernet and SD-Card working on 3 x Main before I order new boards.

 

 

 

3 x CAN GW v1.1

This is revision 1.1 of the 3 x CAN Main board. The main difference to 1.0 is that most IO is tested and updated. This is one of 3 main boards in my system and this version is designed to be located on a desktop or in a cabinet with more “normal” connectors. The other two main boards are (1) M12 design with 8 sub-modules and a (2) motor controller eith sub-modules.

 

  1. STM32H723VE with 500Mhz clock speed and loads os RAM/Flash. I have currently used ca 200Kb of 512Kb Flash and even less of SRAM. I reduced speed from 550Mhz to 500Mhz to get a CAN clock that was 25Mhz since that can be reproduced on STM32H7xx MCU’s. I have considered downgrading H723 to H573 to save a few bucks, but I have so far decided against this on all main boards.
  2. Upgraded PSU with capacitors that handle 50V and have a proper EMI filter. Input PSU is either USB through jumper or 8-36V isolated on the connector. An elegant DC/DC module convert to 5V/4A, while the last stage is a 3.3V/500mA converter. This board/MCU uses a bit of current so “as is ” we are up in ca 300mA, but CAN ports and modules are powered through 5V that handles 4A.
  3. 3 x FDCAN ports through a cable connector that connect to a DSUB9 on front panel. Two of these boards can fit in the same box if you want 6 CAN ports. CAN ports can in theory handle 12Mbps, isolated to 5KV and with SW controlled 120Ohm resistor. I just tested these ports, but I have not tested FD-CAN speeds yet. My experience with CAN tells me multiple devices connected on higher speeds will be an issue, but lets see. CAN is in general much faster and more capable that people expect if SW design is intelligent. I have worked on systems with 12 nodes on the network, but some standards insist on using CAN 1:1 as well.
  4. 3 x Module ports allowing sub-modules to be connected though a very fast serial port. Part of the design is that cables can be connected 1:1 and that sub-modules can download FW and restart etc from main board. I will need to add a bootloader for the mainboard itself, but sub-modules uses the build-in bootloader on STMH5xx MCU’s. I am currently using STM32H503 and STM32H523 on sub-modules.
  5. 1 x Link port designed to connect between main boards. This is the same as the module ports, so it can be used for a 4th module. Planned speed on these are 8Mbps full duplex, but this can be adapted. In theory we can use 12Mbps, but again – these speeds are not tested yet.
  6. 10/100Mbps Ethernet port. This is only partly tested and fixing this is next on my task-list. I also have two Ethernet modules (1) with W5500 and another dual Ethernet module, so I am undecided as to what I want with this Ethernet. I have considered removing it and only use sub-modules several times, but I can as well just leave it and not populate the PCB unless I need the extra pins/space.
  7. 1 x SPI Flash. I equip all boards/modules with a 2 Mbyte Flash as minimum. This is divided into 500Mbyte for variables and 3 images for code.
  8. 1 x SPI FRAM/PSRAM position. It uses the same interface as a SPI Flash, but a more narrow ship.
  9. 32 Gb TF Card – this is the second content that is not tested yet.
  10. Standard USB-C port – this is what I use to power the board and to test with. This is not isolated, but it will work straight up as a serial port on any PC and makes this board a CAN/USB GW for my laptops.

Considerations:

  • A WIFI/BLE or Lora module would be nice, but this can easely be added as a module.
  • More module ports would be nice, but I would need to remove Ethernet for that. The issue with the sub-modules is that you add the IO you need so this becomes a customized system in a box. My M12 design is better on this, but I am considering modules with different connector options as well.
  • I currently use 3 expensive CAN tranceivers and consider saving in the region 15USD by swapping them out with cheaper variants that lower isolation to 3KV and speed to 5Mbps – lets see.

Extensions:

  • LCD/TFT Display. It is possible to attach a LCD/TFT display through one of the 4 serial ports. You can use a 3rd party solution as well. We can easely have screen from 2″ to 10″ as needed by some systems. One option is to use a RPI with a TFT screend just connect on the UART. I have both 5″, 7″ and 10″ screens around as well as larger screens. We could even use a RPI Zero that cost 5USD if you only want a screen or any RPI if you want to use Wifi/BLE that way. The main challenge with RPI is the PSU, but I will test a solution for that as well soon. I have a RPI5 project with a 256Gb M.2 disk + a 10 inch TFT and I need to fix the PSU on that anyway.

Production:

The plan is to start a small production line either by assembling these in China or assembling in-house. I will probably test both.

BOM cost – I think an optimized BOM should be < 50.- USD – I need to work on that.