MT793x GPIO配置生成

EPT

Views:  times Updated on October 25, 2022 Posted by elmagnifico on October 12, 2022

Foreword

ST的CubeMX自动生成GPIO等相关配置文件的代码已经非常简单易懂了,最近看了MT的实现,发现也比较简单易懂,这里做一点解析。

Easy PinMux Tool

Easy PinMux Tool,可以通过这个工具,直接配置GPIO的功能和上下拉以及方向,同时也可以自定义注释。

之后就可以直接生成对应的.c和.h文件,只需要将对应的文件扔到工厂目录中,加入编译即可

部分代码

#ifndef _EPT_GPIO_DRV_H
#define _EPT_GPIO_DRV_H

#define MODE_0  0
#define MODE_1  1
#define MODE_2  2
#define MODE_3  3
#define MODE_4  4
#define MODE_5  5
#define MODE_6  6
#define MODE_7  7
#define MODE_NC  0

#define PULL_ENABLE    1
#define PULL_DISABLE  0
#define DIR_INPUT       0
#define DIR_OUTPUT    1
#define GPIO_PORTNULL_MODE    0
#define GPIO_PORTNULL_DIR       0
#define GPIO_PORTNULL_OUTPUT_LEVEL  0
#define GPIO_PORTNULL_PU        0
#define GPIO_PORTNULL_PD        0
#define GPIO_PORTNULL_R0        0
#define GPIO_PORTNULL_R1        0
#define GPIO_PORTNULL_PUPD    0
#define GPIO_PORTNULL_DOUT   0

#define GPIO_PORT0_MODE   MODE_1 // 1:SF_QPI_CK : Used for SF_QPI_CK
#define GPIO_PORT1_MODE   MODE_1 // 1:SF_QPI_CS : Used for SF_QPI_CS
#define GPIO_PORT2_MODE   MODE_1 // 1:SF_QPI_D0 : Used for SF_QPI_D0
#define GPIO_PORT3_MODE   MODE_1 // 1:SF_QPI_D1 : Used for SF_QPI_D1
#define GPIO_PORT4_MODE   MODE_1 // 1:SF_QPI_D2 : Used for SF_QPI_D2
#define GPIO_PORT5_MODE   MODE_1 // 1:SF_QPI_D3 : Used for SF_QPI_D3
#define GPIO_PORT6_MODE   MODE_3 // 3:SPIM0_SCK : Used for SPIM0_SCK
#define GPIO_PORT7_MODE   MODE_3 // 3:SPIM0_CS_N : Used for SPIM0_CS_N
#define GPIO_PORT8_MODE   MODE_3 // 3:SPIM0_MISO : Used for SPIM0_MISO
#define GPIO_PORT9_MODE   MODE_3 // 3:SPIM0_MOSI : Used for SPIM0_MOSI
#define GPIO_PORT10_MODE   MODE_3 // 3:I2SIN_DAT0 : Used for I2SIN_DAT0
#define GPIO_PORT11_MODE   MODE_3 // 3:I2SO_DAT0 : Used for I2SO_DAT0
#define GPIO_PORT12_MODE   MODE_3 // 3:CONN_BT_TXD : Used for CONN_BT_TXD
#define GPIO_PORT13_MODE   MODE_6 // 6:ANT_SEL4 : Used for ANT_SEL4
#define GPIO_PORT14_MODE   MODE_6 // 6:ANT_SEL5 : Used for ANT_SEL5
#define GPIO_PORT15_MODE   MODE_0 // 0:GPIO15 : Used for GPIO15
#define GPIO_PORT16_MODE   MODE_0 // 0:GPIO16 : Used for GPIO16
/*Output for default variable names*/
/*@XXX_XX_PIN in gpio.cmp          */

const char HAL_UART0_DTE_DCD_PIN = 0xff;
const char HAL_UART0_DTE_DSR_PIN = 0xff;
const char HAL_UART0_DTE_DTR_PIN = 0xff;
const char HAL_UART0_DTE_RI_PIN = 0xff;
const char HAL_UART1_DTE_DCD_PIN = 0xff;
const char HAL_UART1_DTE_DSR_PIN = 0xff;
const char HAL_UART1_DTE_DTR_PIN = 0xff;
const char HAL_UART1_DTE_RI_PIN = 0xff;
const char HAL_UART2_DTE_DCD_PIN = 0xff;
const char HAL_UART2_DTE_DSR_PIN = 0xff;
const char HAL_UART2_DTE_DTR_PIN = 0xff;
const char HAL_UART2_DTE_RI_PIN = 0xff;
const char BSP_CTP_SW_I2C_SCL_PIN = 0xff;
const char BSP_CTP_SW_I2C_SDA_PIN = 0xff;
const char BSP_CTP_RST_PIN = 0xff;
const char BSP_CTP_EINT_PIN = 0xff;
const char BSP_SPEAKER_EBABLE_PIN = 0xff;
const char BSP_AUXADC_ENABLE_PIN = 0xff;
const char BSP_GNSS_POWER_PIN = 0xff;

具体实现

如果直接搜上面代码的宏定义,会发现根本没被调用。实际上这个部分是通过宏字符串拼接来引用的

直接定义了寄存器的组成

#define    GPIO_MODE_REG0    GPIO_HWORD_REG_VAL(MODE,  0,  1,  2,  3,  4,  5,  6,  7, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
#define    GPIO_MODE_REG1    GPIO_HWORD_REG_VAL(MODE,  8,  9,  10,  11,  12,  13,  14,  15, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)

具体实现

#define GPIO_HWORD_REG_VAL(name, port0, port1, port2, port3, port4, port5, port6, port7, port8, port9, port10, \
                                port11, port12, port13, port14, port15, port16, port17, port18, port19, port20, port21, \
                               port22, port23, port24, port25, port26, port27, port28, port29, port30, port31,      \
                               port32, port33, port34, port35, port36, port37, port38, port39, port40, port41,      \
                               port42, port43, port44, port45, port46, port47, port48, port49, port50, port51, port52)      \
((GPIO_PORT##port0##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*0) & 0x1f)) | \
(GPIO_PORT##port1##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*1) & 0x1f)) |    \
(GPIO_PORT##port2##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*2) & 0x1f)) |   \
(GPIO_PORT##port3##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*3) & 0x1f)) |    \
(GPIO_PORT##port4##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*4) & 0x1f)) | \
(GPIO_PORT##port5##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*5) & 0x1f)) |    \
(GPIO_PORT##port6##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*6) & 0x1f)) | \
(GPIO_PORT##port7##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*7) & 0x1f)) |    \
(GPIO_PORT##port8##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*8) & 0x1f)) | \
(GPIO_PORT##port9##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*9) & 0x1f)) |    \
(GPIO_PORT##port10##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*10) & 0x1f)) |\
(GPIO_PORT##port11##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*11) & 0x1f)) |  \
(GPIO_PORT##port12##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*12) & 0x1f)) | \
(GPIO_PORT##port13##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*13) & 0x1f)) |  \
(GPIO_PORT##port14##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*14) & 0x1f)) | \
(GPIO_PORT##port15##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*15) & 0x1f)) |  \
(GPIO_PORT##port16##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*16) & 0x1f)) | \
(GPIO_PORT##port17##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*17) & 0x1f)) |  \
(GPIO_PORT##port18##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*18) & 0x1f)) |  \
(GPIO_PORT##port19##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*19) & 0x1f)) |  \
(GPIO_PORT##port20##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*20) & 0x1f)) | \
(GPIO_PORT##port21##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*21) & 0x1f)) |  \
(GPIO_PORT##port22##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*22) & 0x1f)) | \
(GPIO_PORT##port23##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*23) & 0x1f)) |  \
(GPIO_PORT##port24##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*24) & 0x1f)) | \
(GPIO_PORT##port25##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*25) & 0x1f)) |  \
(GPIO_PORT##port26##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*26) & 0x1f)) |  \
(GPIO_PORT##port27##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*27) & 0x1f)) |  \
(GPIO_PORT##port28##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*28) & 0x1f)) | \
(GPIO_PORT##port29##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*29) & 0x1f)) |  \
(GPIO_PORT##port30##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*30) & 0x1f)) | \
(GPIO_PORT##port31##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*31) & 0x1f)) | \
(GPIO_PORT##port32##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*32) & 0x1f)) |    \
(GPIO_PORT##port33##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*33) & 0x1f)) |   \
(GPIO_PORT##port34##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*34) & 0x1f)) |    \
(GPIO_PORT##port35##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*35) & 0x1f)) | \
(GPIO_PORT##port36##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*36) & 0x1f)) |    \
(GPIO_PORT##port37##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*37) & 0x1f)) | \
(GPIO_PORT##port38##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*38) & 0x1f)) |    \
(GPIO_PORT##port39##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*39) & 0x1f)) | \
(GPIO_PORT##port40##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*40) & 0x1f)) |    \
(GPIO_PORT##port41##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*41) & 0x1f)) |\
(GPIO_PORT##port42##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*42) & 0x1f)) |  \
(GPIO_PORT##port43##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*43) & 0x1f)) | \
(GPIO_PORT##port44##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*44) & 0x1f)) |  \
(GPIO_PORT##port45##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*45) & 0x1f)) | \
(GPIO_PORT##port46##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*46) & 0x1f)) |  \
(GPIO_PORT##port47##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*47) & 0x1f)) | \
(GPIO_PORT##port48##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*48) & 0x1f)) |  \
(GPIO_PORT##port49##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*49) & 0x1f)) |  \
(GPIO_PORT##port50##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*50) & 0x1f)) |  \
(GPIO_PORT##port51##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*51) & 0x1f)) | \
(GPIO_PORT##port52##_##name<<((GPIO_##name##_##ONE_CONTROL_BITS*52) & 0x1f)))

在这里通过,宏拼接,将EPT的定义引入。

之后再通过init初始化各个gpio的模式,输入输出、上下拉,电阻大小等值。

/**
  * @brief  write the joint data about GPIO mode to GPIO mode register one by one
  * @param  None
  * @retval None
  */
void gpio_mode_init(void)
{
    uint32_t i, j;
    uint32_t reg_mask[GPIO_MODE_REG_MAX_NUM];
    uint32_t temp;

#ifdef GPIO_MODE_REG_MAX_NUM
    uint32_t mode_temp[GPIO_MODE_REG_MAX_NUM] = { GPIO_MODE_ALL_VALUE };

    for (i = 0; i < GPIO_MODE_REG_MAX_NUM; i++) {
        reg_mask[i] = 0;
        for (j = 0; j < GPIO_MODE_ONE_REG_CONTROL_NUM; j++) {
            temp = j + i * GPIO_MODE_ONE_REG_CONTROL_NUM;
            if ((1 << (temp % 32)) &  GPIO_REG_PIN_MASK[temp / 32]) {
                uint32_t pin_mask = 0xf << (GPIO_MODE_ONE_CONTROL_BITS * j);
                uint32_t mode_current = ept_gpio_base->GPIO_MODE[i].RW & pin_mask;
                uint32_t mode_update  = mode_temp[i] & pin_mask;

                if (mode_current != mode_update)
                    reg_mask[i] |= pin_mask;
            }
        }
    }

    for (i = 0; i < GPIO_MODE_REG_MAX_NUM; i++) {
        ept_gpio_base->GPIO_MODE[i].CLR = reg_mask[i];
        ept_gpio_base->GPIO_MODE[i].SET = mode_temp[i];
    }

#endif
}

被bsp统一调用

/**
  * @brief  Main program to make the configuration of EPT to take effect
  * @param  None
  * @retval None
  */

void bsp_ept_gpio_setting_init(void)
{
    gpio_mode_init();
    gpio_dir_init();
    gpio_pupd_init();
    gpio_r0_r1_init();
    gpio_output_init();
}
int main(void)
{
    /* Do system initialization, eg: hardware, nvdm, logging and random seed. */
    system_init();

#ifdef HAL_GPIO_MODULE_ENABLED
    bsp_ept_gpio_setting_init();
#endif /* #ifdef HAL_GPIO_MODULE_ENABLED */

#if defined(MTK_MINICLI_ENABLE)
    /* Initialize cli task to enable user input cli command from uart port.*/
    cli_def_create();
    cli_task_create();
#endif /* #if defined(MTK_MINICLI_ENABLE) */

bsp的初始化使能是在hal_feature中设置的

离谱的点

无论是手册还是工具,都单独把以下四个串口给分别独立出来说明了。

uart0
uart1
uart2
CM33_Uart

甚至引脚上也有单独的CM33_Uart,但是实际代码里只有3个uart,就是0-2,并且其中的0就是CM33_Uart,从而出现了一个情况。实际IO上的uart1对应的是代码中的uart0,整体错位,这代码写的,真的好迷

hal_uart0 CM33_UART
hal_uart1 UART0
hal_uart2 UART1

Summary

可能ST的代码看多了,MT793X的这个底层代码写的一言难尽,很多block的地方都非常难受。

MT793X的方案,感觉还是不太行,用的人太少了,代码总是奇奇怪怪的。

Quote

MT793X IoT SDK for Easy PinMux Tool Users Guide .pdf