tinyuf2/ports/mimxrt10xx/apps/esp32programmer/main.c
2025-01-20 22:22:10 +07:00

213 lines
6 KiB
C

/*
* The MIT License (MIT)
*
* Copyright (c) 2020 Ha Thach (tinyusb.org) for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "fsl_gpio.h"
#include "fsl_iomuxc.h"
#include "fsl_lpuart.h"
#include "board_api.h"
#include "tusb.h"
/* This is an application to act as USB <-> Uart and
* used to program ESP32 Co-Processors
*/
// Enable this for more reliable connection require esptool.py default reset option "--before default_reset"
// i.e "--before no_reset" should not be include in the esptool.py command
#define ESP32_DTR_RTS_BOOT_RESET_SUPPORT 0
// optional API, not included in board_api.h
int board_uart_read(uint8_t* buf, int len);
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
//uint8_t const RGB_USB_UNMOUNTED[] = { 0xff, 0x00, 0x00 }; // Red
//uint8_t const RGB_USB_MOUNTED[] = { 0x00, 0xff, 0x00 }; // Green
static volatile uint32_t _timer_count = 0;
static uint32_t baud_rate = 115200;
//--------------------------------------------------------------------+
// Timer
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline uint32_t millis(void) {
return _timer_count;
}
static inline void delay_blocking(uint32_t ms) {
uint32_t start = _timer_count;
while (_timer_count - start < ms) {
tud_task();
}
}
void board_timer_handler(void) {
_timer_count++;
}
//--------------------------------------------------------------------+
// ESP32 Helper
//--------------------------------------------------------------------+
static inline void esp32_set_io0(uint8_t state) {
GPIO_PinWrite(ESP32_GPIO0_PORT, ESP32_GPIO0_PIN, state);
}
static inline void esp32_set_en(uint8_t state) {
GPIO_PinWrite(ESP32_RESET_PORT, ESP32_RESET_PIN, state);
}
void esp32_manual_enter_dfu(void) {
// Put ESP into upload mode
esp32_set_io0(1);
esp32_set_en(0);
delay_blocking(100);
esp32_set_io0(0);
esp32_set_en(1);
delay_blocking(50);
esp32_set_io0(1);
}
//--------------------------------------------------------------------+
// Main
//--------------------------------------------------------------------+
int main(void) {
board_init();
gpio_pin_config_t pin_config = { kGPIO_DigitalOutput, 1, kGPIO_NoIntmode };
// ESP GPIO0
IOMUXC_SetPinMux(ESP32_GPIO0_PINMUX, 0);
IOMUXC_SetPinConfig(ESP32_GPIO0_PINMUX, 0x10B0U);
GPIO_PinInit(ESP32_GPIO0_PORT, ESP32_GPIO0_PIN, &pin_config);
// ESP Reset
IOMUXC_SetPinMux(ESP32_RESET_PINMUX, 0);
IOMUXC_SetPinConfig(ESP32_RESET_PINMUX, 0x10B0U);
GPIO_PinInit(ESP32_RESET_PORT, ESP32_RESET_PIN, &pin_config);
board_uart_init(115200);
board_usb_init();
tud_init(BOARD_TUD_RHPORT);
board_timer_start(1);
#if !ESP32_DTR_RTS_BOOT_RESET_SUPPORT
esp32_manual_enter_dfu();
#endif
while (1) {
uint8_t serial_buf[512];
uint32_t count;
// UART -> USB
count = (uint32_t)board_uart_read(serial_buf, sizeof(serial_buf));
if (count) {
board_led_write(0xff);
tud_cdc_write(serial_buf, count);
tud_cdc_write_flush();
board_led_write(0);
}
// USB -> UART
while (tud_cdc_available()) {
board_led_write(0xff);
count = tud_cdc_read(serial_buf, sizeof(serial_buf));
board_uart_write(serial_buf, count);
board_led_write(0);
}
tud_task();
}
}
//--------------------------------------------------------------------+
// USB CDC
//--------------------------------------------------------------------+
// Invoked when device is plugged and configured
//void tud_mount_cb(void)
//{
// board_rgb_write(RGB_USB_MOUNTED);
//}
//
//// Invoked when device is unplugged
//void tud_umount_cb(void)
//{
// board_rgb_write(RGB_USB_UNMOUNTED);
//}
// Invoked when line coding is change via SET_LINE_CODING
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) {
(void)itf;
if (baud_rate != line_coding->bit_rate) {
baud_rate = line_coding->bit_rate;
// must be the same freq as board_init()
uint32_t freq;
if (CLOCK_GetMux(kCLOCK_UartMux) == 0) /* PLL3 div6 80M */
{
freq = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
} else {
freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
}
LPUART_SetBaudRate(UART_DEV, baud_rate, freq);
}
}
#if ESP32_DTR_RTS_BOOT_RESET_SUPPORT
// Invoked when cdc when line state changed e.g connected/disconnected
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
(void) itf;
/* esptool.py does use DTR and RTS to put esp32 into bootloader mode
* RTS <-> ESP32 Enable
* DTR <-> ESP32 IO0
* Note: hardware DTR and RTS signal is active low, therefore we
* need to invert its logical asserted state.
*/
bool const en = !rts;
bool const io0 = !dtr;
esp32_set_io0(io0);
esp32_set_en(en);
}
#endif