打印
[技术问答]

nuc029lan i2c从机scl一直处于拉低状态

[复制链接]
1620|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hyjing001|  楼主 | 2019-11-18 09:49 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hyjing001 于 2019-11-18 09:50 编辑

nuc029lan用作I2C从机,和其它主控通信,偶尔发现nuc029lan的scl会处于低电平状态,中断程序都有I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);  这种问题有谁遇到过吗?mcu好像一直处于中断程序里面,主循环有个io翻转输出的,测量它没有变化
开了超时并有清除标志
void I2C0_IRQHandler(void)
{
    uint32_t u32Status;

    u32Status = I2C_GET_STATUS(I2C0);
P05 ^= 1;
    if(I2C_GET_TIMEOUT_FLAG(I2C0))
    {
        if( g_u8SlvDataRx ) {
            I2C_ClearTimeoutFlag(I2C0);
            g_u8SlvDataRx = 0;
        }
        else if( g_u8SlvDataTx ) {
            I2C_ClearTimeoutFlag(I2C0);
            g_u8SlvDataTx = 0;
        }
        else {
        /* Clear I2C0 Timeout Flag */
            I2C_ClearTimeoutFlag(I2C0);
        }
    }
    else
    {
        if(s_I2C0HandlerFn != NULL) {
            s_I2C0HandlerFn(u32Status);
        }
    }
}

使用特权

评论回复
沙发
zhuomuniao110| | 2019-11-18 10:43 | 只看该作者
    /* I2C enter no address SLV mode */
    I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
这个不是中断里的啊

使用特权

评论回复
板凳
zhuomuniao110| | 2019-11-18 10:44 | 只看该作者
官方的例子跑不通?

使用特权

评论回复
地板
hyjing001|  楼主 | 2019-11-18 11:01 | 只看该作者
zhuomuniao110 发表于 2019-11-18 10:44
官方的例子跑不通?

可以跑通,是测试10多片板子,跑2天会发现有1片这样,复位mcu后i2c不响应主控的信号了,全部是nack;如果断电又恢复正常了

使用特权

评论回复
5
hyjing001|  楼主 | 2019-11-18 11:03 | 只看该作者
zhuomuniao110 发表于 2019-11-18 10:43
/* I2C enter no address SLV mode */
    I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
这个不是中断 ...

是中断里面清除标志的,
这个是官方的demo
void I2C_SlaveTRx(uint32_t u32Status)
{
    if(u32Status == 0x60)                       /* Own SLA+W has been receive; ACK has been return */
    {
        g_u8SlvDataLen = 0;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0x80)                 /* Previously address with own SLA address
                                                   Data has been received; ACK has been returned*/
    {
        g_au8SlvRxData[g_u8SlvDataLen] = (unsigned char) I2C_GET_DATA(I2C0);
        g_u8SlvDataLen++;

        if(g_u8SlvDataLen == 2)
        {
            slave_buff_addr = (g_au8SlvRxData[0] << 8) + g_au8SlvRxData[1];
        }
        if(g_u8SlvDataLen == 3)
        {
            g_au8SlvData[slave_buff_addr] = g_au8SlvRxData[2];
            g_u8SlvDataLen = 0;
        }

        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xA8)                  /* Own SLA+R has been receive; ACK has been return */
    {
        I2C_SET_DATA(I2C0, g_au8SlvData[slave_buff_addr]);
        slave_buff_addr++;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xC0)                 /* Data byte or last data in I2CDAT has been transmitted
                                                   Not ACK has been received */
    {
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0x88)                 /* Previously addressed with own SLA address; NOT ACK has
                                                   been returned */
    {
        g_u8SlvDataLen = 0;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xA0)                 /* A STOP or repeated START has been received while still
                                                   addressed as Slave/Receiver*/
    {
        g_u8SlvDataLen = 0;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else
    {
        /* TO DO */
        printf("Status 0x%x is NOT processed\n", u32Status);
    }
}

使用特权

评论回复
6
zhuomuniao110| | 2019-11-18 15:40 | 只看该作者
可能是复位电路问题吧,毕竟不是所有的这样。你试试复位后出问题的,其他功能还正常吗,比如主程序设置一个LED闪烁的,如果有问题,这个会停止闪烁,或者不正常。

使用特权

评论回复
7
zhuomuniao110| | 2019-11-18 15:40 | 只看该作者
另外初始化函数注意一下,在需要的时候,初始化一次。

使用特权

评论回复
8
zhuotuzi| | 2019-11-18 20:36 | 只看该作者
个别现象的话,考虑一下硬件的问题。

使用特权

评论回复
9
jasontu| | 2019-11-19 08:26 | 只看该作者
把波形貼出來看一下吧。

使用特权

评论回复
10
hyjing001|  楼主 | 2019-11-25 15:21 | 只看该作者
本帖最后由 hyjing001 于 2019-11-25 15:52 编辑
zhuomuniao110 发表于 2019-11-18 15:40
可能是复位电路问题吧,毕竟不是所有的这样。你试试复位后出问题的,其他功能还正常吗,比如主程序设置一个 ...

用镊子夹复位脚后,i2c波形正常,不过mcu没有响应,感觉复位对这种情况没作用,断电重开就正常;在主循环和i2c中断里面有增加io翻转动作,出问题后这2个io都没有变化。这个程序之前出了1K套板子,没有遇到过这样的情况。

使用特权

评论回复
11
hyjing001|  楼主 | 2019-11-25 15:21 | 只看该作者
本帖最后由 hyjing001 于 2019-11-25 15:54 编辑
jasontu 发表于 2019-11-19 08:26
把波形貼出來看一下吧。

波形没办法抓呀,它是随机出现的,不是固定那一片板子这样

N0UF@G0VIY8RZ80{4~L8{V9.png (195.73 KB )

复位mcu后的i2c波形,mcu没有响应

复位mcu后的i2c波形,mcu没有响应

使用特权

评论回复
12
manufact| | 2019-11-25 16:40 | 只看该作者
错误恢复机制没有做好吧

使用特权

评论回复
13
hyjing001|  楼主 | 2019-11-25 16:47 | 只看该作者
manufact 发表于 2019-11-25 16:40
错误恢复机制没有做好吧

哪些错误机制?好像mcu卡在某个地方不动了一样,镊子复位mcu后scl电压正常,不过mcu没有响应i2c

使用特权

评论回复
14
tianxj01| | 2019-11-25 17:38 | 只看该作者
本帖最后由 tianxj01 于 2019-11-25 17:39 编辑
hyjing001 发表于 2019-11-25 16:47
哪些错误机制?好像mcu卡在某个地方不动了一样,镊子复位mcu后scl电压正常,不过mcu没有响应i2c ...

仔细分析官方库,是不是有类似 while 循环等待某种寄存器变化,这种用法很恐怖的,外设如果没有按照时序动作,则就直接导致挂起。
所谓错误恢复机制,则需要理清楚这类等待,必须加上超时机制,终止等待并将函数改道到错误处理机制段运行。硬件驱动部分,非常忌讳这样的用法。

使用特权

评论回复
15
hyjing001|  楼主 | 2019-11-26 11:54 | 只看该作者
tianxj01 发表于 2019-11-25 17:38
仔细分析官方库,是不是有类似 while 循环等待某种寄存器变化,这种用法很恐怖的,外设如果没有按照时序动 ...

感觉像是程序跑到某个错误地方了,复位mcu后功能都没有了,i2c没有ack,断电重新正常。
我贴中断代码给你看下,没有while死等的地方
void I2C0_IRQHandler(void)
{
    uint32_t u32Status;

P05 = 1;
    u32Status = I2C_GET_STATUS(I2C0);
    if(I2C_GET_TIMEOUT_FLAG(I2C0))
    {
        if( g_u8SlvDataRx ) { // 20190922jone ++
            I2C_ClearTimeoutFlag(I2C0);
            g_u8SlvDataRx = 0;
        }
        //if( g_u8SlvDataTx ) {// 20190920 jone --
        else if( g_u8SlvDataTx ) { // 20190922 jone ++
            I2C_ClearTimeoutFlag(I2C0);
            g_u8SlvDataTx = 0;
        }
        else {
        /* Clear I2C0 Timeout Flag */
            I2C_ClearTimeoutFlag(I2C0);
        }
        est_i2c_debug_2 = 0;
    }
    else
    {
        if(s_I2C0HandlerFn != NULL) {
            s_I2C0HandlerFn(u32Status);
        }
        est_i2c_debug_2 ++;
        if( (4 * 100000) <= est_i2c_debug_2 ) {
            est_i2c_debug_2 = 0;
            est_rst_i2c_in_irq();
        }
    }

P05 = 0;
}

void I2C_SlaveTRx(uint32_t u32Status)
{

    if(u32Status == 0x60)                       /* Own SLA+W has been receive; ACK has been return */
    {
        g_u8SlvDataRx = 0;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0x80)                 /* Previously address with own SLA address
                                                   Data has been received; ACK has been returned*/
    {
        slave_buff_rx[g_u8SlvDataRx] = (unsigned char) I2C_GET_DATA(I2C0);
        g_u8SlvDataRx++;
        if( 6 < g_u8SlvDataRx ) { // 20190922 jone ++
            g_u8SlvDataRx = 0;
        }
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xA8)                  /* Own SLA+R has been receive; ACK has been return */
    { // r-1th:
        g_u8SlvDataTx = 0;
        I2C_SET_DATA(I2C0, slave_buff_tx[g_u8SlvDataTx]);
        g_u8SlvDataTx++;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xb8)                  /* first byte has been send; ACK has been return, send next byte */
    { // r-2th:
        I2C_SET_DATA(I2C0, slave_buff_tx[g_u8SlvDataTx]);
        g_u8SlvDataTx++;
        if( 6 < g_u8SlvDataTx ) { // 20190922 jone ++
            g_u8SlvDataTx = 0;
        }
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
        //if( 6 <= g_u8SlvDataTx ) {
        //    g_u8SlvDataTx = 6;
        //}
        //else {
        //    I2C_SET_DATA(I2C0, slave_buff_tx[g_u8SlvDataTx]);
        //    g_u8SlvDataTx++;
        //}
        //I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xc8)                  /* byte has been send; ACK has been return, send the last byte */
    { // 20191113 jone--
        I2C_SET_DATA(I2C0, slave_buff_tx[g_u8SlvDataTx]);
        g_u8SlvDataTx++;
        if( 6 < g_u8SlvDataTx ) { // 20190922 jone ++
            g_u8SlvDataTx = 0;
        }
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xC0)                 /* Data byte or last data in I2CDAT has been transmitted
                                                   Not ACK has been received */
    { // 3-th
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
        if( 6 <= g_u8SlvDataTx ) {
            slave_i2c_tx_len = g_u8SlvDataTx;
            g_u8SlvDataTx = 0;
            slave_i2c_tx ++;
            i2c_isr_tx_end = 1;
        }
    }
    else if(u32Status == 0x88)                 /* Previously addressed with own SLA address; NOT ACK has
                                                   been returned */
    {
        g_u8SlvDataRx = 0;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xA0)                 /* A STOP or repeated START has been received while still
                                                   addressed as Slave/Receiver*/
    {
        //if( g_u8SlvDataRx ) { // 20190920 jone --
        if( 6 <= g_u8SlvDataRx ) { // 20190920 jone ++
            slave_i2c_rx_len = g_u8SlvDataRx;
            g_u8SlvDataRx = 0;
            slave_i2c_rx ++;
            i2c_isr_rx_end = 1;
        }
        //if( g_u8SlvDataTx ) {// 20190920 jone --
        if( 6 <= g_u8SlvDataTx ) { // 20190920 jone ++
            slave_i2c_tx_len = g_u8SlvDataTx;
            g_u8SlvDataTx = 0;
            slave_i2c_tx ++;
            i2c_isr_tx_end = 1;
        }
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else
    {
        /* TO DO */
        //printf("Status 0x%x is NOT processed\n", u32Status);
        if(u32Status == 0x00) { // 20190920 jone ++
            I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO_SI); // 20190920 jone ++
            I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_STO);    // 20190920 jone ++
            //I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);  // 20191115 jone --; 20190920 jone ++
        }  // 20190920 jone ++
        else if( 0xb0 == u32Status ) { // 20191115 jone ++
            I2C_SET_DATA(I2C0, slave_buff_tx[0]);  // 20191115 jone ++
            g_u8SlvDataTx = 1;  // 20191115 jone ++
            est_i2c_debug = 1;
        }
        else if( 0x68 == u32Status ) { // 20191115 jone ++
            g_u8SlvDataRx = 0; // 20191115 jone ++
            est_i2c_debug = 2;
        }
        else {// 20191115 jone ++
            est_i2c_debug = 3;
        }
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);  // 20191115 jone ++
    }
    if( i2c_isr_rx_end ) { // get cmd from cpu
        i2c_rx_buf_checksum = slave_buff_rx[0]; // 20190920 jone ++
        i2c_rx_buf_checksum += slave_buff_rx[1]; // 20190920 jone ++
        i2c_rx_buf_checksum += slave_buff_rx[2]; // 20190920 jone ++
        i2c_rx_buf_checksum += slave_buff_rx[3]; // 20190920 jone ++
        if( slave_buff_rx[4] == i2c_rx_buf_checksum ) { // 20190920 jone ++
            if( WM_CMD_READ_INPUT == slave_buff_rx[0] ) {
                slave_buff_tx[0] = i2c_input_buf[0];
                slave_buff_tx[1] = i2c_input_buf[1];
                slave_buff_tx[2] = i2c_input_buf[2];
                slave_buff_tx[3] = i2c_input_buf[3];
                slave_buff_tx[4] = i2c_input_buf[4];
                slave_buff_tx[5] = i2c_input_buf[5];
                i2c_isr_tx_read = 1;
            }
            else if( WM_CMD_CONFIG_GPIO == slave_buff_rx[0] ) {
                if( GPIO_MAX > slave_buff_rx[1] ) {
                    if( SET_COIN_CLEAN_ERROR == slave_buff_rx[2] ) {
                        vInput_coin_reset[slave_buff_rx[1]] ++;
                    }
                    else if( SET_COIN_MODE == slave_buff_rx[2] ) {
                        vInput_coin_level_code[slave_buff_rx[1]] = slave_buff_rx[3];
                    }
                }
            }
            else if( WM_CMD_SET_OUT == slave_buff_rx[0] ) {
                if( GPIO_MAX > slave_buff_rx[1] ) {
                    if( GPIO_IS_CNT == def_config_mode[slave_buff_rx[1]] ) {
                        if( slave_buff_rx[3] ) { // value must be true
                            wm_out_cnt[slave_buff_rx[1]] += slave_buff_rx[3];
                        }
                    }
                    else {
                        vOutput_getdata_buff[slave_buff_rx[1]] = slave_buff_rx[3];
                    }
                }
            }
            else if( WM_CMD_SET_COIN_COUNT == slave_buff_rx[0] ) {
                if( GPIO_MAX > slave_buff_rx[1] ) {
                    est_i2c_temp = slave_buff_rx[2];
                    est_i2c_temp <<= 8;
                    est_i2c_temp += slave_buff_rx[3];
                    vInput_coin_count_buff[slave_buff_rx[1]] = est_i2c_temp;
                    vInput_coin_count_flag[slave_buff_rx[1]] ++;
                }
            }
            else if( WM_CMD_SET_SHA256_ARG == slave_buff_rx[0] ) {
                if( 0 == (slave_buff_rx[1] & 0xc0) ) {
                    est_i2c_temp = slave_buff_rx[1];
                    est_sha256_challenge_isr[est_i2c_temp] = slave_buff_rx[2];
                    est_i2c_temp ++;
                    est_sha256_challenge_isr[est_i2c_temp] = slave_buff_rx[3];
                    est_i2c_temp ++;
                    est_sha256_challenge_isr[est_i2c_temp] = slave_buff_rx[4];
                    if( 0x3f == slave_buff_rx[1] ) { // receive data over
                        est_sha256_en_isr ++;
                        est_sha256_cha_isr_len = (slave_buff_rx[2] & 0x3f);
                        est_sha256_cha_mode_0 = slave_buff_rx[3];
                        est_sha256_cha_mode_1 = slave_buff_rx[4];
                    }
                }
            }
            else if( WM_CMD_READ_COIN_COUNT == slave_buff_rx[0] ) {
                if( GPIO_MAX > slave_buff_rx[1] ) {
                    slave_buff_tx[0] = slave_buff_rx[0];
                    slave_buff_tx[1] = slave_buff_rx[1];
                    slave_buff_tx[2] = ((vInput_coin_count[slave_buff_rx[1]] >> 8) & 0xff);
                    slave_buff_tx[3] = (vInput_coin_count[slave_buff_rx[1]] & 0xff);
                    i2c_rx_buf_checksum = slave_buff_tx[0];
                    i2c_rx_buf_checksum += slave_buff_tx[1];
                    i2c_rx_buf_checksum += slave_buff_tx[2];
                    i2c_rx_buf_checksum += slave_buff_tx[3];
                    slave_buff_tx[4] = i2c_rx_buf_checksum;
                    slave_buff_tx[5] = i2c_rx_buf_checksum;
                }
            }
            else if( WM_CMD_SET_COIN_OUT_DELAY == slave_buff_rx[0] ) {
                if( GPIO_MAX > slave_buff_rx[1] ) {
                    est_i2c_temp = slave_buff_rx[2];
                    est_i2c_temp <<= 8;
                    est_i2c_temp += slave_buff_rx[3];
                    vInput_coin_out_port_delay[slave_buff_rx[1]] = est_i2c_temp;
                }
            }
            else if( WM_CMD_ENABLE_NEXT_INPUT == slave_buff_rx[0] ) {
                vInput_SdIIC_valid = 0;    /* wait for next input key */
            }
            else if( WM_CMD_READ_VERSION == slave_buff_rx[0] ) {
                slave_buff_tx[0] = slave_buff_rx[0];
                slave_buff_tx[1] = slave_buff_rx[1];
                slave_buff_tx[2] = boot_fw;
                slave_buff_tx[3] = WM_KEYBOARD_ID;
                i2c_rx_buf_checksum = slave_buff_tx[0];
                i2c_rx_buf_checksum += slave_buff_tx[1];
                i2c_rx_buf_checksum += slave_buff_tx[2];
                i2c_rx_buf_checksum += slave_buff_tx[3];
                slave_buff_tx[4] = i2c_rx_buf_checksum;
                slave_buff_tx[5] = i2c_rx_buf_checksum;
            }
            slave_buff_rx[0] = 0x00; // 20190920 jone ++
            slave_buff_rx[1] = 0x00; // 20190920 jone ++
            slave_buff_rx[2] = 0x00; // 20190920 jone ++
            slave_buff_rx[3] = 0x00; // 20190920 jone ++
        } // 20190920 jone ++
        else { // 20190920 jone ++
            i2c_rx_buf_checksum = 0x00; // 20190920 jone ++
            slave_buff_rx[0] = 0x00; // 20190920 jone ++
            slave_buff_rx[1] = 0x00; // 20190920 jone ++
            slave_buff_rx[2] = 0x00; // 20190920 jone ++
            slave_buff_rx[3] = 0x00; // 20190920 jone ++
        }
    }
    if( i2c_isr_tx_end ) { // mcu send data over
        if( i2c_isr_tx_read ) { // cpu read input triged by int
            vInput_SdIIC_valid = 0; // enable next data packet
            i2c_isr_tx_read = 0;
        }
    }
    i2c_isr_rx_end = 0;
    i2c_isr_tx_end = 0;

}


void TMR1_IRQHandler(void)
{
    if( TIMER_GetIntFlag(TIMER1) == 1 ) {
        /* Clear Timer1 time-out interrupt flag */
        TIMER_ClearIntFlag(TIMER1);
        est_timer1_count ++;
        if( ADC_GET_INT_FLAG(ADC, ADC_ADF_INT) ) { // adc convert ok
            ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);
            est_0_adc[est_index] = ADC_GET_CONVERSION_DATA(ADC, 0);
            est_1_adc[est_index] = ADC_GET_CONVERSION_DATA(ADC, 1);
            ADC_START_CONV(ADC);
            est_index ++;
            est_index &= 0x0f;
            if( 0 == est_index ) {
                est_adc[0] = 0;
                est_adc[1] = 0;
                for( est_adc_temp = 0; 16 > est_adc_temp; est_adc_temp ++ ) {
                    est_adc[0] += est_0_adc[est_adc_temp];
                    est_adc[1] += est_1_adc[est_adc_temp];
                }
                est_adc[0] >>= 4;
                est_adc[1] >>= 4;
            }
        }
    }

}
void UART0_IRQHandler(void)
{
    /*----- Determine interrupt source -----*/
    uint32_t u32IntSrc = UART0->ISR;

    if (u32IntSrc & UART_ISR_RDA_INT_Msk) {
        uart_rcvbuf[buf_in] = UART0->RBR;
        buf_in ++;
        buf_in &= 0x3f;
    }
}


使用特权

评论回复
16
hyjing001|  楼主 | 2019-12-19 16:34 | 只看该作者
用镊子夹复位脚后,lprom的io信号没有发出,好像是程序没有跑,是不是晶振异常?重新烧程序进去仿真变成正常的了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

8

帖子

0

粉丝