2019. 10. 16. 17:08ㆍ기타
제목이 너무 거창한가?
임알못(임베디드를 알지 못하는 인간)이 간단하게 테스트해 본 결과 돌아가길래 올려본다.
* 소스파일(2개)
1) [C#]HEX파일을 읽어서 바이너리로 변환후 시리얼로 전달하는 프로그램(BootloaderUpdator.zip)
(STM32가 구동되고 10초 안에 바이너리가 전달되어야 한다.
그렇지 않으면 업데이트 되지 않고 메인 루틴으로 이동한다.)
2) [STM32] 부트로더 프로그램(BootLoader.zip)
3) [STM32] 메인 프로그램(TestBinary.zip)
1. 대상 CPU : STM32F765ZI
2. 소프트웨어 종류
1) Before : Main S/W (0x8000000)
2) After : BootLoader S/W(0x8000000) + Main S/W(0x8010000)
3. STM32F765ZI_FLASH.ld 파일
1) Before
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
}
2) After
ㄱ) BootLoader
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
}
ㄴ) Main
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8010000, LENGTH = 1984K
}
4. 바이너리 파일 : 시리얼을 통하여 hex파일을 읽어서 바이너리로 변경후
$FILE,NNN,BBBBB\r\n
형식으로 전달한다.
> NNN : (가변크기)바이너리 크기
> BBBBB : (가변크기)메인 프로그램 바이너리
5. 부트로더 프로그램
1) 부트로더 프로그램에서 다음 루틴을 통해 Main 프로그램으로 전달 가능하다.
void GoToApplication()
{
// Get the application stack pointer (First entry in the application vector table)
uint32_t appStack = (uint32_t) *((__IO uint32_t*)APPLICATION_ADDRESS);
// Get the application entry point (Second entry in the application vector table)
pFunction appEntry = (pFunction) *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
// Reconfigure vector table offset register to watch the application bootloader
SCB->VTOR = APPLICATION_ADDRESS;
// Set the application stack pointer
__set_MSP(appStack);
appEntry();
// Infinite loop
while (1);
}
2) Main 프로그램 업데이트 순서
* 정의
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 32 Kbyte */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) /* Base @ of Sector 1, 32 Kbyte */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) /* Base @ of Sector 2, 32 Kbyte */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) /* Base @ of Sector 3, 32 Kbyte */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) /* Base @ of Sector 4, 128 Kbyte */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) /* Base @ of Sector 5, 256 Kbyte */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) /* Base @ of Sector 6, 256 Kbyte */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) /* Base @ of Sector 7, 256 Kbyte */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08100000) /* Base @ of Sector 8, 256 Kbyte */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x08140000) /* Base @ of Sector 9, 256 Kbyte */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x08180000) /* Base @ of Sector 10, 256 Kbyte */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x08C00000) /* Base @ of Sector 11, 256 Kbyte */
ㄱ) 플래쉬 Unlock
void FLASH_If_Init(void)
{
HAL_FLASH_Unlock();//HAL 드라이브에 포함된 함수
/* Clear pending flags (if any) */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR);
}
ㄴ) 플래쉬 Erase
uint32_t FLASH_If_Erase(uint32_t StartSector)
{
uint32_t UserStartSector;
uint32_t SectorError;
FLASH_EraseInitTypeDef pEraseInit;
UserStartSector = GetSector(APPLICATION_ADDRESS);
pEraseInit.TypeErase = TYPEERASE_SECTORS;
pEraseInit.Sector = UserStartSector;
/*
Main 소프트웨어가 쓰여지기 위해서 2개의 블록이 쓰여진다.
ADDR_FLASH_SECTOR_2, ADDR_FLASH_SECTOR_3
0x08010000~0x0801FFFF
*/
pEraseInit.NbSectors = 2;
pEraseInit.VoltageRange = VOLTAGE_RANGE_3;
if (HAL_FLASHEx_Erase(&pEraseInit, &SectorError) != HAL_OK)
{
/* Error occurred while page erase */
return (1);
}
return (0);
}
ㄷ) 플래쉬 Write
if (FLASH_If_Write(APPLICATION_ADDRESS, (uint32_t*) &UpdateFileBuffer[StartPos], (EndPos - StartPos) / 4) == FLASHIF_OK)
{
//Success
}
//
uint32_t FLASH_If_Write(uint32_t FlashAddress, uint32_t* Data ,uint32_t DataLength)
{
uint32_t i = 0;
for (i = 0; (i < DataLength) && (FlashAddress <= (USER_FLASH_END_ADDRESS-4)); i++)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
if (HAL_FLASH_Program(TYPEPROGRAM_WORD, FlashAddress, *(uint32_t*)(Data+i)) == HAL_OK)
{
/* Check the written value */
if (*(uint32_t*)FlashAddress != *(uint32_t*)(Data+i))
{
/* Flash content doesn't match SRAM content */
return(FLASHIF_WRITINGCTRL_ERROR);
}
/* Increment FLASH destination address */
FlashAddress += 4;
}
else
{
/* Error occurred while writing data in Flash memory */
return (FLASHIF_WRITING_ERROR);
}
}
return (FLASHIF_OK);
}
ㄹ) 플래쉬 Lock
HAL_FLASH_Lock();
uint8_t Flash_If_DeInit(void)
{
/* Lock the internal flash */
HAL_FLASH_Lock();
return 0;
}
ㅁ) 메인 프로그램쪽으로 이동한다.
GoToApplication()
'기타' 카테고리의 다른 글
버추얼 박스(VirtualBox)에 설치된 Ubuntu에 USB2Serial 데이터 송수신 (0) | 2020.01.09 |
---|---|
AWS 리눅스 서버 구축시 필요한 명령어 이것저것 (0) | 2020.01.01 |
[C#] STM32 hex파일을 바이너리 데이터포 변경해서 byte array로 할당 루틴 (0) | 2019.10.01 |
패킷 전송 프로그램 (0) | 2019.05.20 |
C# tab control에 winform 넣기 (1) | 2019.04.20 |