4.2 로 바뀌면서 안되는 것이 정말 저에게는 치명적이라,


USB MSC 가 안되서 4.2 에서 돌아가게 해 보려는데 도무지 방법이 없네요.

누가 4.19 버전 갖고 계시면 좀 보내 주시면 감사하겠습니다.

cubemx 4.16 버전 받았습니다. 필요하신 분은, 댓글에 링크 걸어 두었습니다.

그래도 혹시 4.19 버전 갖고 있으신분, 링크 부탁드립니다.

하하, CUBEMX 4.19 버전도 구했습니다. ST 대리점에 부탁해서 얻었습니다. 휴~~

다시 링크 해 드립니다. 혹시 저와 같은 경우로 어려움을 겪으시는 분들이 계시면 다운 받으시기 바랍니다.
1. cubemx v4.16 : 링크
2. cubemx v4.19 : 링크


USB MSC 도 안되고, 


HAL_SD_CardInfoTypedef 도 바뀌었습니다.

BSP_SD_ReadBlocks_DMA(),BSP_SD_WriteBlocks_DMA() 함수도 바뀌었고,

MX_SDMMC1_SD_Init() 함수도 이상하다고 하네요.

얼마 전에, 클럭 조차도 동작 안하던 버그가 있었고요.

아무래도, CUBEMX 4.2 는 쓰지 말고, 이전 버전으로 돌아가야할 듯 합니다.


2018 년 3월 18일에 일어난 업데이트 버그입니다. 예전 글을 1개씩 옮기는 중이라, 현재 일어난 일 인줄 착각 할까봐 이 글을 추가합니다.


CUBEMX 4.2 업데이트를 하고 나서,

KEIL 컴파일러 코드 생성 시, 심각한 버그가 발견 되었습니다.

HCLK 의 초기화가 잘못 되어서 프로그램이 동작되지 않습니다.

SystemClock_Config() 함수 내용 중, 1줄이 잘못 되었는데, 예전 코드로 수정해야 동작이 되네요.

SystemClock_Config() 예전 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void SystemClock_Config(void)
{
 
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
    /**Configure the main internal regulator output voltage 
    */
  __HAL_RCC_PWR_CLK_ENABLE();
 
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
    /**Initializes the CPU, AHB and APB busses clocks 
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
cs

SystemClock_Config() CUBEMX 4.20 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void SystemClock_Config(void)
{
 
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
    /**Configure the main internal regulator output voltage 
    */
  __HAL_RCC_PWR_CLK_ENABLE();
 
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
cs


SystemClock_Config() CUBEMX 4.20 코드(수정)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void SystemClock_Config(void)
{
 
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
    /**Configure the main internal regulator output voltage 
    */
  __HAL_RCC_PWR_CLK_ENABLE();
 
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
    /**Initializes the CPU, AHB and APB busses clocks 
    */
  //RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
cs


처음으로 SD-Card 를 납땜을 해서, 동작이 잘 되는지 확인을 해 봤습니다.


테스트 방법은, uSD-Card 를 마운트 하고 디렉토리 스캔을 해서 USB_CDC 로 터미널에 뿌려서
안에 넣어둔 파일이 제대로 보이는지 확인하면 되겠습니다.

다음은 보드에 uSD-Card 를 납땜한 모습입니다.




uSD-Card 회로도는 다음과 같습니다. STM32F4xx 에 SDIO-4bit 방식으로 연결했습니다.




다음은 ST 사의 CUBEMX 툴로 SDIO-4BIT 를 추가한 핀맵입니다.




다음은 디렉토리 스캔 함수 인데, 출처는 기억이 안납니다. main.c 파일에 붙여서 사용하면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
void f_opendir_scan(void)
{
    #if _USE_LFN
    TCHAR lfn[_MAX_LFN + 1];
    fno.lfname = lfn;
    fno.lfsize = sizeof lfn;
    #endif
    TCHAR path[200= "";
    
    res = f_mount(&fs32,SD_Path,1);
    printf("SD Mount : res f_mount : %02X\n\r",res);
    
    if (res == FR_OK)
    {
    res = f_opendir(&dir,path);
        printf("res f_open : %02X\n\r",res);
        
        if (res == FR_OK)
        {
        while(1)
        {
            char *fn;
             
            res = f_readdir(&dir, &fno);
             
            if (res != FR_OK)
                printf("res = %d f_readdir\n\r", res);
 
            if ((res != FR_OK) || (fno.fname[0== 0))
                break;
 
#if _USE_LFN
      fn = *fno.lfname ? fno.lfname : fno.fname;
#else
      fn = fno.fname;
#endif
            printf("%c%c%c%c ",
                ((fno.fattrib & AM_DIR) ? 'D' : '-'),
                ((fno.fattrib & AM_RDO) ? 'R' : '-'),
                ((fno.fattrib & AM_SYS) ? 'S' : '-'),
                ((fno.fattrib & AM_HID) ? 'H' : '-') );
 
            printf("%10d ", fno.fsize);
             
            printf("%s/%s\n\r", path, fn);
        }        
        }
 
        res = f_mount(0,SD_Path,0);
        printf("SD Unmount : res f_mount : %02X\n\r",res);
    }
}
 
cs

다음은 main() 함수에서, 파일 변수들 정의해 봏고, 디렉토리 스캔함수를 호출해 주면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* Private variables ---------------------------------------------------------*/
HAL_SD_ErrorTypedef res_sd;
 
FRESULT res;
FILINFO fno;
FIL fil;
DIR dir;
FATFS fs32;
 
uint32_t byteswritten, bytesread; /* File write/read counts */
 
 
int main(void)
{
  /* Reset of all peripherals, 
  Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM2_Init();
  MX_USB_DEVICE_Init();
  MX_SDIO_SD_Init();
  MX_FATFS_Init();
 
  /* USER CODE BEGIN 2 */
  // HAL_GPIO_WritePin(SDPWR_GPIO_Port, SDPWR_Pin, GPIO_PIN_RESET);
  HAL_Delay(500);
  HAL_TIM_Base_Start_IT(&htim2);
    
  f_opendir_scan();
 
  while (1)
  {
 
  }
}
cs

그리고 나서 프로그램을 다운로드 하고 실행을 하니, uSD-Card 의 내용이 보입니다.
납땜이 제대로 잘 됐군요.^^




얼마 전에 CUBEMX 업데이트를 했는데, 못보던 LIB가 1개 보이네요.





아직 쓸 일이 없고, 어떻게 쓰는 줄도 모르겠지만, JPEG encode,decode 함수가 있네요.
jpeg_CreateCompress() , jpeg_CreateDecompress()

나중에 쓸 일 있으면 써봐야겠다. ^^.

아뭏든 나온지 보름 정도 밖에 안된 따끈따끈한 라이브러리 랍니다. (2017,3,2)


STM32 MCU 는 PSOC5과 같이 포트를 맘대로 바꾸기 어려워서,

이런 저런 기능을 사용하고 나면 못쓰는 기능들이 생깁니다.

저의 경우에는, TIMx PWM_CHx 핀을 쓰고 싶은데, 없고 TIMx PWM_CHxN 핀은 있어서,
뭐가 다른가 하고 테스트를 해보게 되었습니다.
물론, 메뉴얼을 좀 읽어 보니까 Complementary outputs 기능을 사용할 경우에는 의미가 있지만, 그 내용은 일단 생략하고,
단순한 PWM 출력만을 놓고 테스트 해 봤을 때는, 이름만 다르지 전혀 차이가 없이 사용 가능했습니다.

이 테스트는 STM32F411 Nucleo 보드에서 진행 하였고, 다음과 같은 포트를 사용했습니다.








TIM2 의 설정은 PWM 출력 1개가 나오는데, 이건 오실로 스코프로 찍기 쉽게 
펄스 하나를 TIM2 Update 인터럽트에 맞춰서 내보내도록 설정 한 것으로 중요한 내용이 아니라서 통과하고,
TIM1 의 PWM_CH1 과 PWM_CH2N 을 완벽하게 같은 조건으로 설정하고 포트 출력을 확인해 봤습니다.

[TIM1 PWN 채널 출력 설정]





[위의 설정에 따른 결과]





[설명]
위의 설정은 TIM2 Update INT 마다 TIM1 의 PWM_CH1 과 PWM_CH2N 을 완전히 똑같은 조건으로,
(One Pulse Mode, 5-repeat , 주기 : 5ms, Duty : 1/10) 출력하도록 프로그램을 했고,
오실로 스코프로 출력을 측정한 사진입니다.

결론은 일반적인 PWM 신호를 포트로 출력할 경우는, PWM_CHx 나 PWM_CHxN 은 동일한 출력을 내므로,
PWM_CHx 가 없고 PWM_CHxN 만 있다면 그것을 써도 무방하다.

다만, 프로그램에서 출력 함수가 다르다.
PWM_CHx 출력 함수는 HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel)인데,
PWM_CHxN 출력 함수는 HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel) 입니다.

다음은 CUBEMX 툴로 설정된 내용을 KEIL 코드로 변환한 소스 중에서,
제가 임의로 추가한 부분입니다.
다음은 먼저 main.c 파일의 main() 함수에서 TIM2 Update Interrupt 시작하는 코드와 TIM2 PWM 포트 출력 코드 이고,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int main(void)
{
 
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration----------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
 
  /* USER CODE BEGIN 2 */
  HAL_Delay(500);
  HAL_TIM_Base_Start_IT(&htim2);
    HAL_TIM_OC_Start(&htim2,TIM_CHANNEL_1);
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
 
  }
  /* USER CODE END 3 */
 
}
cs

이 TIM2 인터럽트에 의해 TIM1_PWM_CH1 과 TIM2_PWM_CH2N 을 출력하는 코드입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* Prevent unused argument(s) compilation warning */
    if (htim->Instance == TIM2)
    {
        HAL_TIMEx_OCN_Start(&htim1,TIM_CHANNEL_1);
        HAL_TIM_OC_Start(&htim1,TIM_CHANNEL_2);
    }
    else if (htim->Instance == TIM1)
    {
    }
  /* NOTE : This function Should not be modified, when the callback is needed,
            the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
   */
}
cs


전체 프로젝트를 첨부해 둡니다.

pwm_chN_out.zip



이전에 올린 글 "[STM32F4xx] uSD-Card USB MSC(Mass Storage Class) CUBEMX 설정 (1/2)" 에 이어서,

프로그램 수정 사항을 올립니다.

MSC 의 수정할 부분은 의외로 별로 없습니다.
CUBEMX 에서 설정만 잘 했으면, usbd_storage_if.c 파일만 손보면 됩니다.

1. #include 추가.
1
2
3
4
5
6
/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
/* USER CODE BEGIN INCLUDE */
#include "bsp_driver_sd.h"
/* USER CODE END INCLUDE */
 
cs


2. STORAGE_Init_FS() 함수 수정.
1
2
3
4
5
6
7
int8_t STORAGE_Init_FS (uint8_t lun)
{
  /* USER CODE BEGIN 2 */ 
    BSP_SD_Init();
    return (USBD_OK);
  /* USER CODE END 2 */ 
}
cs


3. STORAGE_GetCapacity_FS() 함수 수정.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 3 */   
  HAL_SD_CardInfoTypedef info;
 
    BSP_SD_GetCardInfo(&info);
 
    *block_num = (info.CardCapacity)/STORAGE_BLK_SIZ  - 1;
    *block_size = STORAGE_BLK_SIZ;
//  *block_num  = STORAGE_BLK_NBR;
//  *block_size = STORAGE_BLK_SIZ;
  return (USBD_OK);
  /* USER CODE END 3 */ 
}
cs

4. STORAGE_Read_FS() 함수 수정.
1
2
3
4
5
6
7
8
9
10
int8_t STORAGE_Read_FS (uint8_t lun, 
                        uint8_t *buf, 
                        uint32_t blk_addr,                       
                        uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */ 
    BSP_SD_ReadBlocks_DMA((uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ,STORAGE_BLK_SIZ, blk_len);
  return (USBD_OK);
  /* USER CODE END 6 */ 
}
cs

5. STORAGE_Write_FS() 함수 수정.
1
2
3
4
5
6
7
8
9
10
int8_t STORAGE_Write_FS (uint8_t lun, 
                         uint8_t *buf, 
                         uint32_t blk_addr,
                         uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */ 
    BSP_SD_WriteBlocks_DMA((uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ,STORAGE_BLK_SIZ, blk_len);
  return (USBD_OK);
  /* USER CODE END 7 */ 
}
cs

이상이고, SDIO_CD (Card Detection) 신호를 사용하려면 위 함수들에 약간의 추가적인 코드가 필요합니다.
이전 글의 마지막에 링크된 웹사이트를 참고하셔서 수정하시면 됩니다.

다음은, 이 USB MSC 로 생성된 USB 드라이브 내용입니다.




엊그제 uSDcard 내용을 읽어서 USB CDC 로 터미널에 뿌렸던 내용과는 너무나 깔끔하고 좋네요.
파일을 PC에서 수정 가능하고, 쉽게 읽고 쓸 수 있습니다. ^^

[엊그제 uSDcard 내용을 읽어서 USB CDC 로 터미널에 뿌렸던 내용




요새 uSD-Card를 보드에 직접 납땜을 해서,

파일을 수정할 방법을 강구하다가 USB MSC(Mass Storage Device Class)를 공부하게 됐습니다.
2일 동안 회사에서 의자에 붙어서 열심히 팠습니다. ㅠㅠ

된다고 하는 여러 예제들이 있었는데, 왜 나만 안되는 것인지.. 참 답답했는데,
원인은 여러가지겠지만, 
가장 큰 원인은 인터럽트 우선순위를 설정하지 않고 모두 0으로 놓으니 동작이 안됐던 것 같았습니다.

그럼, 차근차근 설명을 해 보겠습니다.
제가 테스트하는 H/W 는 
1. SD-Card SDIO-4Bit DMA , 
2. USB Device Only , 
3. Embedded DFU 방식으로 F/W Upload. (BOOT0 핀과 GPIO INPUT 핀에 공통으로 스위치 사용)
4. BOOT1 을 GPIO OUT(LED OUT) 과 공통으로 사용.
5. RCC(HSE)로 24MHz Crystal 사용.
6. Middle Wares -> FATFS -> SD Card 설정.
7. SDPWR 은 필요 없는 기능이니 신경쓰지 마시고요.
으로 어제와 동일합니다.




어제 쓴 글에서는 디렉토리만 읽어서 USB CDC로 표시만 할 수 있었는데, 이번에는 MSC로 읽기 쓰기를 구현해 보고자,
CUBEMX 툴에서 USB_DEVICE 타입을 Mass Storage Class 로만 변경했습니다.






클락 탭의 설정은 다음과 같습니다.






다음은 CUBEMX 의 Configuration TAB의 상세 설정입니다. 
바꾼 것들만 설명을 할 것인데, 그 외의 설정은 디폴드 설정으로 건드리지 않았습니다.
NVIC 는 각각의 상세 설정에도 있고, 따로 NVIC 설정이 분리되어 있는데, 맨 마지막에 NVIC를 수정할 예정입니다.

















다음은 NIVC(인터럽트 우선순위) 설정으로 어떻게 정하는지 저도 잘 모르겠습니다만, MSC 안 되었던 이유 중 가장 큰 원인이, 이 우선순위를 수정하지 않고 모두 우선순위가 0(Default)으로 내버려 뒀기 때문이었습니다.
나중에 같은 실수를 방지하기 위해, 어떤 기준으로 정하는 것인지 확실히 정리해야 할 것 같습니다.






다음으로 HEAP 과 STACK 을 충분히 잡아 두라해서 일단은 최적화는 못했고, 무식하게 크게 잡아두었습니다.





글이 생각보다 너무 길어지고 시간이 너무 늦어서, S/W 쪽은 눈을 좀 붙이고 시간이 나면 작성하도록 하겠습니다.
제가 여러가지를 참고해서 S/W를 만들었는데, 일단 참고한 윕사이트를 링크해 드립니다.



리셋 시, BOOT0 핀과 BOOT1(PB2) 핀은 조합되어서, Booting mode 를 결정하는데 사용한다.


그런데, 리셋 이후의 BOOT0/BOOT1(PB2) 의 기능은?

테스트를 해보겠습니다.

공간의 절약을 위해 스위치를 BOOT0 과 GPIO Input 핀을 같이 연결해서,
스위치를 누르고 리셋을 하면 BOOT0 이 1이 되어 DFU 모드로 동작하고,
리셋 이후에 스위치를 누르면 일반 GPIO Input 기능으로 동작을 하도록 H/W를 구성해서 테스트를 해 봤습니다.

다음이 H/W 구성도 입니다.




바로 전에 쓴 글에서 LED OUT 을 사용해서 리셋 이후, BOOT1(PB2) 을 GPIO OUT으로 사용할 수 있음은 증명이 됐고,

다음은 리셋 이후, BOOT0 과 연결된 GPIO Input 핀에 연결된 스위치를 누르면서 상태를 읽어서,
USB CDC 로 뿌려 본 동영상입니다.



동영상을 보시면 리셋 이후, GPIO Input 핀과 연결된 BOOT0 핀이,
스위치에 의해서 아무 기능을 하지 않는다는 것을 알 수 있습니다.

결론은, BOO0,BOOT1(PB2) 은 리셋 시에만 영향을 미치고, 리셋 이후에는 아무런 기능도 하지 않는다.


아하 이런, 제목이 좀 잘못된 것 같네요. 하지만 Nucleo 보드에서도 적용 가능하니 놔둡니다.
(회사에서 만든 보드니 커스텀 보드 테스트라고 해야 했나? ^^)

[DFU f/w 업로드 과정]

- 간단한 기능의 S/W 를 컴파일해서, 

- ST 에서 다운 받은 응용프로그램(DfuSe 툴: 링크)으로,
- Embedded DFU 모드용 파일로 변환하고, 
- USB 로 MCU에 업로드하는 방법을 알아보겠습니다.

테스트하고 있는 MCU는 STM32F411CCYx(FLASH 256KB / SRAM 128KB / WLCSP) 입니다.
프로그램은 TIM2 Interrupt 에 의해 500ms 마다 LED 와 연결되어 있는 GPIO 를 토글해서 눈으로 동작을 확인할 생각입니다.

TIM2 프로그램은 예전에 올렸던 글을 참조하셔서 작성하면 됩니다.
STM32F446 으로 작성된 내용인데, 클럭만 틀리고 다 같습니다.

혹시 링크타고 가서 보는 것이 번거로울 것 같아서, 다시 CUBEMX 에서 바꿀 부분만 설명 드리자면,
TIM2 의 클럭 소스를 확인해서, (이전글 참고 : [STM32F4xx] Timer Clock source )





CUBEMX 툴의 TIM2 설정에서 0.5ms 에 해당하는 주기를 넣어 준다.




다음으로 CUBEMX에 의해 소스코드를 만들어 주고(저는 KEIL 컴파일러를 사용하므로 KEIL v5로 선택을 했습니다.)
TIM2 인터럽트에 의해 500ms 마다 GPIO를 토글하는 코드를 추가해 줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* Prevent unused argument(s) compilation warning */
    if (htim->Instance == TIM2)
    {
        HAL_GPIO_TogglePin(LED_OUT_GPIO_Port,LED_OUT_Pin);
    }
    else if (htim->Instance == TIM1)
    {
    }
  /* NOTE : This function Should not be modified, when the callback is needed,
            the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
   */
}
/* USER CODE END 0 */
 
int main(void)
{
 
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration----------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_USB_DEVICE_Init();
 
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  HAL_Delay(500);
  HAL_TIM_Base_Start_IT(&htim2);
    
  while (1)
  {
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
 
  }
  /* USER CODE END 3 */
 
}
cs


DFU 로 프로그램을 STM32F4xx 에 업로드 하기 위해서는 HEX 파일이 필요하므로, 
KEIL 컴파일러의 설정에서 다음과 같이 Create HEX File 옵션을 선택해 준다.





다음 과정은 예전에 Custom DFU 에서 설명했던 내용과 똑같은데, 
ST 홈페이지에서 DFU File Manager 를 다운 받아서 실행해서 다음과 같이 입력하고,
S19 or HEX 버튼을 눌러서 생성된 HEX 파일을 선택해 주고 DFU 파일을 원하는 위치에다 만들어 줍니다.




다음으로 DfuSe Demo 프로그램을 ST 사에서 다운 받아서 실행시키고,
BOOT0 을 VCC 로 연결하고 리셋을 합니다(제 경우에는 스위치를 BOOT0 와 VCC 사이에 달아 주고, 스위치를 누른 상태에서 전원을 넣어 줍니다), 
STM Device in DFU Mode 드라이브가 생기면서 DfuSe Demo 프로그램에 해당 칩 정보가 표시됩니다.
DfuSe Demo 프로그램에서 다음과 같이 순서대로 실행하시면 프로그램이 Upgrade 된 후, 실행이 됩니다.
1. Choose 버튼을 눌러 DFU File Manager 에서 만들어 놓은 DFU 파일을 선택한다.
2. Upgrade 버튼을 눌러서 프로그램을 MCU 에 Upload 한다.
3. Leave DFU mode 버튼을 누르거나, BOOT0 핀을 VCC와 연결을 끊고 리셋을 하면 프로그램이 실행됩니다.  





[프로그램 실행 동영상]


+ Recent posts