牛卧堂MCU技术交流

标题: NUC980的PA1~PA6总被jtag占用,怎么才能把这几个io口释放 [打印本页]

作者: 匿名    时间: 2023-8-8 14:56
标题: NUC980的PA1~PA6总被jtag占用,怎么才能把这几个io口释放

# echo 2 > /sys/class/gpio/export
Please Check GPIOA02's multi-function = 0x4
sh: write error: Invalid argument
# echo 3 > /sys/class/gpio/export
Please Check GPIOA03's multi-function = 0x4
sh: write error: Invalid argument
# echo 4 > /sys/class/gpio/export
Please Check GPIOA04's multi-function = 0x4
sh: write error: Invalid argument
# echo 5 > /sys/class/gpio/export
Please Check GPIOA05's multi-function = 0x4
sh: write error: Invalid argument
# echo 6 > /sys/class/gpio/export
Please Check GPIOA06's multi-function = 0x4
sh: write error: Invalid argument



作者: arthur    时间: 2023-8-9 14:17
本帖最后由 arthur 于 2023-8-14 13:52 编辑

查阅NUC980 TRM手册
PA.2 是一个multifunction PIN
MFP = 0 为普通的GPIO功能
MFP = 1 为UART6_CTS
MFP = 2 为I2S_LRCK
MFP = 3 为SC0_CD
MFP = 4 为JTAG1_TDO
MFP = 6 为TM2_ECNT


jtag0组下属的pins有PG11, PG12, PG13, PG14, PG15, pin number分别为0x02, 0x03, 0x04, 0x05, 0x06
jtag1组下属的pins有PA2, PA3, PA4, PA5, PA6, pin number分别为0x6B, 0x6C, 0x6D, 0x6E, 0x6F

文件 pinctrl-nuc980.c,数组nuc980_pinctrl_groups[] 里,
{
    .name = "jtag1_grp",
    .pins = jtag1_pins,
    .num_pins = ARRAY_SIZE(jtag1_pins),
    .func = 0x4,
},

从NUC980 TRM page 62查到
.func = 0x7时,JTAG0作为JTAG使用
.func = 0x4时,JTAG1作为JTAG使用

如果想把JTAG1所占用的IO口作为普通的GPIO来使用的话,就需要将 .func = 0x0

现在来分析结构体 struct nuc980_pinctrl_group.func 是如何通过nuc980_set_mux()对.func来区分不同组(group)下的各个PIN的功能。


int nuc980_set_mux(struct pinctrl_dev *pctldev, unsigned selector, unsigned group)
{
    unsigned int i, j;
    unsigned int reg, offset;

    for (i = 0; i < nuc980_pinctrl_groups[group].num_pins; i++) {
        j = nuc980_pinctrl_groups[group].pins;
        offset = (j >> 4)*8 + ((j & 0x8) ? 4 : 0);
        reg = __raw_readl(REG_MFP_GPA_L + offset);
        reg = (reg & ~ (0xF << ((j&0x7)*4))) | (nuc980_pinctrl_groups[group].func << ((j&0x7)*4));
        __raw_writel(reg, REG_MFP_GPA_L + offset);
    }

    return 0;
}

nuc980_set_mux() 首先取得各个组(jtagX group)下的每个pin, 对每个pin_num 作如下运算,计算出其相对于REG_MFP_GPA_L的偏移offset
offset = (pin_num >> 4) * 8 + ((pin_num & 0x8) ? 4 : 0;

读出每一个pin_num的寄存器的值:reg = __raw_readl(REG_MFP_GPA_L + offset);   在此值的基础上,再将多功能PIN的值附加上去
reg = (reg & ~ (0xF << ((pin_num & 0x7) * 4))) | (nuc980_pinctrl_groups[group].func << ((pin_num & 0x7) * 4));

在此值的基础上,再将多功能PIN的值附加上去”,这里至关重要,也很神密,它是如何做到简单地配置一下.func 就能将“一组group下的所有pin作为单一的功能”的呢?





作者: 匿名    时间: 2023-8-9 14:59
arthur 发表于 2023-8-9 14:17
查阅NUC980 TRM手册
PA.2 是一个multifunction PIN
MFP = 0 为普通的GPIO功能

我改了,还是这样
作者: arthur    时间: 2023-8-9 16:18
本帖最后由 arthur 于 2023-8-14 10:34 编辑

还是显示如下的错误信息吗?
Please Check GPIOA02's multi-function = 0x4
sh: write error: Invalid argument

后面还是 multi-function = 0x4 ??? 如果是这个,说明改了没有生效,Linux有重编译到吗?
在文件pinctrl-nuc980.c中故意写一些错误语句,特别是要注意nuc980_set_mux()这个函数有没有被调用到!!!

作者: arthur    时间: 2023-8-9 16:20
本帖最后由 arthur 于 2023-8-9 16:49 编辑

你的工程如果使用了“设备树”,修改的文件为 pinctrl-nuc980-dt.c, 方法就不是这里提到的,需要在设备树中配置。
设备树中定义jtag1 所用到的pins: PA.2, PA.3, PA.4, PA.5, PA.6
PA.2 --> JTAG1_TDO
PA.3 --> JTAG1_TCK
PA.4 --> JTAG1_TMS
PA.5 --> JTAG1_TDI
PA.6 --> JTAG1_nTRST

jtag1 {
    pinctrl_jtag1_PA: jtag1-PA {
        nuvoton,pins =
            <0 2 0 0
              0 3 0 0
              0 4 0 0
              0 5 0 0
              0 6 0 0>;
};   这里的数组的第三列(0) 即为multifunction = 0,  第一列为bank (0 为 PA, 1 为PB), 第二列为pin编号,第四列“保留”,始终填 '0'



作者: arthur    时间: 2023-8-9 16:58
游客 171.212.148.x 发表于 2023-8-9 14:59
我改了,还是这样

在文件pinctrl-nuc980.c中故意写一些错误语句,看看编译的时候到底有没有编译到。如果是在Buildroot下编译,执行 $ make linux-rebuild ; make

作者: 匿名    时间: 2023-8-11 10:00
Power on setting 中 PG4=0 用PA[2-6]作为jtag,PG4=1用PG[11-15]用作jtag。所以PG4=1可以放开PA作为普通IO
另一种方式参考http://www.nuvoton-mcu.com/nufaq/?q-5554.html

作者: 匿名    时间: 2023-8-17 18:54
游客 112.64.146.x 发表于 2023-8-11 10:00
Power on setting 中 PG4=0 用PA[2-6]作为jtag,PG4=1用PG[11-15]用作jtag。所以PG4=1可以放开PA作为普通IO ...


Power on setting这个是在哪啊





欢迎光临 牛卧堂MCU技术交流 (http://nuvoton-mcu.com/) Powered by Discuz! X3.2