ããŒãããŒããŒã¯äŸ¿å©ã§äŸ¿å©ã§ããã ãŸããããŒããŒãç¬èªã®å®è£ ã§ããå Žåã¯ãããã«äŸ¿å©ã§äŸ¿å©ã§æè»æ§ã
ãŸããããã¯ã䜿çšããŠããã³ã³ãã¥ãŒã¿ãŒïŒãã®å Žåã¯ãARM Cortex-M3ã³ã¢ãåããSTM32ãã€ã¯ãã³ã³ãããŒã©ãŒïŒã®æ©èœãããã«æ·±ãæãäžããŠèª¿æ»ãã絶奜ã®æ©äŒã§ãã
å®éãããŒãããŒããŒã¯äžèŠãããšæããããããç°¡åã§ãã 蚌æ ãšããŠãç§ãã¡ã¯ç¬èªã®USB倧容éã¹ãã¬ãŒãžããŒãããŒããŒãçµã¿ç«ãŠãŸãïŒ
ãã€ã¯ãã³ã³ãããŒã©ïŒä»¥äžãMKïŒ STM32F103RETã§èªå®¶è£œã®ãã¶ãŒããŒãã䜿çšããŸãã äžèŠãªåçã§åºçç©ããã£ã±ãã«ããªãããã«ããã®éçã®åãæšãŠå³ã瀺ããŸãã
ããŒãããŒããŒãäœæãããšããç§ã¯æ¬¡ã®ååã«å°ãããŸããã
- ããŒãããŒããŒã¯éåžžã«å¿ èŠã§ãããTODOãªã¹ãã§ããã延æããã®ã«ååã§ãã座ã£ãŠå®è¡ããæéã§ãã
- ããŒãããŒããŒã«ã¯ããŠãŒã¶ãŒãã¬ã³ããªãŒãªããã°ã©ã èªã¿èŸŒã¿ã€ã³ã¿ãŒãã§ã€ã¹ãå¿ èŠã§ãã ãã©ã€ããŒããµãŒãããŒãã£ããã°ã©ã ãã¢ããã¿ãŒããŒãããŸãã¯ã¿ãŒã²ããããã€ã¹ãžã®MGTFããŒãã¹ã¯ãããŸããã èªåæ€åºãããUSBãã©ãã·ã¥ãã©ã€ããããç°¡åãªãã®ã¯äœã§ããïŒ
- ããŒãããŒããŒã¢ãŒãã§åäœããã«ã¯ããã€ã¯ãã³ã³ãããŒã©ãŒã«æå°éã®ããŒããŠã§ã¢ïŒå®éã«ã¯ãUSBãã¯ã©ãŒãããã¿ã³ã®ã¿ïŒãå¿ èŠã§ãã
- ããŒãã®ãµã€ãºã¯ãã€ã³ãã§ã¯ãããŸããã ãã¡ããéèŠã§ãããæ°ãããã€ãã«å§çž®ãããšããç®æšãè¿œæ±ããŸããã è¯å¿ã®çã¿ãªãã«ãUSBã¹ã¿ãã¯ãäžãããã¡ã€ã«ã·ã¹ãã ãæäœãã printfïŒïŒãè¡ã«è²Œãä»ããŠãéåžžã¯äœãæåŠããŸããïŒhelloã Standard Peripheral Libraries ïŒïŒã
é転ãã
ãã©ãã·ã¥ã«ã€ããŠå°ã
STM32ãã©ãã·ã¥ã¡ã¢ãªãåžžã«é »ç¹ã«äœ¿çšããããããã®äºå®ã«é¢é£ããéèŠãªç¹ãããã«èª¬æãã䟡å€ããããŸãã
䜿çšæžã¿ã®MKã«ã¯512 Kãã€ãã®ãã©ãã·ã¥ã¡ã¢ãªãå«ãŸããŠããŸãã 2048ãã€ãã®ããŒãžã«åå²ãããŸãã
ç§ãã¡ã«ãšã£ãŠãããã¯ãä»»æã®ã¢ãã¬ã¹ã«ã»ãã®æ°ãã€ããæžã蟌ãã ãã§ã¯æ©èœããªãããšãæå³ããŸãã FLASHã«æžã蟌ãå Žåãå¿ èŠãªã»ã«ã®ã¿ããŒãã«ããããšãã§ããŸãããåäœã®èšå®ã¯æ¶å»æäœã䜿çšããŠå®è¡ããããã®æå°å¯èœããªã¥ãŒã ã¯1ããŒãžã§ãã ãããè¡ãã«ã¯ã FLASH_ARã¬ãžã¹ã¿ã䜿çšããŸãããã®ã¬ãžã¹ã¿ã§ã¯ãå¿ èŠãªããŒãžå ã®ä»»æã®ã¢ãã¬ã¹ãæžã蟌ãã ãã§ååã§ããã0xFFãã€ãã§åããããŸãã ãŸããæ¶å»/æžã蟌ã¿æäœã®åã«ããã©ãã·ã¥ã®ããã¯ã解é€ããããšãå¿ããªãã§ãã ããã
FLASHãããã€ãã®é åã«ä»®æ³çã«åå²ããŸããåé åã«ã¯ããããåºæã®ç®çããããŸãã
- BOOT_MEM-ããŒãããŒããŒã«å²ãåœãŠãããã¡ã¢ãªé åã
- USER_MEM-ããã«ãŠãŒã¶ãŒãã¡ãŒã ãŠã§ã¢ãä¿åïŒããã³ããããå®è¡ïŒããŸãã æããã«ãçŸåšã¯200 Kãã€ãã®å¶éããããŸãã
- MSD_MEM-ã³ã³ãã¥ãŒã¿ãŒãšãæ°ã«å ¥ãã®OSã䜿çšããŠãã¡ãŒã ãŠã§ã¢ãããããã§ãã倧容éèšæ¶ãã£ã¹ã¯ããããŸãã
- OTHER_MEM-念ã®ãããããã«ã¹ããŒã¹ã空ããŸãããã
USER_MEMã¯ããµã€ãºãMSD_MEMãšäžèŽããŸãã ããã¯è«ççã§ãããªããªã 2ã€ã®æ£å察ã®å Žåã¯ã USER_MEMã®ã¡ã¢ãªäžè¶³ãŸãã¯éå°ãäžããŸãã
ãããŠä»ããã¹ãŠã¯åãã§ããããã·ã³ïŒããã³ããã°ã©ããŒã®å©äŸ¿æ§ïŒã®ã¿ã§ãã
#define FLASH_PAGE_SIZE 2048 //2 Kbyte per page #define FLASH_START_ADDR 0x08000000 //Origin #define FLASH_MAX_SIZE 0x00080000 //Max FLASH size - 512 Kbyte #define FLASH_END_ADDR (FLASH_START_ADDR + FLASH_MAX_SIZE) //FLASH end address #define FLASH_BOOT_START_ADDR (FLASH_START_ADDR) //Bootloader start address #define FLASH_BOOT_SIZE 0x00010000 //64 Kbyte for bootloader #define FLASH_USER_START_ADDR (FLASH_BOOT_START_ADDR + FLASH_BOOT_SIZE) //User application start address #define FLASH_USER_SIZE 0x00032000 //200 Kbyte for user application #define FLASH_MSD_START_ADDR (FLASH_USER_START_ADDR + FLASH_USER_SIZE) //USB MSD start address #define FLASH_MSD_SIZE 0x00032000 //200 Kbyte for USB MASS Storage #define FLASH_OTHER_START_ADDR (FLASH_MSD_START_ADDR + FLASH_MSD_SIZE) //Other free memory start address #define FLASH_OTHER_SIZE (FLASH_END_ADDR - FLASH_OTHER_START_ADDR) //Free memory size
ã¡ã¢ãªãé åã«åå²ããããšã«åæããããä»åºŠã¯ããããã¹ãŠãã©ã®ããã«çžäºäœçšããããç解ããæãæ¥ãŸããã ãããã¯ç·å³ãæããŸãããïŒ
ãã®ã¢ã«ãŽãªãºã ã«ãããšãããŒãããŒããŒã«ã¯ãäºãã«ç¬ç«ããŠåäœãã2ã€ã®ã¡ã€ã³ã¢ãŒãããããŸãããå ±éã®ãªãœãŒã¹ïŒ MSD_MEMã¡ã¢ãªã®äžéšïŒããããŸãã ãã ãããã®äœ¿çšã¯ããŸããŸãªæç¹ã§çºçãããããããŒãããŒããŒã®å®å®æ§ã«ãã©ã¹ã®åœ±é¿ãäžããããã°ã©ãã³ã°ããã³ãããã°ããã»ã¹ãç°¡çŽ åããŸãã
- æåã®ã¢ãŒãã¯ãå€éšãã©ã€ããšããŠå©çšå¯èœãªMSD_MEMé åã§ãŠãŒã¶ãŒãœãããŠã§ã¢ãåä¿¡ããã³ä¿åãã圹å²ãæãããŸãã
- 2çªç®ã®ã¢ãŒãã§ã¯ã MSD_MEMã§ãAPP.BINããšããååã®ãã¡ã€ã«ãååšãããã©ããããã§ãã¯ãããã®æŽåæ§ãä¿¡é Œæ§ããã§ãã¯ããŸãããŸãã空ãŸãã¯ãã¡ãŒã ãŠã§ã¢ãAPP.BINããããæ°ããå Žåã¯USER_MEMã«ç§»åããŸãã
åã¢ãŒããããã«è©³ããæ€èšããŸãã
USB倧容éããã€ã¹
察å¿ããéå§æ¡ä»¶ãæºããããå Žåã ã¡ã€ã³ïŒïŒãå ¥åããçŽåŸã«éå§ããŸã-ãã¿ã³ãã¯ã©ã³ããããŸãã ç§ã®ããŒãã§ã¯ãããã¯ãªã³/ãªãã¹ã€ããã®äžéšã®ã¹ã©ã€ããŒã§ãïŒã¡ãªã¿ã«ãMK BOOT0ããã³BOOT1ïŒPB2ïŒã®èã«å·»ãä»ããããŠããŸããããã«ãããå¿ èŠã«å¿ããŠããŒããŠã§ã¢UARTããŒããŒMKã䜿çšã§ããŸãïŒã
int mainïŒvoidïŒ
int main(void) { Button_Config(); if(GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN) == SET) //Bootloader or Mass Storage? { LED_RGB_Config(); USB_Config(); Interrupts_Config(); USB_Init(); while(TRUE); } //Bootloader mode }
倧容éèšæ¶ã¢ãŒãã§ã®äœæ¥ã¯ãSTMicroelectronicsïŒ STM32_USB-FS-Device_Lib_V4.0.0 ïŒã®äŸããåãããŠãããWebãµã€ãããããŠã³ããŒãã§ããŸãã ããã§ã¯ãUSB MSDã¢ãŒãã§SDIOãä»ããŠæ¥ç¶ããããã€ã¯ãã³ã³ãããŒã©ãŒãšã¡ã¢ãªã«ãŒãã䜿çšããããšãã©ã®ããã«å¿ èŠã§ãããïŒãŸãã¯ãã®éãå¿ èŠã§ã¯ãªã-STããã®ã©ã€ãã©ãªãŒã«å¯Ÿããæ 床ãåžžã«ååãã§ã¯ãªãïŒã瀺ããŠããŸãã ãã®äŸã§ã¯ã64ãã€ãã®ãã±ããé·ãæã€2ã€ã®ãã«ã¯ã€ã³/ã¢ãŠããšã³ããã€ã³ããšãSCSIãæ©èœããããã«å¿ èŠãªäžé£ã®ã³ãã³ããå®è£ ããŠããŸãã ããããSDã«ãŒããŸãã¯NANDã¡ã¢ãªïŒmass_mal.c / .hïŒã«é¢é£ä»ããããé¢æ°ãç Žæ£ããå éšãã©ãã·ã¥ã«çœ®ãæããŸãïŒ
u16 MAL_InitïŒu8 lunïŒ
u16 MAL_Init(u8 lun) { switch (lun) { case 0: FLASH_Unlock(); break; default: return MAL_FAIL; } return MAL_OK; }
u16 MAL_ReadïŒu8 lunãu32 memOffsetãu32 * readBuffïŒ
u16 MAL_Read(u8 lun, u32 memOffset, u32 *readBuff) { u32 i; switch (lun) { case 0: LED_RGB_EnableOne(LED_GREEN); for(i = 0; i < MassBlockSize[0]; i += SIZE_OF_U32) { readBuff[i / SIZE_OF_U32] = *((volatile u32*)(FLASH_MSD_START_ADDR + memOffset + i)); } LED_RGB_DisableOne(LED_GREEN); break; default: return MAL_FAIL; } return MAL_OK; }
u16 MAL_WriteïŒu8 lunãu32 memOffsetãu32 * writeBuffïŒ
u16 MAL_Write(u8 lun, u32 memOffset, u32 *writeBuff) { u32 i; switch (lun) { case 0: LED_RGB_EnableOne(LED_RED); while(FLASH_GetStatus() != FLASH_COMPLETE); FLASH_ErasePage(FLASH_MSD_START_ADDR + memOffset); for(i = 0; i < MassBlockSize[0]; i += SIZE_OF_U32) { while(FLASH_GetStatus() != FLASH_COMPLETE); FLASH_ProgramWord(FLASH_MSD_START_ADDR + memOffset + i, writeBuff[i / SIZE_OF_U32]); } LED_RGB_DisableOne(LED_RED); break; default: return MAL_FAIL; } return MAL_OK; }
æ¥ç¶ããã¹ãŠæ£ããè¡ããããšãã³ã³ãã¥ãŒã¿ãŒã¯è£œåãUSB倧容éèšæ¶è£ 眮ãšããŠèå¥ãããã©ãŒãããããããã«ææ¡ããŸãã ãã¿ã¯MSD_MEMé åã«ãããŸãã ãã®åäœã¢ãŒãã§ã¯ãMKã¯ãã¹ããšFLASHã¡ã¢ãªã®éã®åãªã仲ä»è ã§ããããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã©ã€ãäžã«ã©ã®ããŒã¿ãšã©ã®ã¢ãã¬ã¹ã眮ãããç¬èªã«æ±ºå®ããããšã«æ³šæããŠãã ããã
ãã£ã¹ã¯ããã©ãŒããããããããMSD_MEMé åã«ã©ã®ããã«åœ±é¿ãããã確èªããŸãã
ããªã¥ãŒã ã¯åãã§ãWindowsã»ã¯ã¿ãŒã®ãµã€ãºã¯æ£ãããšå€æããããŒãã»ã¯ã¿ãŒã¯èµ·åå¯èœã§ãã¡ã¢ãªå ã®å Žæã¯èšç»ã«å¯Ÿå¿ããŠããŸãã ãã¡ã€ã«ã¯æžã蟌ãŸããèªã¿åãããåé»åŸãæ¶ããŸãã-200 Kãã€ãã®ãã«ãã©ãã·ã¥ãã©ã€ãïŒ
ããŒãããŒããŒ
ãã¡ãŒã ãŠã§ã¢ã®æŽæ°ãäžèŠãªå Žåã«éå§ããŸãã ã€ãŸããããã€ã¹ã®éåžžã®åäœã§ãã ãã®äžã§ããŠãŒã¶ãŒãœãããŠã§ã¢ãæ£åžžã«èµ·åããããã«å¿ èŠãªããã€ãã®åºæ¬çãªã¢ã¯ã·ã§ã³ãå®è¡ããå¿ èŠããããŸãã åºæ¬-å¿ èŠã«å¿ããŠãæå·åãæŽåæ§ãã§ãã¯ããããã°ã¡ãã»ãŒãžã®åºåãªã©ãããããçš®é¡ã®æ©èœã䜿çšããŠããŒãããŒããŒã®äœæ¥ãè£å®ã§ãããã
Windowsã䜿çšããŠUSBãã©ã€ãäžã®ãã¡ã€ã«ã·ã¹ãã ãæ¢ã«äœæããå¿ èŠãªãœãããŠã§ã¢ãããŠã³ããŒããããšããŸãã ããã§ãMKã®ç®ã§ã¡ãã£ã¢ã®å 容ãèŠãããšãã§ããã°ããããã§ããã€ãŸãã FatFS ïŒãã€ã¯ãã³ã³ãããŒã©äžã®å°ããªçµã¿èŸŒã¿ã·ã¹ãã çšã«èšèšãããã·ã³ãã«ãªFATãã¡ã€ã«ã·ã¹ãã ã¢ãžã¥ãŒã«ïŒã®Comrade ChaNã«ã¢ã¯ã»ã¹ããŸãã ããŠã³ããŒãããŠãããžã§ã¯ãã«ãããããããã£ã¹ã¯ããå¿ èŠãªããŒã¿ãèªã¿åãæ©èœãåŠæ¹ããŸãã
DRESULT disk_readïŒBYTE pdrvãBYTE * buffãDWORDã»ã¯ã¿ãŒãUINTã«ãŠã³ãïŒ
DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address in LBA */ UINT count /* Number of sectors to read */ ) { u32 i; for(i = 0; i < count * SECTOR_SIZE; i++) { buff[i] = *((volatile u8*)(FLASH_MSD_START_ADDR + sector * SECTOR_SIZE + i)); } return RES_OK; }
disk_writeïŒïŒã¯äžèŠã§ããããŠã³ãããããã¡ã€ã«ã·ã¹ãã ã¯èªã¿åãå°çšã§ãããããã¹ã¿ãã®ãŸãŸã§ãã ããã¯ã ffconf.hæ§æãã¡ã€ã«ã§èšå®ããããšãã§ããäžèŠãªæ©èœãæªäœ¿çšã®æ©èœããã¹ãŠç¡å¹ã«ããŸãã
ãã®åŸããã¹ãŠãå€ããå°ãªããæããã§ãïŒãã¡ã€ã«ã·ã¹ãã ãããŠã³ããããã¡ãŒã ãŠã§ã¢ãã¡ã€ã«ãéããèªã¿å§ããŸãã æåã¯ããã¡ãŒã ãŠã§ã¢ã®ã¡ã€ã³ã¹ãã¬ãŒãžã®å ŽæãMSD_MEMã«ãªãããã«å®è£ ãããŠããããã€ã¯ãã³ã³ãããŒã©ãŒã¯ãªã³ã«ãªããã³ã«ãã©ãã·ã¥ã¡ã¢ãªãäžæžãããŸãã ãã¡ãŒã ãŠã§ã¢ã®äžåšããã³whileïŒTRUEïŒã«é¢ãããããã°ã¡ãã»ãŒãžã¯ãããŸããã ãã¡ãŒã ãŠã§ã¢ããããŸã-USER_MEMã«ã¹ããŒããŸã ã ãã ãããã®ãããªãœãªã¥ãŒã·ã§ã³ã®æãããªãã€ãã¹ç¹ã¯ããã©ãã·ã¥ã¡ã¢ãªã®æ¶å»/æžã蟌ã¿ãªãœãŒã¹ã«å¶éãããã補åãåŸã ã«æèçã«æ®ºãã®ã¯æãã§ããããšã§ãã
ãããã£ãŠã ãAPP.BINããšUSER_MEMãããã€ãããšã«æãã«æ¯èŒããŠãã ããã ããããã2ã€ã®é åã®ããã·ã¥åãæ¯èŒããããšã¯ããããšã¬ã¬ã³ããªãœãªã¥ãŒã·ã§ã³ã®ããã«èŠããŸããã確ãã«æéã§ã¯ãããŸããã mainïŒïŒãããäžåºŠèŠãŠã¿ãŸãããïŒ
int mainïŒvoidïŒ
int main(void) { Button_Config(); if(GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN) == SET) //Bootloader or Mass Storage? { //USB MSD mode } FATFS_Status = f_mount(&FATFS_Obj, "0", 1); if(FATFS_Status == FR_OK) { FILE_Status = f_open(&appFile, "/APP.BIN", FA_READ); if(FILE_Status == FR_OK) { appSize = f_size(&appFile); for(i = 0; i < appSize; i++) //Byte-to-byte compare files in MSD_MEM and USER_MEM { f_read(&appFile, &appBuffer, 1, &readBytes); if(*((volatile u8*)(FLASH_USER_START_ADDR + i)) != appBuffer[0]) { //if byte of USER_MEM != byte of MSD_MEM break; } } if(i != appSize)//=> was done "break" instruction in for(;;) cycle => new firmware in MSD_FLASH { CopyAppToUserMemory(); } FILE_Status = f_close(&appFile); FATFS_Status = f_mount(NULL, "0", 1); PeriphDeInit(); GoToUserApp(); } else //if FILE_Status != FR_OK { if(FILE_Status == FR_NO_FILE) { //No file error } else //if FILE_Status != FR_NO_FILE { //Other error } FATFS_Status = f_mount(NULL, "0", 1); while(TRUE); } } else //FATFS_Status != FR_OK { //FatFS mount error while(TRUE); } }
æ¯èŒäžã«ãµã€ã¯ã«ã®æåŸã«å°éããªãã£ãå Žåããã¡ãŒã ãŠã§ã¢ã¯ç°ãªãã CopyAppToUserMemoryïŒïŒã䜿çšããŠUSER_MEMãæŽæ°ããŸãã ããã§ã¯ã PeriphDeInitïŒïŒãåŒã³åºããŠããGoToUserAppïŒïŒãåŒã³åºããŠãããŒãããŒããŒã®ãã¬ãŒã¹ãç Žæ£ãããšããã§ãããã ããããããã¯å°ãåŸã§ãããä»ã®ãšãã-ã³ããŒããã»ã¹ïŒ
void CopyAppToUserMemoryïŒvoidïŒ
void CopyAppToUserMemory(void) { f_lseek(&appFile, 0); //Go to the fist position of file appTailSize = appSize % APP_BLOCK_TRANSFER_SIZE; appBodySize = appSize - appTailSize; appAddrPointer = 0; for(i = 0; i < ((appSize / FLASH_PAGE_SIZE) + 1); i++) //Erase n + 1 pages for new application { while(FLASH_GetStatus() != FLASH_COMPLETE); FLASH_ErasePage(FLASH_USER_START_ADDR + i * FLASH_PAGE_SIZE); } for(i = 0; i < appBodySize; i += APP_BLOCK_TRANSFER_SIZE) { /* * For example, size of File1 = 1030 bytes * File1 = 2 * 512 bytes + 6 bytes * "body" = 2 * 512, "tail" = 6 * Let's write "body" and "tail" to MCU FLASH byte after byte with 512-byte blocks */ f_read(&appFile, appBuffer, APP_BLOCK_TRANSFER_SIZE, &readBytes); //Read 512 byte from file for(j = 0; j < APP_BLOCK_TRANSFER_SIZE; j += SIZE_OF_U32) //write 512 byte to FLASH { while(FLASH_GetStatus() != FLASH_COMPLETE); FLASH_ProgramWord(FLASH_USER_START_ADDR + i + j, *((volatile u32*)(appBuffer + j))); } appAddrPointer += APP_BLOCK_TRANSFER_SIZE; //pointer to current position in FLASH for write } f_read(&appFile, appBuffer, appTailSize, &readBytes); //Read "tail" that < 512 bytes from file while((appTailSize % SIZE_OF_U32) != 0) //if appTailSize MOD 4 != 0 (seems not possible, but still...) { appTailSize++; //increase the tail to a multiple of 4 appBuffer[appTailSize - 1] = 0xFF; //and put 0xFF in this tail place } for(i = 0; i < appTailSize; i += SIZE_OF_U32) //write "tail" to FLASH { while(FLASH_GetStatus() != FLASH_COMPLETE); FLASH_ProgramWord(FLASH_USER_START_ADDR + appAddrPointer + i, *((volatile u32*)(appBuffer + i))); } }
512ãã€ãã®ãããã¯ã§ã³ããŒããŸãã 512-ãããã¡ãµã€ãºããã®å€ããã倧ãããšã f_readïŒïŒãåãããšãã§ããå ŽæãèŠãããã§ãã ç§ã¯ãã®ç¹ããã§ãã¯ããŸãã-ãã¹ãŠããã倧ããªãããã¡ãŒã§ç§ã®ããã«åããã ãããã念ã®ããã圌ã¯512ãæ®ããŸãã-ã©ãããŠã§ããïŒ RAMãç¯çŽããé床ã«åœ±é¿ãäžããŸãããããã«ã1åã ãå®è¡ãããŸããããã€ã¹ã®é»æºãå ¥ããç¬éã«ããã¡ãŒã ãŠã§ã¢ãæŽæ°ãããšãã ãã§ãã
ãŸãããã©ãã·ã¥ã¡ã¢ãªå ã®ãã¡ã€ã«ã®å Žæãæ¶å»ããŸãã æ¶å»ãããé åã®ãµã€ãºã¯ã ãAPP.BINããå®å šã«å æããã¡ã¢ãªå ã®ããŒãžæ°+ãã1ã€ïŒæºæ¯ã§ã¯ãªãïŒã«çãããªããŸãã ãŸããäºå®äžããbodyããšãtailãã§ãã¡ãŒã ãŠã§ã¢ãã¡ã€ã«ãç ŽããŸãããããã§ããbodyãã¯ãã¡ã€ã«ã®æ倧å¯èœéšåã§ããã512ãã€ãã®æŽæ°ãããã¯ãšãtailã-ãã®ä»ãã¹ãŠã§ãã
ãã¹ãŠã®ãã€ããªãã¡ãŒã ãŠã§ã¢ãã¡ã€ã«ã¯4ãã€ãã®åæ°ã§ããããã§ãã ç§ã¯ããã確å®ã«ïŒãããŠãŸã ïŒç¢ºä¿¡ããŠããªãã£ãã®ã§ã念ã®ãã-ãã¡ãŒã ãŠã§ã¢ãsizeofïŒu32ïŒã®åæ°ã§ãªãå Žå-0xFFãã€ãã§è£å®ããŸãã ç¹°ãè¿ããŸãããããã¯å®è¡ããå¿ èŠã¯ãªãããã§ãããè€æ°ã®sizeofïŒu32ïŒãã€ããªã«å¯ŸããŠæäœã¯ç¡å®³ã§ããããããã®ãŸãŸã«ããŸãã
ããã«ã¡ã¯ãUser ApplicationïŒ
ããããã PeriphDeInitïŒïŒé¢æ°ã§äœ¿çšããããã¹ãŠã®åšèŸºæ©åšã®åæåã解é€ããŸãïŒã»ãšãã©äœããããŸãã-ã¢ãŒããã¿ã³ã®GPIOãããã³å¿ èŠã«å¿ããŠãããã°ã¡ãã»ãŒãžãåºåããUARTãå²ã蟌ã¿ã¯äœ¿çšãããŸããïŒã
ããŒãããŒããŒã®æçµçãªã©ã€ãã¹ããŒãžã¯ãã«ã¹ã¿ã ãã¡ãŒã ãŠã§ã¢ã®å®è¡ã®éå§ã§ãã
void GoToUserAppïŒvoidïŒ
void GoToUserApp(void) { u32 appJumpAddress; void (*GoToApp)(void); appJumpAddress = *((volatile u32*)(FLASH_USER_START_ADDR + 4)); GoToApp = (void (*)(void))appJumpAddress; SCB->VTOR = FLASH_USER_START_ADDR; __set_MSP(*((volatile u32*) FLASH_USER_START_ADDR)); //stack pointer (to RAM) for USER app in this address GoToApp(); }
ããã5è¡ã§ãããã©ããããç¶ããŠããŸããïŒ
ARM Cortex M3ã«ãŒãã«ã§ã¯ãäŸå€ãçºçãããšã察å¿ãããã³ãã©ãŒãåŒã³åºãããŸãã äŸå€ãã³ãã©ã®éå§ã¢ãã¬ã¹ã決å®ããããã«ããã¯ã¿ãŒããŒãã«ã¡ã«ããºã ã䜿çšãããŸãã ãã¯ã¿ããŒãã«ã¯ãã·ã¹ãã ã¡ã¢ãªå ã®ããŒã¿ã¯ãŒãã®é åã§ãããããã1çš®é¡ã®äŸå€ã®éå§ã¢ãã¬ã¹ã§ãã ããŒãã«ã¯ç§»åå¯èœã§ãããSCBïŒã·ã¹ãã ã³ã³ãããŒã«ãããã¯ïŒã®ç¹å¥ãªVTORã¬ãžã¹ã¿ãŒã«ãã£ãŠç§»åãå¶åŸ¡ãããŸãïŒããã¥ã¢ã«ã§ã¯æ¶ŒããèãããŸãããå£ããŸããïŒ ãã¯ã¿ãŒããŒãã«ã¯åé 眮å¯èœã§ãåé 眮ã¯NVICã®åé 眮ã¬ãžã¹ã¿ãŒã«ãã£ãŠå¶åŸ¡ãããŸãïŒã RESETåŸããã®ã¬ãžã¹ã¿ã®å€ã¯0ã§ããã€ãŸãããã¯ã¿ãŒããŒãã«ã¯0x0ã«ãããŸãïŒã¹ã¿ãŒãã¢ãããã¡ã€ã«ã®STM32F103ã®å Žåãæ¢ã«0x08000000ã«ç§»åããŠããŸãïŒã ãããŠãããã¯ç§ãã¡ã«ãšã£ãŠéåžžã«éèŠã§ããããã«ããé åºã¯æ¬¡ã®ãšããã§ãã
- 0x04ã®å€ã¯ã ãªã»ããäŸå€ã®åŸã«ååŸããããã°ã©ã å ã®å Žæã§ãã
- 0x00ã®å€ã¯ããŠãŒã¶ãŒã¢ããªã±ãŒã·ã§ã³ã®åæã¡ã€ã³ã¹ã¿ãã¯ãã€ã³ã¿ãŒå€ã§ãã
ããããã¹ãŠãåãããŠãæ©èœãžã®ãã€ã³ã¿ã䜿çšããéæ³ãè¿œå ãããšãã¢ãªã¹ã¯ãŠãµã®ã®åŸã«ãžã£ã³ãããŸãã
次ã«ãããããŸã£ããæ©èœãããã©ããã確èªããŸãããã mainïŒïŒã®ãµã€ã¯ã«ãšããã€ãã®å²ã蟌ã¿ïŒSysTickãšTIM4ïŒã䜿çšããŠãLEDãç¹æ» ãããç°¡åãªããã°ã©ã ãäœæããŠã¿ãŸãããã
MSDããŒãããŒããŒã®ãã¹ãããã°ã©ã
#include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #include "stm32f10x_tim.h" #include "misc.h" #define SYSCLK_FREQ 72000000 #define TICK_1_KHz ((SYSCLK_FREQ / 1000) - 1) #define TICK_1_MHz ((SYSCLK_FREQ / 1000000) - 1) volatile u32 i, j; int main(void) { GPIO_InitTypeDef GPIO_Options; NVIC_InitTypeDef NVIC_Options; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); GPIO_Options.GPIO_Pin = GPIO_Pin_7; GPIO_Options.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Options.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_Options); GPIO_Options.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_Options.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Options.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_Options); GPIOB->BSRR = GPIO_Pin_0 | GPIO_Pin_1; //LEDs off GPIOA->BSRR = GPIO_Pin_7 TIM4->PSC = 720 - 1; //clock prescaller TIM4->ARR = 60000 - 1; //auto-reload value TIM4->CR1 |= TIM_CounterMode_Up;//upcounter TIM4->DIER |= TIM_IT_Update; //update interrupt enable TIM4->CR1 |= TIM_CR1_CEN; //timer start NVIC_Options.NVIC_IRQChannel = TIM4_IRQn; NVIC_Options.NVIC_IRQChannelPreemptionPriority = 0; NVIC_Options.NVIC_IRQChannelSubPriority = 0; NVIC_Options.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_Options); SysTick_Config(TICK_1_KHz); while(1) { __disable_irq(); GPIOB->BSRR = GPIO_Pin_0 | GPIO_Pin_1; //Off for(i = 0; i < 10; i++) { for(j = 0; j < 500000; j++); //Pause GPIOA->ODR ^= GPIO_Pin_7; //Reverse } GPIOA->BSRR = GPIO_Pin_7; //Off __enable_irq(); for(i = 0; i < 5000000; i++); //Pause } } void SysTick_Handler(void) { volatile static u32 LED_Counter = 0; if(LED_Counter >= 40) { GPIOB->ODR ^= GPIO_Pin_1; //Reverse LED_Counter = 0; } LED_Counter++; } void TIM4_IRQHandler() { TIM4->SR = ~TIM_SR_UIF; GPIOB->ODR ^= GPIO_Pin_0; //Reverse }
ãšããã§ããããžã§ã¯ãå ã®ããã€ãã®åé¡ãä¿®æ£ããããšãå¿ããŠã¯ãªããŸããã
- SystemInitïŒïŒãããäœããã®å€ïŒ // SCB-> VTOR = FLASH_BASE ïŒã§ãã¯ã¿ãŒããŒãã«ã移åããæäœãåé€ããŸãã ããŒãããŒããŒã¯ãŠãŒã¶ãŒããã°ã©ã ã«ç§»åããåã«èªåã§ç§»åããŸãïŒ
- ãªã³ã«ãŒã¹ã¯ãªããã§ãããã°ã©ã ã®éå§ãã¢ãã¬ã¹0x08000000ããéå§ã¢ãã¬ã¹USER_MEM ïŒ FLASHïŒrxïŒïŒORIGIN = 0x08010000ãLENGTH = 200K ïŒã«å€æŽããŸãã
ãããŠããã®ã³ãŒããå®è¡ãããŸãïŒLEDãç¹æ» ããã®ã誰ããèŠãªããããããŸãã...ïŒïŒ
ããŒãããŒããŒãä»ããMKã§ã®ãã®ãã¡ãŒã ãŠã§ã¢ã®ããŒããã°ã¯æ¬¡ã®ãšããã§ãã
UARTãã°ã¡ãã»ãŒãž
---------------ãã°ãéå§---------------
BOOT_MEMéå§ã¢ãã¬ã¹ïŒ0x08000000
BOOT_MEMãµã€ãºïŒ64K
USER_MEMéå§ã¢ãã¬ã¹ïŒ0x08010000
USER_MEMãµã€ãºïŒ200K
MSD_MEMéå§ã¢ãã¬ã¹ïŒ0x08042000
MSD_MEMãµã€ãºïŒ200K
OTHER_MEMéå§ã¢ãã¬ã¹ïŒ0x08074000
OTHER_MEMãµã€ãºïŒ48K
åèšã¡ã¢ãªãµã€ãºïŒ512K
ããŒãããŒããŒã¢ãŒã...
FAT FSããŠã³ãã¹ããŒã¿ã¹= 0
ã¢ããªã±ãŒã·ã§ã³ãã¡ã€ã«ã®ãªãŒãã³ã¹ããŒã¿ã¹= 0
MSD_MEMãšUSER_MEMã®éãïŒ2212ãã€ããã4ãã€ã
MSD_MEMã®USER_MEMãžã®ã³ããŒãéå§ããŸãã
ãã¡ã€ã«ãµã€ãº= 2212ãã€ã
æ¬äœãµã€ãº= 2048ãã€ã
ããŒã«ãµã€ãº= 164ãã€ã
ã»ã¯ã¿ãŒ0ïŒ0x08010000-0x08010800ïŒãæ¶å»ãããŸãã
ã»ã¯ã¿ãŒ1ïŒ0x08010800-0x08011000ïŒãæ¶å»ãããŸãã
0ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ã ïŒ0x08010000-0x08010200
1ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ãã³ã°ïŒ0x08010200-0x08010400
2ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ã ïŒ0x08010400-0x08010600
3ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ã ïŒ0x08010600-0x08010800
ããŒã«ã®èªã¿åãïŒèªã¿åãã¹ããŒã¿ã¹= 0ãèªã¿åã164ãã€ããããŒã«ã®ãµã€ãº= 164
ããŒã«ã®æ°ãããµã€ãº= 164
164ãã€ãã®ããã°ã©ãã³ã°ïŒ0x08010800-0x080108A4
ãã¡ã€ã«ã®ã¯ããŒãºç¶æ = 0
FAT FSã¢ã³ããŠã³ãã¹ããŒã¿ã¹= 0
åšèŸºæ©åšã®åæåã解é€ããŠ0x08010561ã«ãžã£ã³ã...
BOOT_MEMéå§ã¢ãã¬ã¹ïŒ0x08000000
BOOT_MEMãµã€ãºïŒ64K
USER_MEMéå§ã¢ãã¬ã¹ïŒ0x08010000
USER_MEMãµã€ãºïŒ200K
MSD_MEMéå§ã¢ãã¬ã¹ïŒ0x08042000
MSD_MEMãµã€ãºïŒ200K
OTHER_MEMéå§ã¢ãã¬ã¹ïŒ0x08074000
OTHER_MEMãµã€ãºïŒ48K
åèšã¡ã¢ãªãµã€ãºïŒ512K
ããŒãããŒããŒã¢ãŒã...
FAT FSããŠã³ãã¹ããŒã¿ã¹= 0
ã¢ããªã±ãŒã·ã§ã³ãã¡ã€ã«ã®ãªãŒãã³ã¹ããŒã¿ã¹= 0
MSD_MEMãšUSER_MEMã®éãïŒ2212ãã€ããã4ãã€ã
MSD_MEMã®USER_MEMãžã®ã³ããŒãéå§ããŸãã
ãã¡ã€ã«ãµã€ãº= 2212ãã€ã
æ¬äœãµã€ãº= 2048ãã€ã
ããŒã«ãµã€ãº= 164ãã€ã
ã»ã¯ã¿ãŒ0ïŒ0x08010000-0x08010800ïŒãæ¶å»ãããŸãã
ã»ã¯ã¿ãŒ1ïŒ0x08010800-0x08011000ïŒãæ¶å»ãããŸãã
0ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ã ïŒ0x08010000-0x08010200
1ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ãã³ã°ïŒ0x08010200-0x08010400
2ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ã ïŒ0x08010400-0x08010600
3ãµã€ã¯ã«ãèªã¿åãã¹ããŒã¿ã¹= 0ã512ãã€ãèªã¿åã
512ãã€ãã®ããã°ã©ã ïŒ0x08010600-0x08010800
ããŒã«ã®èªã¿åãïŒèªã¿åãã¹ããŒã¿ã¹= 0ãèªã¿åã164ãã€ããããŒã«ã®ãµã€ãº= 164
ããŒã«ã®æ°ãããµã€ãº= 164
164ãã€ãã®ããã°ã©ãã³ã°ïŒ0x08010800-0x080108A4
ãã¡ã€ã«ã®ã¯ããŒãºç¶æ = 0
FAT FSã¢ã³ããŠã³ãã¹ããŒã¿ã¹= 0
åšèŸºæ©åšã®åæåã解é€ããŠ0x08010561ã«ãžã£ã³ã...
ãŸãšãããšã ããŒãããŒããŒãå€æããŸããïŒ ãããŠãããæ©èœããŸãã UARTã§ãããã°ã¡ãã»ãŒãžãåºåãããšã-25608ãã€ããªãã§31684ãã€ãã®ãã©ãã·ã¥ã¡ã¢ãªãå æããŸãã 倧容éã¹ãã¬ãŒãžãã£ã¹ã¯ã«å¿ èŠãªã¡ã¢ãªéãèæ ®ãããšãããã»ã©å€ãã¯ãããŸããã ãœãŒã¹ãšäœæ¥ãã©ããïŒAtollic TrueSTUDIOïŒã¯ã Bitbucketã§è¡šç€ºã§ããŸãã
ãæž èŽããããšãããããŸããïŒ