Another interesting use of placement new

Rick Kimball
Sun Jun 07, 2015 3:59 pm
In another thread, I had made brief mention of using placement new to delay the constructor call of an object. However, it isn’t really limited to that type of thing. Placement new has a lot more to tap into. It is commonly used to provide access methods to registers at a fixed location.

Take the GPIO registers for instance, a placement new approach could provide a zero overhead API to these registers and provide methods that abstract away some of the register’s unfriendliness. In the code below, I created a simple GPIOPort C++ class that maps the address of the registers of the GPIOB to a class that can use those registers. I created a couple of methods that let you set a pin high() or low() with zero code overhead. * the other methods are left as an exercise to the reader *

Maple Mini code * assumes PB1 is the led and it is active high *
// placement_new_blink - thin API to direct use of GPIO registers

inline void * operator new( size_t sz, void * here ) { return here;}

class GPIOPort : public gpio_reg_map {
public:
void high(const uint32_t pin_mask) { BSRR = pin_mask; }
void low(const uint32_t pin_mask) { BRR = pin_mask; }
};

static GPIOPort & portb = *(new ((void *)GPIOB_BASE) GPIOPort());

#define LED_MASK 1<<1

void setup() {
pinMode(PB1, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
portb.high(LED_MASK); // turn on led
delay(100); // wait
portb.low(LED_MASK); // turn on led
delay(900); // wait
}


Rick Kimball
Sun Jun 07, 2015 4:30 pm
Before anyone beats me up with a comment like, “You don’t need to use placement new to accomplish that, you can just set the address of the portb to GPIOB” and yes this is true:

* code without placement new *
// zero overhead API for register based manipulation
class GPIOPort : public gpio_reg_map {
public:
void high(const uint32_t pin) { BSRR = 1 << pin; }
void low(const uint32_t pin) { BRR = 1 << pin; }
};
static GPIOPort & portb = *((GPIOPort *)GPIOB_BASE);

#define LED_PORT_PIN PB1
#define LED_PIN 1 /* PB1 */

void setup() {
pinMode(LED_PORT_PIN, OUTPUT);
}

void loop() {
portb.high(LED_PIN); // turn on led
delay(100); // wait
portb.low(LED_PIN); // turn on led
delay(400); // wait
}


mrburnette
Sun Jun 07, 2015 5:03 pm
You never know, something like this might come in handy if you need to eliminate some of the Arduino’s API overhead. Of course, you have to weigh that gain against the fact that you are writing chip specific code that won’t be able to be used any place else.

Since we know the chip flavor at compile time, can this knowledge not be used to normalise with alias (typedef) through a little bit of #ifdef magic?

Ray


Rick Kimball
Sun Jun 07, 2015 6:33 pm
mrburnette wrote:Since we know the chip flavor at compile time, can this knowledge not be used to normalise with alias (typedef) through a little bit of #ifdef magic?Ray

mrburnette
Sun Jun 07, 2015 9:06 pm
However, there are times when I’d like the code to be more efficient speed wise than what the Arduino API provides.

A noble goal…
I think all of us want both flexibility (pin ss variable) and speed (pin mapped directly to port.) It is a shame that these seem to be mutually exclusive.


You must have been looking at my fabooh c++ template framework. ]

No, but I am a big fan of your work; esp. the BMP effort. As summer progresses and the wife’s to-do list becomes shorter, I hope to sacrifice a Mini to the BMP role… I had 30, gave 1 to an old friend who just had to have one (immediate gratification personality), and have 4 allocated to various on-bench projects… I have no problem tossing a virgin down the volcano as a sacrifice for the greater good.

Ray


victor_pv
Mon Jun 08, 2015 12:45 am
Rick, is then there an advantage for the pin manipulation by using placement new?
You comment that without it, the code is better, but I would like to understand why. The main different I noticed is that it saves a few bytes, but I see both cases avoid calling digitalwrite, and all that digitalWrite calls by itself…

Rick Kimball
Mon Jun 08, 2015 1:42 am
The big advantage would be that the constructor would be called. Although in this example I’m not doing anything with the constructor. With the pointer solution, you would have to create a init function and call it in setup, or at the point it makes sense.

-rick


mrburnette
Mon Jun 08, 2015 2:49 am
Rick Kimball wrote:The big advantage would be that the constructor would be called. Although in this example I’m not doing anything with the constructor. With the pointer solution, you would have to create a init function and call it in setup, or at the point it makes sense.

-rick


Rick Kimball
Mon Jun 08, 2015 3:52 am
mrburnette wrote:Does this mean that the pointer-based object is in the heap? Or, does the Harvard architecture force the compiler to put that into flash?

mrburnette
Mon Jun 08, 2015 12:19 pm
If you were writing this yourself in asm…
… not since college and 68000 and 6502 later on.

But, I do understand your explanation and it is helpful. Up until AVR, I had not worked with little chips and assembler since college in the mid-70’s. And with AVR, mostly only digging around in V-USB. I was fair at 6502 stuff back in my Apple II days, but never fancy enough to do anything other than xmodem stuff and a few helper routines for Applesoft. But everything was von Neumann – my comfort zone with Harvard is a bit shaky.

But; I am grateful for the explanation (makes sense) and I certainly am glad this forum have a bit-head on the team! Take care of your neurons, you’re a valuable asset.

Ray


victor_pv
Mon Jun 08, 2015 2:57 pm
mrburnette wrote:If you were writing this yourself in asm…
… I had not worked with little chips and assembler since college in the mid-70’s…
Ray

mrburnette
Mon Jun 08, 2015 3:22 pm
victor_pv wrote:mrburnette wrote:If you were writing this yourself in asm…
… I had not worked with little chips and assembler since college in the mid-70’s…
Ray

ahull
Mon Jun 08, 2015 7:54 pm
Just in case you were wondering (and I’m sure you were not ;) ) I think I must be pretty much the same vintage as Ray, one of the first computers I did any serious developing on was this “Portable” beast, which was, I suspect Philips “Osbourne 1 wanabe..” It also had Wordstar, Supercalc and C, Pascal and Basic compilers.
Image
Portable meant that you could lug it (puffing and wheezing) in and out of a Taxi, and use it as a seat on the train. :D

The spec is here. and I wrote a bunch of stuff including a print spooler and barcode printing utility (for hospital case notes). If you needed “speed” and “graphics”, that involved a lot of head scratching to talk to the “co-processor” and terminal board directly. I suspect one of these STM32F103C8XX chips would eat it for breakfast.


Rick Kimball
Mon Jun 08, 2015 8:01 pm
Man this place is full of old men. “GET OFF MY LAWN!” : )

* Sadly, I fall into this same vintage as all the other old guys.

-rick


ahull
Mon Jun 08, 2015 8:19 pm
I might have to change my avatar.
Image

martinayotte
Mon Jun 08, 2015 10:59 pm
Rick Kimball wrote:Man this place is full of old men.

madias
Tue Jun 09, 2015 10:23 am
Haha, I like this thread!
So I think with 41 years I’m a “youngster” here ;)
BTW: I dreamt about this “portable” (but it wasn’t affordable for me in 1000 light years) :
Image
(ok, this was 20 years later than the machines you posted, but – I think – equal if not more powerful than any STM32F1xx)
(( and yes, I was “ATARI” not commodore, because I needed MIDI))

mrburnette
Tue Jun 09, 2015 12:44 pm
The entire last shelf of IBM/Compaq stuff has been donated but all the old Apple stuff remains in my little closet museum in my old office.
2 Apple ][ with disk drives, all of the original Macintosh ( I added the last one after the pic was taken – so, all the monochrome units) and the CPM machine can just be seen in the right edge. The IIGS Woz edition has been donated.
The P.E.T. is in a different room. Somewhere on the server is a nice pix… but obviously not indexed!

Ray

IMG_0282.JPG
IMG_0282.JPG (52.32 KiB) Viewed 631 times

Leave a Reply

Your email address will not be published. Required fields are marked *