Author Topic: Taking a C++ class, looking for a C++14 compatible microcontroller to play with.  (Read 26371 times)

0 Members and 1 Guest are viewing this topic.

Offline lukier

  • Supporter
  • ****
  • Posts: 634
  • Country: pl
    • Homepage
I have nothing against assembly as such, sometimes some inline might be required (e.g. inline for SSE/AVX accelerations), but no one in a sane mind would write any project of sensible complexity in assembly, not in 2016. I often prefer to inspect the output assembly to see if I could hint the compiler to do better instead of writing inline snippets.

Maybe the advantages of the example presented in the talk are not clear to everyone. Let me explain. His memory(...) function with this reinterpret_cast is the only contact point with the hardware. One might call it a minimalistic HAL. The rest is C++ business as usual, readable to anyone familiar with C++ and not necessarily this particular chip assembly language.

Also, this is very easy to test. This memory(...) function can be mocked and unit tests can be written in C++ and run on developer's workstation (as there is no inline assembly!) and Continuous Integration systems. In the next step this function might instead interface with SystemC simulation of 6502 or a Cadence simulator - sometimes the hardware is not there yet. Only when hardware reaches FPGA and ASIC levels we can actually run the vanilla code somewhere, and this can be expensive so such testing is done in the later stages and mostly for performance profiling.

Additionally, this memory(...) function can be, for some test build type, replaced with a function that does RPC over UART/Ethernet/whatever to the target system running only so called "Monitor" that only reads and writes to memory/peripherals, while the code itself runs on x86.

Of course all this testing can be done with C and has been, but may require more ugly constructs (preprocessor macros etc), and with inline assembly it becomes a royal pain. The point here is that it might seem that his game is very abstracted (and this improves testability), with classes, TMP and other C++ tricks, and yet it produces very neat and compact assembly.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Apparently "Embedded C++" is so far from "Real C++" that C++ programmers will sneer at you...
http://softwareengineering.stackexchange.com/questions/48401/learning-c-properly-not-c-with-classes
(especially: "you should definitely be using all of those self-expanding containers from the STL.")

(is there an "embedded STL" that omits dynamic allocation?  That might be interesting...)
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Quote
Explain how
*reinterpret_cast<uint8_t*>(53280) = 1;
is clearer than
lda  #1

sta  53280
Hopefully your actual program ends up containing something like:
Code: [Select]
   TIMER1_ENA = 1;or
Code: [Select]
   lda #1
   sta TIMER1_ENA
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Code: [Select]
#include <functional>
#include <type_traits>

template<typename BASE>
constexpr bool _isOneOf_f()
{
    return false;
}

template<typename BASE, typename TEST, typename... TYPES>
constexpr bool _isOneOf_f()
{
    return std::is_same<BASE, TEST>::value || _isOneOf_f<BASE, TYPES...>();
}

template<typename BASE, typename... TYPES>
constexpr bool isOneOf = _isOneOf_f<BASE, TYPES...>();


template<typename V1>
constexpr auto _biggestValue_f(const V1 v1)
{
    return v1;
}

template<typename V1, typename... TYPES>
constexpr auto _biggestValue_f(const V1 v1, const TYPES... others)
{
    return std::max(v1, _biggestValue_f(others...));
}

template<typename... TYPES>
constexpr auto biggestTypeSize = _biggestValue_f(sizeof(TYPES)...);



template<typename TOSEARCH>
constexpr int _findTypeIndex_f(const int indexSoFar)
{
    return -1;
}

template<typename TOSEARCH, typename TEST, typename... TYPES>
constexpr int _findTypeIndex_f(const int indexSoFar)
{
    if(std::is_same<TOSEARCH, TEST>::value)
        return indexSoFar;
    else
        return _findTypeIndex_f<TOSEARCH, TYPES...>(indexSoFar + 1);
}

template<typename TOSEARCH, typename... TYPES>
constexpr int findTypeIndex = _findTypeIndex_f<TOSEARCH, TYPES...>(0);



template<typename RETTYPE, typename... ERRORTYPES>
class Except
{
    private:
        char values[biggestTypeSize<RETTYPE, ERRORTYPES...>];
        int whichIsIt = 0;


    public:

        template<
            typename TYPE,
            typename = std::enable_if_t< isOneOf<TYPE, RETTYPE, ERRORTYPES...> >
        >
        Except(TYPE value)
            : whichIsIt{ findTypeIndex<TYPE, RETTYPE, ERRORTYPES...> }
        {
            TYPE *ptr = reinterpret_cast<TYPE*>(&this->values[0]);
            *ptr = value;
        }


        template<
            typename ERRT,
            typename = std::enable_if_t< isOneOf<ERRT, ERRORTYPES...> >
        >
        Except<RETTYPE, ERRORTYPES...> & when(const std::function<void(const ERRT &)> & callback)
        {
            if(findTypeIndex<ERRT, RETTYPE, ERRORTYPES...> == whichIsIt)
                callback(*reinterpret_cast<ERRT*>(&this->values[0]));
            return *this;
        }


        void ok(const std::function<void(const RETTYPE &)> & callback)
        {
            if(whichIsIt == 0)
                callback(*reinterpret_cast<RETTYPE*>(&this->values[0]));
        }
};


above the attempt of handing exceptions-like
with "exceptions disabled" flag, which sounds
like impossible mission, and the arrangement
of words & phrases in C++11 seems designed
to cause headache  :palm: :palm: :palm: :palm:

 

Offline John Coloccia

  • Super Contributor
  • ***
  • Posts: 1212
  • Country: us
Code: [Select]
#include <functional>
#include <type_traits>

template<typename BASE>
constexpr bool _isOneOf_f()
{
    return false;
}

template<typename BASE, typename TEST, typename... TYPES>
constexpr bool _isOneOf_f()
{
    return std::is_same<BASE, TEST>::value || _isOneOf_f<BASE, TYPES...>();
}

template<typename BASE, typename... TYPES>
constexpr bool isOneOf = _isOneOf_f<BASE, TYPES...>();


template<typename V1>
constexpr auto _biggestValue_f(const V1 v1)
{
    return v1;
}

template<typename V1, typename... TYPES>
constexpr auto _biggestValue_f(const V1 v1, const TYPES... others)
{
    return std::max(v1, _biggestValue_f(others...));
}

template<typename... TYPES>
constexpr auto biggestTypeSize = _biggestValue_f(sizeof(TYPES)...);



template<typename TOSEARCH>
constexpr int _findTypeIndex_f(const int indexSoFar)
{
    return -1;
}

template<typename TOSEARCH, typename TEST, typename... TYPES>
constexpr int _findTypeIndex_f(const int indexSoFar)
{
    if(std::is_same<TOSEARCH, TEST>::value)
        return indexSoFar;
    else
        return _findTypeIndex_f<TOSEARCH, TYPES...>(indexSoFar + 1);
}

template<typename TOSEARCH, typename... TYPES>
constexpr int findTypeIndex = _findTypeIndex_f<TOSEARCH, TYPES...>(0);



template<typename RETTYPE, typename... ERRORTYPES>
class Except
{
    private:
        char values[biggestTypeSize<RETTYPE, ERRORTYPES...>];
        int whichIsIt = 0;


    public:

        template<
            typename TYPE,
            typename = std::enable_if_t< isOneOf<TYPE, RETTYPE, ERRORTYPES...> >
        >
        Except(TYPE value)
            : whichIsIt{ findTypeIndex<TYPE, RETTYPE, ERRORTYPES...> }
        {
            TYPE *ptr = reinterpret_cast<TYPE*>(&this->values[0]);
            *ptr = value;
        }


        template<
            typename ERRT,
            typename = std::enable_if_t< isOneOf<ERRT, ERRORTYPES...> >
        >
        Except<RETTYPE, ERRORTYPES...> & when(const std::function<void(const ERRT &)> & callback)
        {
            if(findTypeIndex<ERRT, RETTYPE, ERRORTYPES...> == whichIsIt)
                callback(*reinterpret_cast<ERRT*>(&this->values[0]));
            return *this;
        }


        void ok(const std::function<void(const RETTYPE &)> & callback)
        {
            if(whichIsIt == 0)
                callback(*reinterpret_cast<RETTYPE*>(&this->values[0]));
        }
};


above the attempt of handing exceptions-like
with "exceptions disabled" flag, which sounds
like impossible mission, and the arrangement
of words & phrases in C++11 seems designed
to cause headache  :palm: :palm: :palm: :palm:

It that from a new STL? Like I said before, I'm not a huge fan of the STL, though it's not particularly terrible for what it does. It's just a little bloated.

Anyhow, I'm not sure I really like C++11 either. I think it's trying to do too much. I like C++ as an object oriented extension to C, along with being a more strongly typed language. I like it for embedded and system level programming. IMHO, it misses the mark as a modern language. That's not to say you need a modern language, and C++ is just fine for quite a few things, but trying to turn it into a modern language just doesn't feel like it's working. The syntax and rules just get more and more complex and obfuscated. It's not insurmountable, but I feel like it's counterproductive.
 

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 19507
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Anyhow, I'm not sure I really like C++11 either. I think it's trying to do too much. I like C++ as an object oriented extension to C, along with being a more strongly typed language. I like it for embedded and system level programming. IMHO, it misses the mark as a modern language. That's not to say you need a modern language, and C++ is just fine for quite a few things, but trying to turn it into a modern language just doesn't feel like it's working. The syntax and rules just get more and more complex and obfuscated. It's not insurmountable, but I feel like it's counterproductive.

Yes indeed.

C++ tries to be both simple and close to the hardware, and also a high-level language - and fails at both. The give-away is how much you can't guarantee, because it is left as "implementation defined".
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline technix

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Anyhow, I'm not sure I really like C++11 either. I think it's trying to do too much. I like C++ as an object oriented extension to C, along with being a more strongly typed language. I like it for embedded and system level programming. IMHO, it misses the mark as a modern language. That's not to say you need a modern language, and C++ is just fine for quite a few things, but trying to turn it into a modern language just doesn't feel like it's working. The syntax and rules just get more and more complex and obfuscated. It's not insurmountable, but I feel like it's counterproductive.

Yes indeed.

C++ tries to be both simple and close to the hardware, and also a high-level language - and fails at both. The give-away is how much you can't guarantee, because it is left as "implementation defined".

That is why there is no unified C++11, rather than separate clang++11 or gnu++11 or msvc++11 or icc++11... (clang++11 and gnu++11 are fairly similar though, as clang try to be a drop-in replacement of GCC)
 

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 19507
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Anyhow, I'm not sure I really like C++11 either. I think it's trying to do too much. I like C++ as an object oriented extension to C, along with being a more strongly typed language. I like it for embedded and system level programming. IMHO, it misses the mark as a modern language. That's not to say you need a modern language, and C++ is just fine for quite a few things, but trying to turn it into a modern language just doesn't feel like it's working. The syntax and rules just get more and more complex and obfuscated. It's not insurmountable, but I feel like it's counterproductive.

Yes indeed.

C++ tries to be both simple and close to the hardware, and also a high-level language - and fails at both. The give-away is how much you can't guarantee, because it is left as "implementation defined".

That is why there is no unified C++11, rather than separate clang++11 or gnu++11 or msvc++11 or icc++11... (clang++11 and gnu++11 are fairly similar though, as clang try to be a drop-in replacement of GCC)

Plus why the behaviour of compiled code can (and does) change when the compiler version changes, and why the concept of a portable library is problematic.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Code: [Select]
std::mutex myMutex;


{
   std::lock_guard<std::mutex> guard(myMutex);

   //critical code
...
}
// lock_guard automatically unlocks the mutex


in my spare time I am designing my own language
actually it looks like "--C", but I am grabbing some
interesting feature from C++11, and I like "scopes"


I just need to (re)invent the wheel with a better
syntax  :-DD :-DD :-DD
 

Offline technix

  • Super Contributor
  • ***
  • Posts: 3507
  • Country: cn
  • From Shanghai With Love
    • My Untitled Blog
Code: [Select]
std::mutex myMutex;


{
   std::lock_guard<std::mutex> guard(myMutex);

   //critical code
...
}
// lock_guard automatically unlocks the mutex


in my spare time I am designing my own language
actually it looks like "--C", but I am grabbing some
interesting feature from C++11, and I like "scopes"


I just need to (re)invent the wheel with a better
syntax  :-DD :-DD :-DD

This is from Objective-C:
Code: [Select]
@synchronized (mutex_object)
{
    // ...
    [mutex_object canStillBeUsed:NORMALLY];
    // ...
}

The mutex_object can be any object, not just mutexes.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf