Memory-Mapped Devices as Objects - Dan Saks - CppCon 2020

Sdílet
Vložit
  • čas přidán 9. 06. 2024
  • cppcon.org/
    github.com/CppCon/CppCon2020
    ---
    Most, if not all, modern CPUs communicate with external devices via memory-mapped device registers. A memory-mapped register is circuitry that connects to a CPU’s bus structure and responds to bus signals almost as if it were ordinary memory. Almost, but not quite.
    C++ programs can use C features such as pointers and casts to access memory-mapped registers. This is still widespread practice. However, traditional C techniques tend to treat memory-mapped registers more as raw storage than as objects with constrained behaviors. C idioms for accessing memory-mapped devices leave too many opportunities for programming errors and late nights with a debugger.
    This session explains various C++ techniques for placing objects into memory-mapped locations and for guaranteeing proper initialization and destruction. It shows how you can use base classes and templates to capture commonalities among different devices that use similar register layouts. By applying these techniques, you’ll be able to package memory-mapped devices as lightweight class objects that are easy to use correctly and hard to use incorrectly.
    ---
    Dan Saks is the president of Saks & Associates, which offers training and consulting in C and C++ and their use in developing embedded systems. Dan used to write the “Programming Pointers” column for embedded.com online. He has also written columns for numerous print publications including The C/C++ Users Journal, The C++ Report, Software Development, and Embedded Systems Design. With Thomas Plum, he wrote C++ Programming Guidelines, which won a 1992 Computer Language Magazine Productivity Award. Dan has taught C and C++ to thousands of programmers around the world. He has presented at conferences such as Software Development, Embedded Systems, and C++ World. He has served on the advisory boards of the Embedded Systems and Software Development conferences. Dan served as secretary of the ANSI and ISO C++ Standards committees and as a member of the ANSI C Standards committee. More recently, he contributed to the CERT Secure C Coding Standard and the CERT Secure C++ Coding Standard.
    ---
    Streamed & Edited by Digital Medium Ltd - events.digital-medium.co.uk
    events@digital-medium.co.uk
    *-----*
    Register Now For CppCon 2022: cppcon.org/registration/
    *-----*
  • Věda a technologie

Komentáře • 38

  • @lglima61
    @lglima61 Před 3 lety +19

    +1 Wow! Very good and powerful features. Never thought about overloading the new operator that way, it really makes sense for embedded programming.

  • @fhajji
    @fhajji Před 3 lety +15

    Thank you for this outstanding presentation. So accessing memory-mapped devices in Standard C++ (C++20) is possible after all. This was very instructive.

  • @JohannesEckhoff
    @JohannesEckhoff Před 3 lety +9

    This was a great talk. I learned a lot!

  • @NKernytskyy
    @NKernytskyy Před 3 lety +3

    Amazingly informative lecture!

    • @CppCon
      @CppCon  Před 3 lety

      Glad it was helpful!

  • @microtechbdsystem-automati8689

    I found best talk on memory map for device Driver development and embedded software development..
    Amazing presentations..
    Thankful for..

  • @user-fv2cn4rf9z
    @user-fv2cn4rf9z Před 3 lety +4

    After the lection you'll know "the right dose of volatility".

  • @luismolinatanco1330
    @luismolinatanco1330 Před 2 lety +1

    What an amazing presentation. I learned so much!!

  • @rajatmond
    @rajatmond Před rokem

    Thank you very much. I am a hobbyist embedded systems programmer and my girlfriend needed my help building a device to automatically take some sensor data for her research. I'm finding it very difficult to use i2c, spi, uart devices in Linux and interrupt handling outright prohibitively difficult. I'm using c++ because i love it. This helped me a little along the way.
    I think a microcontroller is more suited for these jobs as most come with a helper library and there is no separate user-space code as in linux.

  • @brandonlewis2599
    @brandonlewis2599 Před 3 lety +6

    Very cool talk. I was wondering if C++ would allow for this, and I'm glad it's at least moving in that direction. Now to get the hardware vendors to rewrite their C++ APIs using these techniques -- how amazing would it be if you could talk to the peripherals of an STM32 using this approach? It would be so much simpler than the STM32 HAL, and perform better too! But you could write a *real* HAL to provide abstracted interfaces for things like UART, DMA, etc. Similar to what is going on in the embedded Rust ecosystem.

  • @wangyi8848
    @wangyi8848 Před 3 lety +2

    Nice idea for writing a CPP driver.

  • @newoap
    @newoap Před 3 lety

    Excellent talk.

  • @ognianmilanov5276
    @ognianmilanov5276 Před 3 lety +1

    Good stuff!

  • @abrarrahmanprotyasha1675

    Amazing lecture! I learned a lot :-)

    • @CppCon
      @CppCon  Před 2 lety

      Glad it was helpful!

  • @ABaumstumpf
    @ABaumstumpf Před 3 měsíci

    10:50 - would be a lot better if the committee FINALLY did what people had been suggesting for decades: give us actual strong type aliases.
    "using device_regist = uint32_t;" would help a lot more if the compiler then treated it as a separate type so you can not mess up parameter order (still a common problem specifically cause of this).
    27:37 - and that is the same problem as before.
    30:01 - no, it is not to "inhibit" optimizations... it is to declare that accessing that variable can have other side-effects.
    It would also have helped if they never made the mistake of "std::atomic".

  • @NKernytskyy
    @NKernytskyy Před 3 lety

    59:16 - brilliant idea!
    59:44 - hack-and-twist.

  • @rafalmichalski4893
    @rafalmichalski4893 Před 3 lety +5

    Great talk as always, but I believe there is still one thing to cover. There is custom new operator implementation and that's fine, but how about missing custom operator delete. In case of UART class object we should not invoke delete operator I guess, since default implementation frees memory on the heap (probably "free" function based implementation) and such invokation would be problematic (or does not make any sense rather) in our case for hardcoded device address. But missing delete invokation may cause some memory leak error detected by some tools (e.g. valgrind), so we got some kind of false positive error then. I can also imagine case where someone uses UART class with smart pointer (with default deleter). So maybe only one missing part of this picture is empty implementation for custom delete operator ?

    • @magnusf2582
      @magnusf2582 Před 3 lety +2

      He seems to"leak" the object and the constructor is not throwing anything so the delete operator should never be called but yes, an operator delete should probably be declared.

  • @nhanNguyen-wo8fy
    @nhanNguyen-wo8fy Před 5 měsíci

    10:00
    23:30
    25:45
    46:24 padding, packing
    47:24

  • @ryanobrady569
    @ryanobrady569 Před 2 lety

    This is a good talk. One thing I'm wondering is does LTO help with performance when using the linker placement method?

  • @CameronTacklind
    @CameronTacklind Před 3 lety +4

    Does anyone have a minimum header file that does this for some trivial memory mapped hardware? It would be super handy to have a place to start from instead of trying to copy all the gems out of this video one at a time.

  • @Johnny-ot3go
    @Johnny-ot3go Před 7 měsíci

    In my opinion, instantiating for this type of class is often not what we want, which means the constructor and copy operation should be deleted. Consequently, we likely to have a factory method to get the instant, and I think that factory can achieve the same goals as "class-specific new".

  • @user-ck1kx5ie6t
    @user-ck1kx5ie6t Před 3 lety

    I would prefer to define the device registers to reside in a dedicated segment and instruct the linker with the starting address of that segment. It's still implementation-dependent, but it calls the constructor and is way better than resorting to reinterpret_cast in my opinion.

  • @kuhluhOG
    @kuhluhOG Před 2 lety

    9:22 that's more of a subset though
    "easy to use correctly but hard to use correctly" also implies that it is so easy to use, that you don't get any errors

  • @urugulu1656
    @urugulu1656 Před 3 lety

    great talk! but how do you use interrupts in that manner?
    think: interrupts have to reset certain bits to prevent multiple fireings of the same interrupt. so interrupt handlers should ideally access the registers as directly as possible. (some interrupts even have to be cleared within x number of cycles...) until no i go with the interrupt service routine being declared as a friend function of the device driver class... this does not feel to great however...

    • @magnusf2582
      @magnusf2582 Před 3 lety +3

      I think the normal way is to make the interrupt handler a stativ member.

    • @luismolinatanco1330
      @luismolinatanco1330 Před 2 lety

      Hi @urugulu, look up 'Writing better embedded Software Dan Saks Embedded 2018'

  • @urugulu1656
    @urugulu1656 Před 3 lety

    avr-gcc 5.4.0 in cpp11 mode does not have type_traits...

  • @azdinator
    @azdinator Před 2 měsíci

    Is there any reasons why the Saks brothers dont put the slides on git ?

  • @xavierthomas1980
    @xavierthomas1980 Před 2 lety

    Isn't it possible to work around the limitation of reinterpret_cast not being acceptable in a contant expression by using bit_cast instead? Also I think the deprecation of volatile is only affecting the "non sensical" use of the qualifier, like declaring a function parameter volatile. It should not affect what was said in this talk.

    • @vedvern
      @vedvern Před 9 měsíci

      Unfortunately, the std::bit_cast template is not constexpr when converting to and/or from a pointer type

  • @goswinvonbrederlow6602

    Using attribute packed is about the worst you can do for device registers. A packed structure will have an alignment of 1 and the compiler has to generate code that will work with that alignment. On architectures without unaligned access, e.g. ARM, that means reading/writing the uint32_t as 4 separate bytes, which is often undefined by the hardware as device registers must be accessed in the right size. So NO NO NO to using attribute packed. Use a plain class and static_assert the offsets.

  • @oidpolar6302
    @oidpolar6302 Před 3 lety

    Cpp have no standard mechanism to map the register, so instead of mentioning compiler dependent placement, why don't you show how to define class wrapper around already existing c based SDK?

    • @magnusf2582
      @magnusf2582 Před 3 lety +8

      Because C also lack a standard mechanism. The usual C method is to have pointers to each register and he uses the whole talk to speak about better ways than that.

  • @PrivateUsername
    @PrivateUsername Před 2 lety

    6:40 Seems like a straw man. No C programmer worth a damn would ever use "int" for a device driver. "int" can vary in size depending on which modern architecture. But even then, the hardware interface would be defined as a packed struct with endianess guarantees.

    • @martinmckee5333
      @martinmckee5333 Před 2 lety

      I agree that I've never seen a plain int in a vendor library. I have absolutely seen assumptions being made about packing, however. You could argue that they aren't good C programmers (I'd happily agree), but that doesn't mean that code like that is in the wild.