Embedded C Programming Design Patterns | Clean Code | Coding Standards |

แชร์
ฝัง
  • เผยแพร่เมื่อ 21 พ.ย. 2024

ความคิดเห็น • 48

  • @viveknaththulasi7178
    @viveknaththulasi7178 3 ปีที่แล้ว +27

    Not solid info about design pattern, but some quality discussion and topics that embedded developers need to know!
    43:08 use of start-up code
    50:40 use of elf over bin
    1:14:00 Need for RTOS

  • @rjgonzalez8108
    @rjgonzalez8108 3 ปีที่แล้ว +16

    Really good info on container-of. What are other good sources/books for learning more about C design patterns for embedded systems?

  • @ivanperezs
    @ivanperezs 4 ปีที่แล้ว +1

    This deserves a lot of views.

  • @newoap
    @newoap 2 ปีที่แล้ว +2

    Looks good but the code examples are, for me, hard to read.
    I see some people are asking for a link to the presentation. That would be a great idea.

  • @gokulrajaking
    @gokulrajaking 3 ปีที่แล้ว +7

    Please give a link for ppt presentation

  • @massimopanzica7137
    @massimopanzica7137 2 ปีที่แล้ว +2

    Please can you share a link to the presentation?

  • @maciej_sliv
    @maciej_sliv 2 ปีที่แล้ว +6

    Martin! I have learned a few design patterns in C++ (applicable to embedded) and I am trying to find this info in C lang. Many of "DPs" are redundant if someone would switch to C++ and use classes and hide some particular properties, would you agree?
    And with the use of C++ we reveal much more about DPs.

    • @tomaszstanislawski457
      @tomaszstanislawski457 2 ปีที่แล้ว +4

      The problem with C++ is that it bring far too many complex and implicit mechanics with it. And the actually useful parts have simple workarounds in plain C.

    • @maciej_sliv
      @maciej_sliv 2 ปีที่แล้ว +6

      @@tomaszstanislawski457 I find C++ simplifying the stuff I am doing. Have a look at Dan Saks's talks on youtube.

    • @mkschreder
      @mkschreder  ปีที่แล้ว +4

      C++ is a slippery language. There is layers upon layers of abstractions and compilation times (because of people that abuse templates) are snail speed compared to C (this makes huge difference when you need to build 1000s of sources). So I agree with Tomasz that C is entirely sufficient and if we want to move away from C we can move away into Rust but definitely not C++. (we can still use C++ for where it makes sense - complex application development - but for kernel, drivers and system level utilities C is golden).

    • @Kotesu
      @Kotesu ปีที่แล้ว

      @@mkschreder @tomaszstanislawski457 - I'm a 15-year embedded dev and wanted to reinforce their points: I've used both C and C++ for embedded work and when we did, we chose C++98 to C++11 and even then we limited it to a subset that some people call "C with Classes": restricted inheritance (primarily for virtual classes to define interface), no templates, no dynamic memory, etc. To do this, we usually ran baremetal with no standard libraries whatsoever. It meant a bit of work up front but the net result was super clean and tight. It's a monster job getting up to that standard though, for what could be argued was syntactic sugar.

  • @nortronics
    @nortronics 9 หลายเดือนก่อน

    Thanks for the video but for future ones, the slides need to be full screen to be able to read the code.

  • @EdwinFairchild
    @EdwinFairchild 2 ปีที่แล้ว +5

    they hijacked some of the discussion into random micro-controller and C 101 topics lol

  • @jamespeterson7979
    @jamespeterson7979 ปีที่แล้ว +1

    Thanks for the overview.
    I am new to the embedded world and c in general. My goal is to produce code that is maintainable, which is not as easy as i would wish because of tight deadlines. Unfortunately Code get's shipped as soon as it works, that makes it kind of difficult to get it right in the sense of good structured. As soon as it is shipped the project is locked no changes allowed afterwards :/
    Just a small note. The video codec is blurring the dark-themed code-examples very heavily, even on max resolution. Maybe you could zoom the presentation to full screen-width or increase the size of the font.

    • @mkschreder
      @mkschreder  ปีที่แล้ว

      This video is quite old. I have a much more up to date udemy course here: www.udemy.com/course/embedded-c-programming-design-patterns/

    • @jamespeterson7979
      @jamespeterson7979 ปีที่แล้ว

      ​@@mkschreder Thank you, i gone look into that.

  • @electronlabs2802
    @electronlabs2802 2 ปีที่แล้ว

    @58:10 i believe when a bootloader jumps (not a reset but changing the SP and PC registers) to a user application (or vice versa) .. they might be turned on by the other program. its not a reset so its good idea to disable inturrepts i think

    • @electronlabs2802
      @electronlabs2802 2 ปีที่แล้ว

      01:07:45 "kind-of a guarantee" 32-bit integers are atomic ..
      i thought they are "guaranteed" to be atomic arent they ? .. could please tell me more on this ? thanks.

    • @Julian-vs1tl
      @Julian-vs1tl 2 ปีที่แล้ว +1

      The guaranteed atomicity does mean that you will not get inconsistencies within the byte/half-word/word as long as they are aligned. The aligned requirements makes that brittle already (imagine operating on a packed struct).
      And what you also need to consider: The atomicity is with respect to the write instruction. A concurring read to the same address is guaranteed (alignment given) to get a consistent value before OR after the write. But your common usage of a memory location would be to read->modify->write. Imagine the interrupt arrives after the applications read instruction, writing to that same location. Then your application modifies the old value (taken from the register that the read has loaded into and that got restored on the interrupt return) and overwrites the updated value that the interrupt wrote in between. You will never have seen that interrupt update. Very subtle and hard to find. And can get more tricky with interrupt nesting.
      -> always protect concurrent usage of memory locations.
      Your app should disable interrupts, operate on the shared data, and reenable. Time with disabled interrupts needs to be as short as possible to ensure not to miss consecutive interrupts from the same interrupt source since there is just one interrupt flag for a source and not every source will have a data buffer.

  • @alicangul2603
    @alicangul2603 3 ปีที่แล้ว +3

    Questions end at 1:11:50

    • @themohmand
      @themohmand 2 ปีที่แล้ว +1

      Big thanks for that! 🙂

  • @Umbra2310
    @Umbra2310 2 ปีที่แล้ว +2

    Any way of downloading the pdf of the presentation?

  • @kunvarc
    @kunvarc 3 ปีที่แล้ว +4

    Where can I find the source code for mcp4461and stm32 that is shown in this video?

  • @LDdrums20
    @LDdrums20 2 ปีที่แล้ว +1

    Wonderful content! Too bad for the middle questions section. Really annoying!

  • @Picdev-z6l
    @Picdev-z6l 2 ปีที่แล้ว

    Is there any book ?

  • @10e999
    @10e999 3 ปีที่แล้ว +3

    Interesting video.
    I have noticed that some patterns in this video need dynamic memory allocation to work, which, in IMO, is a big red flag in embedded.
    Is the context of this video only kernel-related? (No RTOS/baremetal)

    • @mkschreder
      @mkschreder  3 ปีที่แล้ว +7

      Not necessarily. You can do dynamic allocation if you only limit it to init stage. Then it's not really dynamic allocation - it is rather initial partitioning of the memory into objects that you need based on your configuration. The drawback of such allocation is that you don't know at compile time whether you are within bounds or not. But beyond that it doesn't suffer any fragmentation or similar problems that would warrant against its use - it works exactly the same way as a static array from a memory point of view. Zephyr has been able to implement an excellent workaround so that you only use static allocation - but it does require a whole macro subsystem to implement it properly.

    • @10e999
      @10e999 3 ปีที่แล้ว

      @@mkschreder interesting. Thanks for sharing your though. I like your Zephyr example.

  • @coolwinder
    @coolwinder 6 หลายเดือนก่อน

    Note: Put otherwise global objects in structs and pass them as the first argument.

    • @mkschreder
      @mkschreder  6 หลายเดือนก่อน

      They can be static global, statically allocated through elf sections (ie many variables of the same type across the codebase all go into the same section) or dynamically allocated. The key thing to note is that "data is stored in structs and functions operate on structs. Functions that are member functions of a struct take struct typed self parameter as first argument. Always." this keeps code very easy to understand. Data is segregated and close together in the same struct. You know that a function taking self only modifies that structure and structures under it and has no other side effects.

  • @marcosimpson18
    @marcosimpson18 3 ปีที่แล้ว

    Very clear explication. Thank you very much for the video.

  • @sidhunp
    @sidhunp 3 ปีที่แล้ว

    hello. thank you for detailed presentation. i have not clearly understood the Abstract interface using container_of, specifically the use of double pointer. i have read about container_of and it takes usually the pointer to the element. but I did not understand why there is need to make a ** for the uart driver. is it because our abstract type is of an element inside a struct inside struct?
    Thank you!

    • @tomaszstanislawski457
      @tomaszstanislawski457 2 ปีที่แล้ว

      It is because the element if the container struct is a pointer. Therefore the type of a pointer to this member is a double pointer

    • @mkschreder
      @mkschreder  ปีที่แล้ว +1

      Double pointer is in order to save memory. You can have potentially huge number of instances that all use the same abstract function pointers. So what you do is you place the function pointers into a static const struct and then you link to that struct from each instance. Hence you get a pointer to pointer when you then take the pointer to this pointer member and send it to the abstract interface function as a pointer to a pointer to a member from which the implementation of that function can then get pointer to the enclosing struct using container_of. :)

  • @ravimali2814
    @ravimali2814 3 ปีที่แล้ว

    Amazing video and channel content. Subscribed

  • @AbdelrahmanSameh-mm7dr
    @AbdelrahmanSameh-mm7dr ปีที่แล้ว

    nice info ♥♥

  • @yoyuasa352
    @yoyuasa352 3 ปีที่แล้ว

    How to enable the g option for debugging that is mentioned at 54:02 ?

    • @mkschreder
      @mkschreder  3 ปีที่แล้ว

      gcc -g -c file.c -o file.o

  • @damorafik
    @damorafik 3 ปีที่แล้ว

    Thank you I I subscribed and I will share your channel

  • @mcgdb3606
    @mcgdb3606 3 ปีที่แล้ว

    kick ass presentation

  • @Manjuju123
    @Manjuju123 ปีที่แล้ว

    Seems like a few of these patterns are what OOP languages like C++ supports.

    • @mkschreder
      @mkschreder  ปีที่แล้ว

      Patterns are more often about a way of thinking about functionality rather than language features. The same patterns apply to javascript, python, c# etc. just the syntax is different.

  • @caleb7799
    @caleb7799 2 ปีที่แล้ว +1

    Uuuhhh uuuuuhhhh uuuuhhhh

  • @kurchak
    @kurchak 3 ปีที่แล้ว +1

    uhhhhhh