AnsweredAssumed Answered

STM32 bootloader form SD card

Question asked by Rosenbaum.Piotr on Aug 21, 2015
Latest reply on Aug 24, 2015 by Rosenbaum.Piotr
Hello !
I have a problem with my bootloader form SD card. I think i try everything, now i don't have any ideas. App in sd card have changed memory start address to 0x08002000 and memory size to 0x0003E000. Can someone look for it and help ? Microcontroller is : STM32F107VC. Thanks !

#include <board_led.h>
#include <util_delay.h>
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_flash.h"
#include "ff.h"
#include "diskio.h"
#include "init_spi.h"
#include <stdio.h>
 
 
#define DEF_APP_ADDRESS           0x8002000
 
 
#define FLASH_KEY1               ((u32)0x45670123)
#define FLASH_KEY2               ((u32)0xCDEF89AB)
 
#define CR_LOCK_Set              ((u32)0x00000080)
 
#define EraseTimeout             ((u32)0x00000FFF)
 
#define CR_PER_Set               ((u32)0x00000002)
#define CR_PER_Reset             ((u32)0x00001FFD)
 
#define CR_STRT_Set              ((u32)0x00000040)
 
#define ProgramTimeout           ((u32)0x0000000F)
 
 
#define CR_PG_Set                ((u32)0x00000001)
#define CR_PG_Reset              ((u32)0x00001FFE)
 
 
void FlashUnlock(void);
void FlashLock(void);
uint32_t FlashErasePage(uint32_t page_address);
uint32_t FlashWritePage(uint32_t page_address, const uint8_t *chunk, uint32_t chunk_len);
 
void switch_to_main_app(void);
uint8_t is_app_correct(void);
 
FATFS FatFs;   /* Work area (file system object) for logical drive */
 
uint16_t page_piece = 0;
uint32_t address_shift = 0;
 
int main(void) {
 
 
    static const unsigned delay_time = 80000;
    LEDconfigure();
    init_spi();
    RedLEDon();
    GreenLEDoff();
 
 
    FIL     file;
    FRESULT fresult;
    UINT len;
    static BYTE buffer[256];
 
 
    fresult = f_mount(&FatFs, "", 0);
    if(fresult == FR_OK)
        fresult = f_open(&file,"update.bin", FA_OPEN_EXISTING | FA_READ);       // Sprawdzenie czy jest plik z programem
 
    // Warunku uruchomienia bootloadera
        if((fresult == FR_OK) || !is_app_correct()) {
            FlashUnlock();
            do {
 
                if(!page_piece){
 
                    if (FlashErasePage(DEF_APP_ADDRESS + address_shift))
                        break;
                }
                fresult = f_read(&file,buffer,256,&len);
                if(fresult == FR_OK)
                    GreenLEDon();
                else
                    GreenLEDoff();
                if(fresult != FR_OK)
                    break;
                if (FlashWritePage(DEF_APP_ADDRESS + address_shift,(uint8_t *)buffer,(uint32_t)len))
                    break;
 
                address_shift += len;
 
                page_piece++;
 
                if((page_piece << 8) == 1024) {
                    page_piece = 0;
                }
 
            }while(len == 256);
 
            FlashLock();
 
            fresult = f_close(&file);
 
            }
            switch_to_main_app();
 
 
 
    while(1) {
    RedLEDon();
    Delay(delay_time);
    RedLEDoff();
    Delay(delay_time);
  }
}
 
 
void switch_to_main_app(void) {
 
 
    typedef  void (*function_ptr)(void);
 
    function_ptr firmware;
 
    uint32_t addr = 0x08002000;
 
    //__set_PRIMASK(1); //wylaczenie przerwan
    //SysTick->CTRL = 0;
    //SysTick->LOAD = 0;
    //SysTick->VAL = 0;
 
    __set_MSP(*(uint32_t*)addr);
 
    __set_PSP(*(uint32_t*)addr); //ta linia nie jest konieczna
 
    __set_CONTROL(0);
 
    SCB->VTOR = (volatile uint32_t)(0x08002000);    // set vector table
 
    const uint32_t firmware_entry = *(volatile uint32_t*)(0x08002000 + 4);
 
    firmware = (function_ptr)(firmware_entry);
 
    (*firmware)();  // jump to firmware
}
 
 
uint8_t is_app_correct(void) {
    uint32_t *app_vector_isr;
    app_vector_isr = (uint32_t *)DEF_APP_ADDRESS;
 
    // app seems to be incorrect
    if ((app_vector_isr[0] == 0xffffffff) || (app_vector_isr[0] == 0x0) ||
        (app_vector_isr[1] == 0xffffffff) || (app_vector_isr[1] == 0x0))
    {
        return(0);
    }
    return(1);
}
 
 
 
 
void FlashUnlock(void) {
 
    /* Authorize the FPEC Access */
    FLASH->KEYR = FLASH_KEY1;
    FLASH->KEYR = FLASH_KEY2;
}
 
 
 
void FlashLock(void)  {
 
    /* Set the Lock Bit to lock the FPEC and the FCR */
    FLASH->CR |= CR_LOCK_Set;
}
 
 
 
 
uint32_t FlashErasePage(uint32_t page_address)  {
 
    FLASH_Status status;
 
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(EraseTimeout);
 
    if (status == FLASH_COMPLETE)
    {
      /* if the previous operation is completed, proceed to erase the page */
      FLASH->CR|= CR_PER_Set;
      FLASH->AR = page_address;
      FLASH->CR|= CR_STRT_Set;
 
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastOperation(EraseTimeout);
 
      if (status != FLASH_BUSY)
      {
        /* if the erase operation is completed, disable the PER Bit */
        FLASH->CR &= CR_PER_Reset;
      }
    }
    /* Return the Erase Status */
    return (status != FLASH_COMPLETE);
}
 
 
 
uint32_t FlashWritePage(uint32_t page_address, const uint8_t *chunk, uint32_t chunk_len)  {
 
    FLASH_Status status;
    volatile uint16_t *wr_addr;
    uint16_t *data;
    uint32_t data_len;
 
    wr_addr = (volatile uint16_t*)page_address;
    data = (uint16_t*)chunk;
    data_len = chunk_len / 2U;
 
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(ProgramTimeout);
 
    if (status == FLASH_COMPLETE)
    {
        /* if the previous operation is completed, proceed to program the new data */
        FLASH->CR |= CR_PG_Set;
    }
 
    while (data_len)
    {
        *wr_addr = *data;
        /* Wait for last operation to be completed */
        status = FLASH_WaitForLastOperation(ProgramTimeout);
 
        if (status == FLASH_COMPLETE)
        {
            if (*wr_addr != *data)
            {
                status = FLASH_ERROR_WRP;
                break;
            }
            data++;
            wr_addr++;
            data_len--;
        }
        else
        {
            break;
        }
    }
 
    if (status != FLASH_BUSY)
    {
        /* if the program operation is completed, disable the PG Bit */
        FLASH->CR &= CR_PG_Reset;
    }
 
    return (status != FLASH_COMPLETE);
}

Outcomes