#include <stdio.h>
#include <string.h>

#include "cmsis_os.h"
#include "ImC/imc_api.h"
#include "stm32l5xx_hal.h"

extern ADC_HandleTypeDef ADC_HANDLER_SBC;

#define FRAM_MEM_SIZE (0x100000) // 1 MiB = 2 * 512 * 1024 bytes
#define MEM_TEST_ADDR (0x68000000U)
#define MEMORY_SIZE (FRAM_MEM_SIZE)

void fmc_expr()
{
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    DWT->CYCCNT = 0;
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_11, GPIO_PIN_SET);

    int counter = 0;

    int *fmc_base_addr = (void *)0x68000000;

    while(1) {
        // uint32_t tick = DWT->CYCCNT;

        // printf("%d %d %d\r\n", tick, correct, counter);

        register int errors = 0;
        register int expval = 0x55555555;
        register int tmpval = 0;
        register int count = MEMORY_SIZE / sizeof(int);

        volatile int *accs = (volatile int *)MEM_TEST_ADDR;
        for (int i = 0; i < count; i++, accs++, expval ^= 0xFFFFFFFF)
        {
            *accs = i;
            tmpval = *(accs + 1);
            if (*accs != i)
            {
                // printf("[%p] exp=%08X, act=%08X (NOT EQUAL!!!!!!!!)\r\n", accs, expval, *accs);
                // HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_11);
                errors++;
            }
            if (i % 500 == 0) {
                printf("%d %d %d\r\n", DWT->CYCCNT, errors, i);
            }
        }

        printf("-- %d errors occurred. (@%p)\r\n", errors, accs);
        printf("\r\n");
    }
}

void test_case_1_s4(int seq, unsigned int baseaddr, int length)
{
    register int errors = 0;
    register int expval = 0x55555555;
    register int tmpval = 0;
    register int count = length / sizeof(int);

    printf("\r\n");
    printf("==========================================\r\n");
    printf(" [%04d] TEST CASE #1 - S4\r\n", seq);
    printf("==========================================\r\n");

    volatile int *accs = (volatile int *)baseaddr;
    for (int i = 0; i < count; i++, accs++, expval ^= 0xFFFFFFFF)
    {
        *accs = expval;
        tmpval = *(accs + 1);
        if (*accs != expval)
        {
            printf("[%p] exp=%08X, act=%08X (NOT EQUAL!!!!!!!!)\r\n", accs, expval, *accs);
            errors++;
        }
    }

    printf("-- %d errors occurred. (@%p)\r\n", errors, accs);
    printf("\r\n");
}