0

I'm using the Atmel AVR ATmega328p chip, and I'm trying to create multiple ring buffers, with varying lengths, using the FifoBuffer class, in file fifobuffer.h, which I created...

class FifoBuffer {

    private:

    uint8_t buf_head;  // Head position, where next character is to be added
    uint8_t buf_tail;  // Tail position, when next character is to be removed
    uint8_t buf_size;  // Size of buffer in number of characters
    uint8_t *buffer;   // Declare buffer pointer

    public:

    FifoBuffer (uint8_t); // Constructor declaration

    uint8_t get () { return buffer[2]; }

    void put (uint8_t character) { }

    void empty () { }

    uint8_t count () { return 10; }

    uint8_t head () { return buf_head; }

    uint8_t tail () { return buf_tail; }

    uint8_t size () { return buf_size; }
};

// Constructor
//
FifoBuffer::FifoBuffer (uint8_t buffer_length) {
    buf_head   = 0;
    buf_tail   = 0;
    buf_size   = buffer_length;
    buffer     = new uint8_t [buffer_length];
    buffer[1] = 20; // Test
    buffer[2] = 16; // Test
    buffer[3] = 32; // Test
}

In my main.cpp file I have...

...

void *operator new(size_t s)     { return malloc(s); }
void *operator new[](size_t s)   { return malloc(s); }
void  operator delete(void *m)   { free(m); }
void  operator delete[](void *m) { free(m); }

#include "fifobuffer.h"

...

FifoBuffer tty_rx_buf(64);
FifoBuffer tty_tx_buf(64);

uint8_t ttt = tty_rx_buf.get();
show_8_bits (ttt, 'n');  
ttt = tty_rx_buf.size();
show_8_bits (ttt, 'n');  

...

Now everything complies, and the .get() returns 16, and .size() returns 64, which I would expect. But I observe that the size of the program (Program Memory Usage: 1194 bytes, Data Memory Usage: 11 bytes) does not change, whether I select a size of 64 or 10 for the ring buffer constructor calls. When I make only 1 ring buffer constructor call, memory use does change, to 1178 bytes, and 11 bytes, respectively.

I'm worried that the buffer = new uint8_t [buffer_length] line is not really allocating buffer_length bytes.

Is my concern warranted? Is there a better way to do this? Yes I am new at this.

jwhitney
  • 11
  • 4
  • What malloc is this calling? You don't get malloc by default when writing code for a microcontroller. Are you using a library that provides a malloc implementation? – Jacob Parker Mar 12 '13 at 18:54
  • `` has `malloc()` though often AVR programs are written without using without `malloc()` – angelatlarge Mar 12 '13 at 19:14
  • Yes the libraries I'm using are#include #include // ### test #include #include #include – jwhitney Mar 12 '13 at 19:17

1 Answers1

3

The reason you are not getting memory report "correctly" is that the compiler does not track memory allocated in malloc() calls: for example you might have code such as:

if (PINSB && 0x01) {
    myPtr = malloc(0x10);
}

What the above example illustrates is a malloc() call made or not made as a result of real-world conditions, such as voltage level on an input pin. The compiler doesn't know when/how malloc() and free() will be called, and as a result cannot track that memory. The only memory it does track is variables allocated on the stack, i.e. memory allocated without a malloc() call. To illustrate the contrast:

char dataA[10];   // Counted by compiler as memory
char* dataB = malloc(10); // Not counted by compiler except for the size of the pointer dataB itself.
angelatlarge
  • 4,086
  • 2
  • 19
  • 36
  • Wow @angelatlarge, thanks. Makes sense now. Then I'll have to keep track of what I use in my ring buffers, and add that to the memory size the compiler knows about. Since I only call the constructors once, at the beginning, and the ring buffers never change in size after they are first set, is there a better way to set up the ring buffer storage? – jwhitney Mar 12 '13 at 22:34
  • The buffer size you are wanting to use is not going to change on the fly, right? You set it once before/at compile time, and go with that, correct? – angelatlarge Mar 12 '13 at 22:38
  • Yes, @angelatlarge. I'll have 4 buffers, with 4 fixed sizes, but each different in size, set once at the start, and not changing on the fly. – jwhitney Mar 12 '13 at 22:53
  • 1
    Here's one thing you could do to allocated everything on the stack: allocate the buffer data array on the stack in `setup()` using `#define`s to specify buffer size, and then pass the pointer to that when constructing each `FifoBuffer`. It does break the encapsulation slightly, but you might decide that this is an OK price to pay. That will allow you to get rid of `new()` and `delete` operators, which I think you'd agree is a bit cludge-y. Plus you will know exactly how much precious SRAM your program takes up. What do you think? – angelatlarge Mar 12 '13 at 22:59