MiniDSO TS100 은 꽤나 괜찮은 가성비를 가지는 인두기입니다. 특히 인두기 컨트롤러의 펌웨어가 오픈 소스(빌드에 IAR ARM 이 필요하지만… 없는 것보단 나으니까요)에 커스텀 펌웨어가 가능하다는 점은, 순정펌보다 나은 커스텀 펌웨어 (https://github.com/Ralim/ts100/) 가 나올 수 있는 환경을 만들어 주었습니다.

하지만 여기에는 한 가지 골 아픈 문제가 있는데, 인두기의 부트로더 코드는 MiniDSO 측에서 공개하지 않았고, 이 부트로더의 USB MSD를 이용하는 DFU가 상당히 “삐걱거리며” 돌아간다는 데 있습니다.

이에, 새 부트로더 개발 이슈를 Ralim/ts100 에 올려서 약간 간을 봐 본 결과, 꽤나 반응이 호의적이었고, 해당 이슈에서, DAPBoot 포팅을 하는 것이 좋을 것 같다는 의견을 받고, 포팅 작업을 진행하였습니다.

DAPBoot 는 USB DFU 표준과, WebDFU 를 지원하는 STM32 MCU 용 부트로더입니다. 이 부트로더를 TS100 에 포팅하는 프로젝트를 우선은 쉬운 개발을 위해, Olimex STM32-H103 보드 위에서 개발을 진행하고, 이후 실 TS100 하드웨어 위에서 문제를 해결하는 것을 목표로 작업 진행하였습니다.

개발용 STM32-H103 보드를 셋업합니다. TS100 회로를 읽고, 스위치에 해당하는 부분에 점퍼를 달아줍니다.

이후, DAPBoot 코드를 읽고, 개략적인 보드 하드웨어 초기화 루틴을 작성하였습니다. TS100 에서 버튼을 쓰는 방식인, 내장 풀업을 켜고, 버튼은 풀다운을 하는 방식을 지원하기 위해, target_gpio_setup() 함수에

    /* Setup Buttons */
#if HAVE_BUTTON
    {
        const uint8_t mode = GPIO_MODE_INPUT;
        const uint8_t conf = (BUTTON_EXT_PUPD ? GPIO_CNF_INPUT_FLOAT
                                              : GPIO_CNF_INPUT_PULL_UPDOWN);

        gpio_set_mode(BUTTON_GPIO_PORT, mode, conf, BUTTON_GPIO_PIN);

        #if !BUTTON_EXT_PUPD && !BUTTON_ACTIVE_HIGH
        gpio_set(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN);
        #else
        gpio_clear(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN);
        #endif
    }
#endif

이와 같은 버튼 초기화용 매크로 설정 몇 가지를 가지고, 버튼 모드와 내장 풀업/풀다운을 설정하는 코드를 작성하였습니다.

그리고, TS100 의 클럭 소스를 확인한 결과, USB 표준에 부합하지 않음에도 불구하고, 원가 절감을 위해 외부 크리스털을 생략한 것을 확인할 수 있었습니다.

물론, HSI 오실레이터를 보정 없이 USB에 사용하는 것은 USB 표준에 부합하지 않기 때문에 원본 DAPBoot 코드에는 HSI 오실레이터 관련 코드가 존재하지 않았습니다. 하지만 이 프로젝트에서는 어쨌거나 기존 하드웨어의 수정 없이 부트로더를 포팅해야 했기에, DAPBoot 부트로더의 클럭 초기화 함수를 패치해서, HSE 오실레이터를 활성화하는 코드를 target_clock_setup() 에 추가하였습니다.

void target_clock_setup(void) {
    /* Set system clock to 72 MHz */
    #ifdef USE_HSI
    rcc_clock_setup_in_hsi_out_48mhz();
    #else
    rcc_clock_setup_in_hse_8mhz_out_72mhz();
    #endif
}

여기까지 작업하고, TS100 순정 펌웨어를 패치된 DAPBoot 를 이용하여, 부트시켜 보았습니다. 제대로 동작한다면 USB MSD 로 잡혀야 하지만, USB enumeration 실패 로그를 확인할 수 있었습니다. 또한 실 TS100 하드웨어에서는 OLED 스크린이 켜지지 않는 문제도 발견되었습니다.

이 문제를 보았을 때, 처음 든 생각은, 클럭 소스 문제라는 직감이었습니다. 이에, ST-Link 와 OpenOCD 를 이용, 부트로더를 바꿔가며, 순정 부트로더로 부팅시켰을 때의 RCC(Reset & Clock Control) 설정 메모리 영역 덤프를 비교해 보았습니다.

두 경우의 RCC 메모리 덤프를 뜬 다음, diff 를 이용해 비교합니다.

이 Diff 에서 다른 부분 중 어드레스 0x4002101C 부분은 RCC_APB1ENR 레지스터입니다. 차이가 무엇인지를 데이터시트를 참조해 알아냅니다.

확인 결과, DAPBoot 포트에서는 USBEN 과 I2C1EN 플래그가 꺼져 있음이 보입니다. 이를 해결해 순정 펌웨어를 부트시키기 위해, 부팅 전에 하드웨어를 활성화 시켜주는 부분을 추가로 작성해 넣습니다.

void target_configure_hardware(void) {
#ifdef TARGET_TS100
    rcc_set_usbpre(0x1);
    rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN | RCC_APB1ENR_I2C1EN);
#endif
}

이 작업을 완료하고 순정 펌웨어의 USB 인식 상태를 확인해 보면, 2MB USB MSD로 잡히는 것을 확인할 수 있습니다.

이제 이 부트로더를 실제로 장치에 구워봅니다

정상적으로 부팅되는 것을 확인할 수 있습니다.

이로서, 부트로더 포팅을 완료하였습니다.

추가:

웹 DFU 도 잘 됩니다

프로젝트 리포지토리: https://github.com/perillamint/dapboot