#include <stdio.h>
#include <stdlib.h>

#include "pico/stdlib.h"

int global;
int globalInit = 0;

int main() {
    extern int __end__;
    extern int __HeapLimit;
    extern int __bss_start__;
    extern int __bss_end__;
    extern int __stack;
    extern int __StackLimit;

    const char const * constString = "  Test #2: Address of a constant string: 0x%08X\n";
    int uninitialized;
    int initialized = 0;

    volatile int stackPointer;
    volatile int *heapPointer;


    stdio_init_all();
    printf("Raspberry Pi Pico Address Map Exploration - Exercise 8\n");
    printf("------------------------------------------------------------------------------\n");
    printf("The Pi Pico datasheet indicates that External Flash starts at 0x10000000\n");
    printf("We would thus expect all .text and .data to exist close to this address.\n");
    printf("  Test #1: Address of main():            0x%08X\n", (uint32_t) &main);
    printf(constString, constString);
    printf("------------------------------------------------------------------------------\n");
    printf("The Pi Pico datasheet indicates that SRAM starts at 0x20000000\n");
    printf("We would thus expect all .bss, heap and stack to exist close to this address.\n");
    printf("Checking initialized and uninitialized global variables:\n");
    printf("  Test #3: Uninitialized global:    0x%08X\n", (uint32_t) &global);
    printf("  Test #4: Initialized global:      0x%08X\n", (uint32_t) &globalInit);
    printf("These should exist within the bss range. The Pi Pico build system defines two\n");
    printf("variables indicating where the bss starts and ends: __bss_start__ and __bss_end__.\n");
    printf("  Test #5: bss start:               0x%08X\n", (uint32_t) &__bss_start__);
    printf("  Test #6: bss end:                 0x%08X\n", (uint32_t) &__bss_end__);
    printf("  Test #7: bss size:                %lu Bytes\n", (uint32_t) &__bss_end__ - (uint32_t) &__bss_start__);
    printf("------------------------------------------------------------------------------\n");
    printf("The Pi Pico build system defines two variables indicating where the heap\n");
    printf("starts and ends: __end__ and __HeapLimit.\n");
    printf("  Test #8: Heap start:              0x%08X\n", (uint32_t) &__end__);
    printf("  Test #9: Heap end:                0x%08X\n", (uint32_t) &__HeapLimit);
    printf("  Test #10: heap size:              %lu Bytes\n", (uint32_t) &__HeapLimit - (uint32_t) &__end__);
    
    heapPointer = malloc(1);
    printf("  Test #10.5: Heap pointer malloc'd:             0x%08X \n", (uint32_t) heapPointer);

    printf("As expected, the heap start matches the bss end.\n");
    printf("------------------------------------------------------------------------------\n");
    printf("Checking initialized and uninitialized variables (on the stack):\n");
    printf("  Test #11: Uninitialized variable: 0x%08X\n", (uint32_t) &uninitialized);
    printf("  Test #12: Initialized variable:   0x%08X\n", (uint32_t) &initialized);
    printf("These should exist within the stack range. The Pi Pico build system defines two\n");
    printf("variables indicating where the stack starts and ends: __stack and __StackLimit.\n");
    printf("  Test #13: Stack start:            0x%08X\n", (uint32_t) &__StackLimit);
    printf("  Test #14: Stack end:              0x%08X\n", (uint32_t) &__stack);
    printf("  Test #15: Stack size:             %lu Bytes\n", (uint32_t) &__stack - (uint32_t) &__StackLimit);
    printf("The stack pointer can be accessed from the ARM r13 register with a little fiddling:\n");



    asm volatile ("mov %0, r13;" : "=r"(stackPointer));

    printf("  Test #16: Stack pointer:          0x%08X\n", (uint32_t) stackPointer);
    printf("------------------------------------------------------------------------------\n");

    // Do nothing
    while (true) {
        sleep_ms(1000);
    }
}
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT