Design pattern for interchip communication? - Page 1
Forum section: electronics / general

author: jnz
author_rank: Frequent Contributor
timestamp: October 26, 2020, 04:05:32 am
content: If you need data going "up" layers, do you try and segment it at each layer? So in my example, Network A would never talk to Application but rather the to Network manager who is then responsible for taking A and B data and getting it to Application.What works for you?EDIT: Nevermind. I am leaning towards an event bus. What got me was there is a difference between Observer which is annoying because each producer needs to know who the consumers will be and message or notify them on event. And Publisher/Subscriber where there is a middleman broker that each consumer will subscribe to and it's that layer's job to message and notify. Saves me from having a bunch of queue externs all over the place and tightly coupled layers that directly talk to each other. Where I'm heading everyone will bring in the event bus and subscribe to what they want to see.

author: Sal Ammoniac
author_rank: Super Contributor
timestamp: October 26, 2020, 05:30:20 pm
content: KISS

author: jnz
author_rank: Frequent Contributor
timestamp: October 27, 2020, 07:36:16 am
content: Quote from: Sal Ammoniac on October 26, 2020, 05:30:20 pmThat's the point of discussing design patterns, right?Except few people seem to do it, and even less in embedded. It's all new wheels all the time.

author: voltsandjolts
author_rank: Unknown
timestamp: October 27, 2020, 09:15:00 am
content: Single wire CANbus? (Assuming micros are in close proximity, on same board)

author: MosherIV
author_rank: Super Contributor
timestamp: October 27, 2020, 09:27:35 am
content: From what I remember of your original post, I think you are mixing a number of ideas up :Hirachical design and task managementTask management and resource managementInter task messaging and function calls.I am not aware of a 'design pattern' specifically for tasks but generally intertask communications is best done with the RTOS task messaging. Just use the RTOS task message read function to make the task wait/suspend for a message. When a message is recieved, process it.Put this into a loop.Design around this basic concept.Yes, one task will have to direct message to another specifc task.No need to use semaphore or mutex - these are used to manage multiple tasks using 'resources' such as hdd or in your case serial device.However, the fact that you have tasks to manage the serial port to transmit and receive messages means you use the task as the resource manager. Only use that task to handle the serial hardware.Only use task message to that task.Edit: KISS means Keep It Simple Stupid, not a name of a design pattern. He means do not over think it and go with the simplest solution.

author: Jeroen3
author_rank: Super Contributor
timestamp: October 27, 2020, 09:59:14 am
content: Network A does talk to application, except there is a network manager behaving as proxy application in between.

author: Siwastaja
author_rank: Super Contributor
timestamp: October 27, 2020, 10:11:33 am
content: Start by realizing if you need generic anyone-can-talk-to-anyone communication, or are youreallydoing just point-to-point links.The latter case is often very easy to handle with non-generic, per use case tailored direct memory transfer operations; I prefer simple packed structs in C for code reuse on both sides, often completely getting rid of the task of writing any kind of data parser.For the former case, see if a simple classic shared bus like CAN or I2C works out for you.

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 27, 2020, 02:25:49 pm
content: (Insertabout badly designed multi-recipient software message buses here. Please use point-to-point messaging, or implement your event bus using point-to-point message passing. Hardware stuff is completely different matter, of course.)

author: jnz
author_rank: Frequent Contributor
timestamp: October 28, 2020, 07:50:11 am
content: Quote from: MosherIV on October 27, 2020, 09:27:35 amIt's definitely touching on all three of those. But there should be more work put into patterns for embedded so everyone isn't always reinventing the wheel.I know what KISS means, I was implying the curt answer wasn't helpful.Agreed that it's best to use the RTOS queue/mail/event/message/stream objects. Usually we're looking at small amounts of data and a copy queue works fine, other times it's a pointer to a larger object and you have ownership issues if you malloc'ed it in one play, need to use somewhere else, and then need to decide who frees/kills it.QuoteThat was my issue though.That's the difference in Observer pattern and PubSub pattern.I didn't really want each producer to have to explicitly know each consumer, know it's function calls, know it's rtos objects, etc. Reason being each of my layers need specific code related to the others, I like the idea of functionally my PowerManager will get SMPS status from someone, but doesn't care exactly who. Instead.... I like the idea of an event bus. Where each producer reports events, consumers register that they are interested in these events. Everyone knows how to use the event broker / event bus, but no one needs knowledge of any other layers or who else cares about X or Y data. You post things that are important, someone else may or may not read into them. It decouples my layers. I now have a system that works to push data down and read data up at the same time.Along with the other notes, yes, it's great if you can wait on a queue message to come in. But I have defered ISRs. So if Network A has an ISR, it triggers, I set a flag, and notify my Network A task. Notifications are lighter and faster than putting a queue object in that says "ISR HAPPENED" but it's pretty much the same thing. So my loops end with waiting for notification or a timeout because there are cyclic things that need work too. I guess I could drop notifications and land solely on a queue, but I don't see that it's saying a ton, I guess it reduces the complexity a little to one rtos object instead of two.

author: jnz
author_rank: Frequent Contributor
timestamp: October 28, 2020, 07:51:29 am
content: Quote from: Nominal Animal on October 27, 2020, 02:25:49 pmDo you think you could elaborate on the issues of a general pub/sub event bus for event + object passing?

author: MosherIV
author_rank: Super Contributor
timestamp: October 28, 2020, 11:17:43 am
content: QuoteIt has been a while (years) since I worked with FreeRTOS.Aquick glance at the APIs, there is EventGroups for doing the ISR events that you want.However, I prefer using QueuesSets or MessageBuffers. Neither have a wait on message and suspend so you will have do - if no messages, suspend for xLet the OS manage the tasks. Avoid loops that continuously do things, try to suspend tasks as often as possible - so that the system is as responsive as possible.Good idea to mix n match patterns. Yes, you certainly can use the Observer pattern to direct message to the right task.

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 28, 2020, 07:48:52 pm
content: Quote from: jnz on October 28, 2020, 07:51:29 amTL;DR: Publisher-subscriber buses are trivial to DDOS or jam. As an analogue, consider what happens if a chip pulls I2C SDA down "forever".If your implementation does not cross privilege separation boundaries, and you trust each communicator, there are no issues.If your implementation crosses privilege separation boundaries, but you trust all senders, and you limit message lifetime (allowing for some recipients sometimes missing messages), there are no issues.It is when your implementation crosses privilege separation boundaries, and you have untrusted senders and receivers, that you get into very, very careful design and implementation domain. You mentioned userspace application, and this is the part that gives me the heebie-jeebies.Or is your RTOS okay completely crashing if an userspace program does not check its pending events/messages often enough?From past implementations, we know that a "supervisor" cannot heuristically detect spamming and jamming from rapid valid messaging and valid CPU stalling due to overload. That is, there is no difference between a buggy or malicious sender sending lots of messages, and a valid situation where lots of messages are generated. There also is no difference between a receiver that leaves messages unread (or worse, partially received) because it wants to stall the bus, or is simply starved of CPU time due to something even more important. Priority inversion has been suggested as a solution for the latter case, but I haven't seen a single acceptable implementation yet; in particular, PI just makes it easier for a buggy or malicious participant to jam or spam the bus.The known working patterns are implemented on top of point-to-point links. (For example, consider IP multicasting, and POSIX signaling to a process group.) If the typical message size is large, you can reduce memory use by deduplicating and reference-counting the data, so that each recipient basically has a set of message pointers – but unfortunately you'll see that metadata maintenance (especially message expiry due to a stalled recipient) becomes complicated, or your per-recipient-per-message data structures grow larger than typical messages. Instead, copying smallish messages to each recipient's own receive buffer, turns out to be more efficient. Especially if you track resource ownership, the point-to-point approach works best.I have not yet seen an implementation where the message bus was implemented as a subscriber-publisher model inside the privileged/trusted section (kernel), with a scatter-gather "arbitrator" on the userspace boundary so userspace would only have point-to-point messaging, and only kernel-internal messages use the pub-sub event bus. Ithinkit might work. This matches IP multicast model, does not require much state per userspace client on the arbitrator, and trivially allows the kernel side to work even when the userspace side is stalled (with userspace only losing messages); it allows you to implement privilege separation properly, without too much state tracking. Unfortunately, it is nontrivial, and I haven't implemented it myself, so at this point, consider it a theoretical possibility.I am also not convinced that the OSI (or TCP/IP) layer model is the best one for the software implementation itself. That is, that your software needs to implement the layers. You of course need to implement their functionality; I am just saying their structure is only one option.For example, consider a model where each event or message is split into three separate parts: headers, payload data, and errors/state changes. Headers contain routing information across all OSI layers. Only the application layer and the data link and physical layers are interested in the payload data – data link layer only when headers contain a checksum of the payload data; and the physical layer because the data needs to be transmitted physically. Everything in between is only interested in the headers and errors and state changes, so why pass the payload data at all? Also, for firewalls and routers, the header information needs to be separatelymutable, both adding or removing optional fields. (This is especially important with VLAN support.)A typical TCP/IPv4 header is 40 bytes (without options), and TCP/IPv6 60 bytes (also without options). Errors are rare, but state changes relatively common, from connection handshaking to closing. While small packets are relatively common, atypicalpacket has about 1500 bytes of payload. Splitting the logical "event" into the parts that matter, definitely affects how much data you shuffle around.As to interchip communication, I have been assuming here that they all have full memory access, because I'm a software person, and only a hobbyist wrt. hardware implementation details. (This is why I wrote "software message buses".) In that case, it becomes a multiprocessing or distributed processing software problem, with some rather "interesting" cache behaviour real-world issues (in that either you consider cache behaviour, or your implementation will be slow). And those I do claim to know about some.Obviously, others will disagree with what I've written here; that is to be expected. I am only pointing out problems and issues I see repeated time and time again. The CS in me would *love* to see a robust pub-sub message bus implementation that magically didn't have any resource management or privilege separation issues.. but the software engineer side reminds me of the myriad of (security or resource management) problems every one I've seen have thus far had, and that while point-to-point links are "dull" and "uninteresting" and "a chore" to implement, they just have much fewer of those problems, and in a form that is much easier to deal with.

author: jnz
author_rank: Frequent Contributor
timestamp: October 29, 2020, 05:37:37 am
content: QuoteI don’t know where that was implied because it isn’t the case at all.This is a very closed system of only my code. I am only looking at an event bus because I can easily add or subtract subscribers, and that I can add or remove publishers without breaking dependencies in other code.Somehow we got to DDOS and a full OSI model.

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 29, 2020, 06:28:15 am
content: Quote from: jnz on October 29, 2020, 05:37:37 amYou used terms "layer" and "application" and "networking". If you cannot understand why they imply OSI and privilege separation, I do not believe it is worth the effort of either of us discussing the matter at all.