/**
  ******************************************************************************
  * @file    main.c
  *
  * @brief   Пример выполнения операций с основной загрузочной флеш: чтение,
  *          запись, стирание.
  *
  *          Текущий контроллер не поддерживает работу с внутренней памятью из
  *          внутренней памяти, поэтому происходит переход в функцию,
  *          расположенную в ОЗУ, откуда и вызываются функции драйвера для
  *          записи и стирания.
  *
  *          В примере читаются и выводятся в терминал последовательно 4
  *          32-разрядных слова. Затем происходит запись новых данных.
  *          Обновленные данные считываются, а затем происходит стирание
  *          страницы с модифицированными адресами.
  *
  *          При компиляции будет выдаваться предупреждение:
  *          Warning: setting incorrect section attributes for .data.ramfunc
  *          Оно связано с примененным методом расположения функции в ОЗУ и его
  *          следует проигнорировать.
  *
  *          Для того чтобы функция из ОЗУ корректно вызывалась, компилятору был
  *          дополнительно передан ключ -mlong-calls.
  *
  *          Компилятор: GCC ARM 4.9.3
  *          Среда: Qt Creator 3.4.2
  *
  * @author  НИИЭТ
  *             - Богдан Колбов (bkolbov), kolbov@niiet.ru
  * @date    07.12.2015
  *
  ******************************************************************************
  * @attention
  *
  * ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО
  * ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ
  * ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ
  * НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ
  * ПРЕДНАЗНАЧЕНО ДЛЯ ОЗНАКОМИТЕЛЬНЫХ ЦЕЛЕЙ И НАПРАВЛЕНО ТОЛЬКО НА
  * ПРЕДОСТАВЛЕНИЕ ДОПОЛНИТЕЛЬНОЙ ИНФОРМАЦИИ О ПРОДУКТЕ, С ЦЕЛЬЮ СОХРАНИТЬ ВРЕМЯ
  * ПОТРЕБИТЕЛЮ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ
  * ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА ПРЯМОЙ ИЛИ КОСВЕННЫЙ УЩЕРБ, ИЛИ
  * ПО ИНЫМ ТРЕБОВАНИЯМ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
  * ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
  *
  * <h2><center>&copy; 2015 ОАО "НИИЭТ"</center></h2>
  ******************************************************************************
  */

#include "niietcm4.h"
#include "retarget.h"

void SystemInit()
{
    // инициализация printf
    retarget_init();

    BOOTFLASH_Init(EXT_OSC_VALUE);
}

uint32_t read_arr[4] = {0x11111111, 0x22222222, 0x33333333, 0x44444444};

int main()
{
    uint32_t addr = 0x00003010;

    // читаем значения до всех операций
    printf("Read flash before operation:\n");
    for (uint32_t i = 0; i < 4; i++)
    {
       printf("%d - 0x%x - 0x%x\n", i, addr + 0x4*i, *(volatile uint32_t*)(addr + 0x4*i));
    }

    // пишем значения
    printf("Performing write...\n");
    // Чтобы выполнять операции над флешкой, нужно перейти в ОЗУ.
    // Однако, прямой вызов функции не сработает, т.к. функция будет за пределами видимости
    // поэтому использован такой костыль.
    static void (*ram_bfwrite)(uint32_t, uint32_t,  uint32_t, uint32_t, uint32_t) = BOOTFLASH_Write;
    (*ram_bfwrite)(addr, 0xDEADF00D, 0xCAFEBABE, 0xBEEFBEEF, 0x79977997);
    //BOOTFLASH_Write(addr, 0xDEADF00D, 0xCAFEBABE, 0xBEEFBEEF, 0x79977997);

    // читаем и выводим новые значения
    printf("Write operation complete!\n");
    printf("Current values:\n");
    for (uint32_t i = 0; i < 4; i++)
    {
       printf("%d - 0x%x - 0x%x\n", i, addr + 0x4*i, *(volatile uint32_t*)(addr + 0x4*i));
    }

    // стираем страницу, куда писали
    printf("Performing page erase...\n");
    static void (*ram_bfpgerase)(uint32_t) = BOOTFLASH_PageErase;
    (*ram_bfpgerase)(addr/BOOTFLASH_PAGE_SIZE_BYTES);
    //BOOTFLASH_PageErase(addr/BOOTFLASH_PAGE_SIZE_BYTES);

    // читаем и выводим новые значения
    printf("Erase operation complete!\n");
    printf("Current values:\n");
    for (uint32_t i = 0; i < 4; i++)
    {
       printf("%d - 0x%x - 0x%x\n", i, addr + 0x4*i, *(volatile uint32_t*)(addr + 0x4*i));
    }

    printf("The end!\n");
    while(1);
}

