GY-63_MS5611/libraries/AvrHeap/avrheap.cpp

289 lines
5.8 KiB
C++
Raw Normal View History

2015-12-10 12:30:14 -05:00
//
2015-12-10 12:26:56 -05:00
// FILE: avrheap.cpp
// AUTHOR: Rob Tillaart
2024-04-09 03:21:57 -04:00
// VERSION: 0.2.7
// DATE: 2015-10-25
// PURPOSE: Experimental Arduino library to investigate the AVR heap Arduino UNO
2020-11-27 05:10:47 -05:00
// URL: https://github.com/RobTillaart/avrheap
2015-12-10 12:26:56 -05:00
//
2024-04-09 03:21:57 -04:00
// REFERENCES
// http://forum.arduino.cc/index.php?topic=27536.15
// http://forum.arduino.cc/index.php?topic=355660
2015-12-10 12:26:56 -05:00
2021-05-28 07:20:16 -04:00
2018-10-24 10:26:18 -04:00
#include "avrheap.h"
2015-12-10 12:26:56 -05:00
2021-05-28 07:20:16 -04:00
struct __freelist
{
2021-01-29 06:31:58 -05:00
size_t size;
struct __freelist *next;
2015-12-10 12:26:56 -05:00
};
2024-04-09 03:21:57 -04:00
extern struct __freelist *__flp;
extern uint16_t __heap_start;
extern uint16_t *__brkval;
extern char *__malloc_heap_start;
extern char *__malloc_heap_end;
extern size_t __malloc_margin;
extern uint16_t __data_start;
extern uint16_t __data_end;
extern uint16_t __bss_start;
extern uint16_t __bss_end;
size_t hNibble(Print& p, byte val)
{
2024-04-09 03:21:57 -04:00
return p.write(val + (val < 10 ? '0' : 'A' - 10));
}
2021-05-28 07:20:16 -04:00
size_t hByte(Print& p, byte val)
{
2021-01-29 06:31:58 -05:00
size_t len = hNibble(p, val >> 4);
return len + hNibble(p, val & 0x0F);
}
2021-05-28 07:20:16 -04:00
size_t hWord(Print& p, uint16_t val)
{
2021-01-29 06:31:58 -05:00
size_t len = hByte(p, (byte)(val >> 8));
return len + hByte(p, (byte)(val & 0xFF) );
}
2021-05-28 07:20:16 -04:00
size_t dumpR(Print& p, byte* adr, int len)
{
2021-01-29 06:31:58 -05:00
size_t glen = 0;
byte idx;
if (!len)
{
len = 16;
}
for (; len > 0; len -= 16, adr += 16)
{
glen += hWord(p, (uint16_t)adr);
glen += p.print(F(": "));
for (idx = 0; idx < 16; idx++)
{
2021-01-29 06:31:58 -05:00
if (idx < len )
{
glen += hByte(p, adr[idx]);
glen += p.write(' ');
} else {
glen += p.print(F(" "));
}
}
2021-01-29 06:31:58 -05:00
glen += p.write('\'');
for (idx = 0; (idx < 16) && (idx < len); idx++)
{
2021-01-29 06:31:58 -05:00
glen += p.write(adr[idx] < 0x20 ? '.' : adr[idx]);
}
2021-01-29 06:31:58 -05:00
glen += p.write('\'');
glen += p.println();
}
return glen;
}
2021-05-28 07:20:16 -04:00
size_t dumpAlloced(byte *ptr, bool withDump)
{
2021-01-29 06:31:58 -05:00
return dumpAlloced(Serial, ptr, withDump);
}
2021-05-28 07:20:16 -04:00
size_t dumpAlloced(Print& p, byte *ptr, bool withDump)
{
2021-01-29 06:31:58 -05:00
size_t len = hWord(p, (uint16_t)ptr);
if (!ptr)
{
len += p.println(F(": NULL"));
} else {
2024-04-09 03:21:57 -04:00
size_t size = *(size_t*)(ptr - sizeof(size_t));
2021-01-29 06:31:58 -05:00
if (size < __malloc_margin)
{
2021-01-29 06:31:58 -05:00
len += p.print(F(": size "));
len += p.println(size);
} else {
2021-01-29 06:31:58 -05:00
len += p.print(F(": invalid size "));
len += p.println(size);
size = 16;
}
2021-01-29 06:31:58 -05:00
if (withDump)
{
len += dumpR(p, ptr, size);
len += p.println();
}
}
return len;
}
2015-12-10 12:26:56 -05:00
2023-10-17 13:54:22 -04:00
//////////////////////////////////////////////////////
//
// AVRHEAP
//
Avrheap::Avrheap()
2015-12-10 12:26:56 -05:00
{
};
2021-05-28 07:20:16 -04:00
2015-12-10 12:26:56 -05:00
bool Avrheap::isFragmented()
{
2021-01-29 06:31:58 -05:00
return freeListCount() > 0;
2015-12-10 12:26:56 -05:00
};
2021-05-28 07:20:16 -04:00
2015-12-10 12:26:56 -05:00
uint16_t Avrheap::freeListCount()
{
2021-01-29 06:31:58 -05:00
uint16_t count = 0;
for (struct __freelist* p = __flp; p; p = p->next) count++;
return count;
2015-12-10 12:26:56 -05:00
}
2021-05-28 07:20:16 -04:00
2015-12-10 12:26:56 -05:00
uint16_t Avrheap::freeListSize()
{
2021-01-29 06:31:58 -05:00
uint16_t total = 0;
for (struct __freelist* p = __flp; p; p = p->next)
{
total += 2; // malloc size
total += (uint16_t) p->size;
}
return total;
2015-12-10 12:26:56 -05:00
}
2021-05-28 07:20:16 -04:00
void Avrheap::freeListWalk(bool withDump)
2015-12-10 12:26:56 -05:00
{
2021-01-29 06:31:58 -05:00
int elements = freeListCount();
Serial.print(F("\nFreeList: "));
Serial.print(isFragmented() ? F("fragmented") : F("clean"));
Serial.print(F(", count "));
Serial.print(elements);
Serial.print(F(", largest "));
Serial.print(freeListLargest());
Serial.print(F(", total size "));
Serial.println(freeListSize());
Serial.println();
if (elements)
{
for (struct __freelist* p = __flp; p; p = p->next)
2015-12-10 12:26:56 -05:00
{
2021-01-29 06:31:58 -05:00
hWord(Serial, (uint16_t)p);
Serial.print(F(": size "));
Serial.print((uint16_t)p->size);
Serial.print(F(" next "));
hWord(Serial, (uint16_t)p->next);
Serial.println();
if (withDump)
{
2024-04-09 03:21:57 -04:00
dumpR(Serial, ((byte*)p) + 2, p->size);
2021-01-29 06:31:58 -05:00
Serial.println();
}
2015-12-10 12:26:56 -05:00
}
2021-01-29 06:31:58 -05:00
}
2015-12-10 12:26:56 -05:00
}
2021-05-28 07:20:16 -04:00
2015-12-10 12:30:14 -05:00
uint16_t Avrheap::startAddress()
{
2021-01-29 06:31:58 -05:00
return (uint16_t) &__heap_start;
2015-12-10 12:30:14 -05:00
}
2021-05-28 07:20:16 -04:00
void Avrheap::dumpHeap(uint16_t count)
2015-12-10 12:30:14 -05:00
{
2021-01-29 06:31:58 -05:00
hWord(Serial, (uint16_t)RAMEND);
Serial.println(F(" RAMEND"));
hWord(Serial, (uint16_t)SP);
Serial.println(F(" SP"));
hWord(Serial, (uint16_t)__brkval);
Serial.println(F(" __brkval"));
hWord(Serial, (uint16_t)__malloc_heap_end);
Serial.println(F(" __malloc_heap_end"));
hWord(Serial, (uint16_t)__malloc_heap_start);
Serial.println(F(" __malloc_heap_start"));
hWord(Serial, (uint16_t)&__heap_start);
Serial.println(F(" __heap_start"));
hWord(Serial, (uint16_t)&__bss_end);
Serial.println(F(" __bss_end"));
hWord(Serial, (uint16_t)&__bss_start);
Serial.println(F(" __bss_start"));
hWord(Serial, (uint16_t)&__data_end);
Serial.println(F(" __data_end"));
hWord(Serial, (uint16_t)&__data_start);
Serial.println(F(" __data_start"));
hWord(Serial, (uint16_t)__malloc_margin);
Serial.println(F(" __malloc_margin"));
Serial.println();
Serial.println(F("start of heap"));
Serial.println();
dumpR(Serial, (byte*)startAddress(), count);
}
2021-05-28 07:20:16 -04:00
size_t Avrheap::heapWalk(bool withDump) {
2021-01-29 06:31:58 -05:00
return heapWalk(Serial, withDump);
2015-12-10 12:30:14 -05:00
}
2021-05-28 07:20:16 -04:00
2024-04-09 03:21:57 -04:00
// EXPERIMENTAL
size_t Avrheap::heapWalk(Print& pr, bool withDump) const
{
2021-01-29 06:31:58 -05:00
byte* p = (byte*) &__heap_start;
struct __freelist* fp = __flp;
2021-01-29 06:31:58 -05:00
size_t len = pr.println(F("Heap\n"));
while ((int)p < (int)__brkval)
{
2023-10-17 13:54:22 -04:00
len += hWord(pr, (uint16_t)p); // p+2 ?
2021-01-29 06:31:58 -05:00
len += pr.write(' ');
len += pr.print(*p, DEC);
if ( (fp != NULL) && ((uint16_t)p == (uint16_t)fp))
{
2021-01-29 06:31:58 -05:00
len += pr.print(F(" (free)"));
fp = fp->next;
}
len += pr.println();
if (withDump) {
2024-04-09 03:21:57 -04:00
len += dumpR(pr, p, *p + 2);
2021-01-29 06:31:58 -05:00
len += pr.println();
}
2024-04-09 03:21:57 -04:00
p += (byte) * p + 2;
2021-01-29 06:31:58 -05:00
}
return len;
}
2015-12-10 12:26:56 -05:00
2021-05-28 07:20:16 -04:00
bool Avrheap::inFreeList(uint16_t addr)
{
2021-01-29 06:31:58 -05:00
for (struct __freelist* p = __flp; p; p = p->next)
{
if (addr == (uint16_t)p) return true;
}
return false;
}
2021-05-28 07:20:16 -04:00
uint16_t Avrheap::freeListLargest()
{
2021-01-29 06:31:58 -05:00
uint16_t largest = 0;
for (struct __freelist* p = __flp; p; p = p->next)
{
largest = max(largest, (uint16_t) p->size);
}
return largest;
}
2015-12-10 12:26:56 -05:00
2021-05-28 07:20:16 -04:00
size_t Avrheap::printTo(Print& p) const
{
2021-01-29 06:31:58 -05:00
size_t len = heapWalk(p, true);
return len;
}
2021-05-28 07:20:16 -04:00
2023-10-17 13:54:22 -04:00
// --- END OF FILE ---