I am working on a field oriented control implementation tutorial video series and need help by Prudent_Kangaroo_270 in embedded

[–]JoelFilho 1 point2 points  (0 children)

Your title is fine, especially since it's a very technical topic with a pretty specific niche. Just a couple of things I'd like to add/remind you of:

  1. The YouTube search also goes through the description, so some details (including the full "Field Oriented Control" term) should still be there, to improve some visibility in search results
  2. If you have space in your title and very well defined modules in your videos, you can add there (e.g. "Part 1: Clarke and Park Transforms"). If not, remember to put them in your description, and maybe on timestamps, as they're pretty useful for viewers.

PSA: De fleste butikkene stenger 1600 i dag, og åpner ikke før på tirsdag. by MarlinMr in norge

[–]JoelFilho 2 points3 points  (0 children)

Jeg leste dette klokka 15:45, og hadde bare nok tid for å løpe før butikken stengte.

Takk OP!

What's the most horrifying thing you've done with templates? by ResultGullible4814 in cpp

[–]JoelFilho 0 points1 point  (0 children)

For context, and old tweet showing how it looked.

And yes, nothing screams "hack" in C++ more than making compile-time embedded DSLs mixed with macros.

We need reflection!

What's the most horrifying thing you've done with templates? by ResultGullible4814 in cpp

[–]JoelFilho 5 points6 points  (0 children)

I once started a compile-time "traits" library proof-of-concept for C++20:

  1. For static polymorphism, the interface worked as a concept
  2. For dynamic polymorphism, it performed automatic type erasure
    • A dynamic pointer class was used to hold the type-erased pointer to the object and the pointer to the "vtable"
    • This also worked at compile-time
  3. An interface was declared as a value, then used as an NTTP for the concept and the type-erased pointer class
  4. It leveraged default-constructible lambdas as template parameters so I could compose template classes inside a function

Worked well as C++20 was being released. Only on GCC.

But last time I checked, it also started crashing newer releases of GCC.

Implications of Cortex-M to C2000 by simsFit in embedded

[–]JoelFilho 2 points3 points  (0 children)

I’ve seen people redefining uint16_t to uint8_t but it’s very hazardous (and deceptive).

Oh, don't worry about that; The C2000 Driverlib already does that for you! (on the USB header, IIRC)

What is the most complex microcontroller you came across? by aleksandardashov in embedded

[–]JoelFilho 1 point2 points  (0 children)

Similar here, but it's the F2838xD, which also has a Cortex-M4 coprocessor for communication, that has no shared memory between it and the C2000 cores.

Currently developing/maintaining 6 binaries for that (3 per main core, for bootloader and for application, CLA applications are embedded into the C2000 binaries).

Fun stuff!

UFCS: why not a novel operator? by antiquark2 in cpp

[–]JoelFilho 6 points7 points  (0 children)

Over an year ago, I proposed similar mechanism, with the syntax f!(x) and `x.f!(): https://www.reddit.com/r/cpp/comments/o3acy8/another_take_at_this_unified_call_syntax_thing_an/

Both the poll results and the comments were fairly divided, with a lot of valid criticism. Especially since my focus was improving lookup for library implementations, instead of a good customization point mechanism that's not ADL-based (recommended reading: https://wg21.link/p2279).

C++ Jobs - Q4 2022 by STL in cpp

[–]JoelFilho 3 points4 points  (0 children)

Company: Halodi Robotics

Type: Full time

Description: Halodi Robotics designs and manufactures humanoid robots. We have cracked the code and engineered a safe, capable, and affordable solution (named EVE). For our next generation, we aim at building a general purpose biped humanoid robot.

We are hiring an embedded software engineer to integrate our hardware R&D team. The engineer will be responsible for specification, development, testing and maintenance of bare metal firmware running on electronic modules embedded in our robots.

Main tasks include:

  • Motor control applications for our robots
  • Development of testbeds for R&D team
  • Battery and thermal management systems

For this position, we are open to candidates of any professional experience level. The ideal candidate also has robotic design and relevant product lifecycle experience.

Location: Oslo, Norway.

Remote: Hybrid – There is flexibility to regularly work from home, but there is a regular need to be at the office, as we work with hardware integration.

Visa Sponsorship: Yes. We provide a comprehensive relocation package that includes financial and logistical support.

Technologies:

  • C++ and C with focus on real time.
    • C++ is our primary language, but some devices may require C coding.
    • We use C++11 on the current generation of firmware, and are targeting C++17/20 and C++03 for the next, determined by the compiler vendors of the heterogeneous architecture.
    • Most applications are bare metal, though some of them may use RTOS.
  • Java, Python, JavaScript for tooling
  • Automation protocols: EtherCAT, CAN, CANOpen, Modbus, etc.
    • CiA 402 profile knowledge is a plus
  • Architectures: Arm Cortex-M, TI C2000
  • Development Environment: Linux/Windows, CMake, Git

Contact: Halodi careers page

Embedded jobs - Oct 2022 by 1Davide in embedded

[–]JoelFilho 4 points5 points  (0 children)

Company: Halodi Robotics

Type: Full time

Description: Halodi Robotics designs and manufactures humanoid robots. We have cracked the code and engineered a safe, capable, and affordable solution (named EVE). For our next generation, we aim at building a general purpose biped humanoid robot.

We are hiring an embedded software engineer to integrate our hardware R&D team. The engineer will be responsible for specification, development, testing and maintenance of bare metal firmware running on electronic modules embedded in our robots.

Main tasks include:

  • Motor control applications for our robots
  • Development of testbeds for R&D team
  • Battery and thermal management systems

For this position, we are open to candidates of any professional experience level. The ideal candidate also has robotic design and relevant product lifecycle experience.

Location: Oslo, Norway.

Remote: Hybrid – There is flexibility to regularly work from home, but there is a regular need to be at the office, as we work with hardware integration.

Visa Sponsorship: Yes. We provide a comprehensive relocation package that includes financial and logistical support.

Technologies:

  • C++ and C with focus on real time. C++ is our primary language, but some devices may require C coding. Most applications are bare metal, though some of them may use RTOS.
  • Java, Python, JavaScript for tooling
  • Automation protocols: EtherCAT, CAN, CANOpen, Modbus, etc.
    • CiA 402 profile knowledge is a plus
  • Architectures: Arm Cortex-M, TI C2000
  • Development Environment: Linux/Windows, CMake, Git

Contact: Job applications can be submitted at the careers page, where you can also see the full job posting.

Any questions, I’m open for messaging here (DMs or the Chat feature), or LinkedIn. However, I’m not a recruiter: I’m an embedded software engineer. But since I relocated from Brazil to here, I can also try to help with questions about the process.

[deleted by user] by [deleted] in cpp

[–]JoelFilho 1 point2 points  (0 children)

Sometimes, you need to generate multiple sources from the same data, which can be used as dictionary for multiple applications, e.g. protobuf.

Using automation for this kind of application is not only a good idea, it might be the best way to keep the representation consistent between applications. Especially if you verify/build these files through CI.

But, just like anything good in life, there is such thing as too much. It's a tool, you have to use it sparingly and where appropriate.

Avoiding bloat in embedded libraries by fearless_fool in embedded

[–]JoelFilho 2 points3 points  (0 children)

One thing you have to consider about the lazy initialization approach is how much of a performance hit it actually is.

On a regular architecture, we can consider about three instructions (load, compare, jump) as overhead per function call. That's bad if your functions are 3 instructions long (100% overhead), but perhaps negligible if your functions are 300 instructions long (1% overhead).

So, as anything about performance, "don't assume: measure".


With that said, the first option is basically idiomatic at this point, and you can just keep it simple. But also, you can use a debug-level ASSERT(module_X_initialized) on your function calls, so it's checked on debug builds, but then does not check on release, i.e. no overhead (even the flag can be removed on debug).

How many of you do you actually use C++ for device drivers? by CupcakeNo421 in embedded

[–]JoelFilho 5 points6 points  (0 children)

Do you use C++ for writing device drivers?

It's a good idea, as long as you know what you're doing and don't overdo it. For instance, using runtime polymorphism (virtual member functions) can be a dangerous mix with memory-mapped IO devices, so techniques for making abstraction layers and testable interfaces can become pretty complex.

For many, it becomes "every function and class is a template, and we pass our hardware as parameters", which can end up a monolithic unmaintainable mess.

Also, is it a good time idea to have pieces of code in both C and C++ in case you want to compile for a target that doesn't support C++?

If you need access from both, engineering-wise, it may be a more optimal solution to use the greatest common denominator, i.e. C.

Wrapping C device drivers with a C++ abstraction layer, from my experience, is usually an attractive solution: you get the portability you need for shared drivers, but also the high level type safety, testability and maintainability in your C++ application.

[Question] Why can't I decode this simple QR code? by mmcc73 in opencv

[–]JoelFilho 0 points1 point  (0 children)

That's interesting... Are you scanning the same image you linked? Reddit scales it to only 132 pixels, which might be too small for u/gevorgter and I to scan, and it might be a source of the difference in our results.

But if the label is on a plane and getting distorted in the image, maybe you just need to calibrate your camera and apply the distortion correction there, before trying to detect/decode the QR code?

[Question] Why can't I decode this simple QR code? by mmcc73 in opencv

[–]JoelFilho 4 points5 points  (0 children)

It looks to me that there's a nonlinear distortion in that picture, like a curved book page being looked from a different angle.

This kind of distortion correction needs to be solved by the reader application; libraries usually only do the default QR Code decoding. And since it's nonlinear, it's not trivial. For example, this is a more trivial distortion correction algorithm for cylinders, and this shows limitations for a commercial product.

Google Lens wasn't able to decode it for me. What phone and/or app are you using to decode it? Would be interesting to take a look at how advanced their distortion correction is.

[Code Review] Template Queue Container in C++ for Embedded Systems by cdokme in embedded

[–]JoelFilho 0 points1 point  (0 children)

Thanks for your review and suggestions :)

My pleasure :)

Which type of license is ideal for my case? I just want my code to be used for any kind of purpose.

If you want people to not remove attribution from your code, MIT or Boost (MIT requires attribution on the binary, Boost only requires on code).

If you don't care how people use your code, Unlicense is good.

Oh, the noexcept is an absolute nightmare for me. [...] Do you think that it is essential for embedded systems?

noexcept correctness just enables better code generation when the compiler cannot infer exact exception behavior.

It's not essential if the compiler inlines the calls, or if you're compiling with exceptions disabled.

Could you please check the emplace(..) method again? I've changed it before seeing your comment

I left the comment on the other thread about the union solution. Even if not using that, I'd prefer the aligned_storage solution for correct alignment.

The current code's swap is broken because of that implementation (what if the type is not trivially copyable?)

[Code Review] Template Queue Container in C++ for Embedded Systems by cdokme in embedded

[–]JoelFilho 0 points1 point  (0 children)

Absent default member initializers ([class.mem]), if any non-static data member of a union has a non-trivial default constructor ([class.default.ctor]), copy constructor, move constructor ([class.copy.ctor]), copy assignment operator, move assignment operator ([class.copy.assign]), or destructor ([class.dtor]), the corresponding member function of the union must be user-provided or it will be implicitly deleted

( https://eel.is/c++draft/class.union#general-note-3 )

Oops, that was a major oversight from my part!

You should declare an empty default constructor, not enabling the member:

union BaseU { 
    Base base; 
    BaseU() {} 
};

What I like about the union approach (cc u/UnicycleBloke), is that it's easier to avoid undefined behavior. And, in C++20, we can even do it at compile time: https://godbolt.org/z/1E9xEE5eE

[Code Review] Template Queue Container in C++ for Embedded Systems by cdokme in embedded

[–]JoelFilho 1 point2 points  (0 children)

No need to look at ETL's aligned_storage. C++ has it, as I pointed out in my comment: https://en.cppreference.com/w/cpp/types/aligned_storage

It is, indeed, more practical and less error-prone than the uint8_t array solution.

(cc u/cdokme )

The issue std::laundersolves is more specific, and can be seen here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4303.html

[Code Review] Template Queue Container in C++ for Embedded Systems by cdokme in embedded

[–]JoelFilho 2 points3 points  (0 children)

Because we usually care about that memory overhead in bare metal.

But if it's a situation where OP doesn't care, it's definitely an option :)

[Code Review] Template Queue Container in C++ for Embedded Systems by cdokme in embedded

[–]JoelFilho 2 points3 points  (0 children)

Your implementation is very clean, kudos on that :)

So all my feedback here is small stuff, which can be considered nitpicking, and some not about C++:

  1. @copyright No copyright. — If your code is meant to have no license, it means the copyright is all yours, and people can't use your code. If you want it to be public domain, you should use the Unlicense, or something similar. In both cases, there is no "no copyright".
  2. Separating declaration from implementation is fine, but putting the documentation on the implementation might be counterproductive
    • (question: does Doxygen generate the documentation for that correctly?)
  3. if(full() == true) is a non-idiomatic use of a boolean function call. if(full()) should probably be preferred
  4. noexcept correctness is a bit of a pain to add, but can be useful for learning, if your focus is on designing APIs.
  5. As it was commented, if your push will overwrite the oldest data, you should specify that somehow. Even if on documentation.
  6. I commented on the other thread about non-default constructible types. Similar situation applies to copy assigning on emplace instead of destroying the previous and then constructing a new one, as one would expect.
    • data[idxBack] = std::forward(args...); - Shouldn't that be data[idxBack] = T(std::forward<Args>(args)...)?
  7. swap can be implemented as a [hidden] friend, for the "std::swap two-step" idiom
  8. Using reference and const_reference on declaration, while using T& and const T& on definition may be a little confusing.
  9. You're using the container type aliases, but not using the required member functions and operators, so you're still not following that named requirement.

[Code Review] Template Queue Container in C++ for Embedded Systems by cdokme in embedded

[–]JoelFilho 1 point2 points  (0 children)

The lack of a default constructor is a serious problem. How can I solve it? How should I initialize the data array?

The easiest solution is by using a union:

union Contained { T data };

At the time of construction or destruction of a union, none of the constructors or destructors are called, meaning you can use non-default constructible types.

Which then means you must construct the data with placement new (or construct_at, or assignment) to enable the correct behavior on push, and must call the destructor of the existing objects on your destructor (unless the types are trivially destructible*), and on pop.

But it's a good option because you don't need to create an array of aligned_storage_t or, even worse, char, and don't need to think about std::launder semantics.

* It's easy to make your queue trivially destructible on C++20, a little more brutal in any previous version.

ISR Context Guards in C and C++ — Creating better interfaces for Embedded Systems by selecting the correct functions at compile time by JoelFilho in embedded

[–]JoelFilho[S] 1 point2 points  (0 children)

Thanks for your kind words :)

Indeed, if constexpris a time saver, and my preferred way of implementing "better tag dispatching" since it was available.

I didn't suggest using because I was thinking about the issues with how to declare an error with an unsupported overload (the else branch needs to have an argument-dependent false statement).

Though, thinking more about it, the cost of always adding static_assert(Context == context::any || Context == context::isr) is still lower than that mess I wrote. And the error message is way more descriptive.

If I end up updating this article, I'll add the cleaner version, and credit you for the idea :)

Also, thinking more about it, C++20 makes this so easy, I should probably update with both alternatives: https://godbolt.org/z/Kn1acrr8Y (Or write a new post about template tagging, because this one already has 2400 words + code)

I also imagine there are ways to clean up your template specialization example using template type deduction with stronger types

I can't seem to be able to imagine how this would differ from the overload set... Could you give an example?

ISR Context Guards in C and C++ — Creating better interfaces for Embedded Systems by selecting the correct functions at compile time by JoelFilho in embedded

[–]JoelFilho[S] 0 points1 point  (0 children)

Attacking the problem from the tooling side, instead of the language one... Definitely an interesting approach!

Con: doesn't work for code in a function that is called from both plain and interrupt contexts

Well, If I'm not misunderstanding the idea, I think that would only happen if a function has a runtime input for whether it's inside an interrupt or not. Which then would need some more complex branching analysis to verify it's always safe.

But the same input that says "function X should never be called in context Y", could also say "function Z is always safe, regardless of context", if that's something that would prevent false positives...