打印
[DemoCode下载]

I3C你用过吗,快来看看

[复制链接]
185|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wahahaheihei|  楼主 | 2024-1-28 18:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
* [url=home.php?mod=space&uid=247401]@brief[/url]    Demonstrate how to use I3C0 Slave to reveive and transmit the data from a Master.
*
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] SPDX-License-Identifier: Apache-2.0
* @copyright Copyright (C) 2022 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include "NuMicro.h"


//#define DGBINT          printf
#define DGBINT(...)

/*---------------------------------------------------------------------------------------------------------*/
/* Functions and variables declaration                                                                     */
/*---------------------------------------------------------------------------------------------------------*/
#define I3CS0_SA        (0x68)
#define I3CS0_MID       (0x8123UL)
#define I3CS0_PID       (0xA13573C0UL)

volatile uint32_t   g_RespQ[I3CS_DEVICE_RESP_QUEUE_CNT];
volatile uint32_t   g_RxBuf[I3CS_DEVICE_RX_BUF_CNT], g_TxBuf[I3CS_DEVICE_RX_BUF_CNT];
volatile uint32_t   g_u32IntSelMask = 0, g_u32IntOccurredMask = 0;
volatile uint32_t   g_u32RespStatus = I3CS_STS_NO_ERR;

int32_t I3CS_ProcessNoneRespInt(I3CS_T *i3cs, uint32_t i32IntMask);
int32_t I3CS_ProcessRespError(I3CS_T *i3cs, uint32_t u32RespStatus);
void I3CS0_IRQHandler(void);
void SYS_Init(void);
void UART_Init(void);


/**
  * @brief  Process interrupt events except Response Ready interrupt.
  */
int32_t I3CS_ProcessNoneRespInt(I3CS_T *i3cs, uint32_t u32IntMask)
{
    if(u32IntMask & I3CS_INTEN_DA_ASSIGNED)
        printf("[ Set I3C Dynamic Address 0x%02x ]\n\n", (uint32_t)I3CS_GET_I3CS_DA(i3cs));
    if(u32IntMask & I3CS_INTEN_TRANSFER_ERR)
        printf("[ Transfer error ]\n\n");
    if(u32IntMask & I3CS_INTEN_READ_REQUEST)
        printf("[ Master read request event ]\n\n");
    if(u32IntMask & I3CS_INTEN_CCC_UPDATED)
    {
        printf("[ CCC Updated event ]\n");
        if(i3cs->SLVEVNTS & I3CS_SLVEVNTS_MWLUPD_Msk)
        {
            i3cs->SLVEVNTS = I3CS_SLVEVNTS_MWLUPD_Msk;
            printf("\t* Updated MWL to 0x%x\n\n", (uint32_t)((i3cs->SLVMXLEN&I3CS_SLVMXLEN_MWL_Msk) >> I3CS_SLVMXLEN_MWL_Pos));
        }
        else if(i3cs->SLVEVNTS & I3CS_SLVEVNTS_MRLUPD_Msk)
        {
            i3cs->SLVEVNTS = I3CS_SLVEVNTS_MRLUPD_Msk;
            printf("\t* Updated MRL to 0x%x\n\n", (uint32_t)((i3cs->SLVMXLEN&I3CS_SLVMXLEN_MRL_Msk) >> I3CS_SLVMXLEN_MRL_Pos));
            /* Reset TX FIFO and CMDQ FIFO -> apply resume */
            I3CS_ResetAndResume(i3cs, (I3CS_RESET_TX_BUF | I3CS_RESET_CMD_QUEUE), TRUE);
        }
        else
        {
            printf("\t* Updated - ENTAS%d\n", (uint32_t)((i3cs->SLVEVNTS&I3CS_SLVEVNTS_ACTSTATE_Msk) >> I3CS_SLVEVNTS_ACTSTATE_Pos));
            printf("\t* Updated - HJEN %d\n", (uint32_t)((i3cs->SLVEVNTS&I3CS_SLVEVNTS_HJEN_Msk) >> I3CS_SLVEVNTS_HJEN_Pos));
            printf("\t* Updated - SIREN %d\n", (uint32_t)((i3cs->SLVEVNTS&I3CS_SLVEVNTS_SIREN_Msk) >> I3CS_SLVEVNTS_SIREN_Pos));
        }
    }
   
    return 0;
}

/**
  * @brief  Process response error event.
  */
int32_t I3CS_ProcessRespError(I3CS_T *i3cs, uint32_t u32RespStatus)
{
    printf("[ Resp Error 0x%x] ", (u32RespStatus >> I3CS_RESPQUE_ERRSTS_Pos));
    if(u32RespStatus == I3CS_RESP_CRC_ERR)            
        printf("CRC error\n");
    else if(u32RespStatus == I3CS_RESP_PARITY_ERR)
        printf("Parity error\n");
    else if(u32RespStatus == I3CS_RESP_FRAME_ERRR)
        printf("Frame error\n");
    else if(u32RespStatus == I3CS_RESP_FLOW_ERR)
        printf("Underflow/Overflow error\n");
    else if(u32RespStatus == I3CS_RESP_MASTER_TERMINATE_ERR)
        printf("Master early termination error\n");
    else
        printf("Unknow error\n");

    if(I3CS_IS_PROTOCOL_ERR(i3cs))
        printf("[ Device Protocol Error ] (0x%04x)\n\n", I3CS_GET_DEVICE_STATUS(i3cs));
    if(I3CS_IS_UNDERFLOW_ERR(i3cs))
        printf("[ Device Underflow Error ] (0x%04x)\n\n", I3CS_GET_DEVICE_STATUS(i3cs));
    if(I3CS_IS_OVERFLOW_ERR(i3cs))
        printf("[ Device Overflow Error ] (0x%04x)\n\n", I3CS_GET_DEVICE_STATUS(i3cs));
    if(I3CS_IS_DATA_NOT_READY(i3cs))
        printf("[ Device Data Not Ready Status ] (0x%04x)\n\n", I3CS_GET_DEVICE_STATUS(i3cs));
    if(I3CS_IS_BUFFER_NOT_AVAIL(i3cs))
        printf("[ Device Buffer Not Available Status ] (0x%04x)\n\n", I3CS_GET_DEVICE_STATUS(i3cs));
    if(I3CS_IS_FRAME_ERR(i3cs))
        printf("[ Device Frame Error ] (0x%04x)\n\n", I3CS_GET_DEVICE_STATUS(i3cs));
    if(I3CS_IS_SLAVE_BUSY(i3cs))
    {   
        printf("[ Device Slave Busy Status ] (0x%04x)\n\n", I3CS_GET_DEVICE_STATUS(i3cs));
        printf("\tPerform FIFO/Queue reset then wait RESUME complete ... ");
        I3CS_RespErrorRecovery(I3CS0, g_u32RespStatus);
        printf("done.\n\n");
    }
   
    return 0;
}

/**
  * @brief  The I3CS0 default IRQ, declared in startup_NUC1263.s.
  */
void I3CS0_IRQHandler(void)
{   
    DGBINT("\n");
   
    if(g_u32IntSelMask & I3CS_INTEN_TX_EMPTY_THLD)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_TX_EMPTY_THLD))
        {
            DGBINT("[ INT ] TX_EMPTY_THLD\n");
            g_u32IntOccurredMask |= I3CS_INTSTS_TX_EMPTY_THLD;
        }        
    }
   
    if(g_u32IntSelMask & I3CS_INTEN_RX_THLD)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_RX_THLD))
        {
            DGBINT("[ INT ] INTSTS_RX_THLD\n");
            g_u32IntOccurredMask |= I3CS_INTSTS_RX_THLD;
        }
    }
   
    if(g_u32IntSelMask & I3CS_INTEN_CMDQ_EMPTY_THLD)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_CMDQ_EMPTY_THLD))
        {
            DGBINT("[ INT ] CMDQ_EMPTY_THLD\n");        
            g_u32IntOccurredMask |= I3CS_INTSTS_CMDQ_EMPTY_THLD;
        }
    }
        
    if(g_u32IntSelMask & I3CS_INTEN_RESPQ_READY)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_RESPQ_READY))
        {
            DGBINT("[ INT ] RESPQ_READY\n");        
            g_u32IntOccurredMask |= I3CS_INTSTS_RESPQ_READY;
        }
    }
        
    if(g_u32IntSelMask & I3CS_INTEN_CCC_UPDATED)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_CCC_UPDATED))
        {
            DGBINT("[ INT ] CCC_UPDATED\n");
            I3CS_CLEAR_CCC_UPDATED_STATUS(I3CS0);
            g_u32IntOccurredMask |= I3CS_INTSTS_CCC_UPDATED;
        }
    }
        
    if(g_u32IntSelMask & I3CS_INTEN_DA_ASSIGNED)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_DA_ASSIGNED))
        {
            DGBINT("[ INT ] DA_ASSIGNED\n");
            I3CS_CLEAR_DA_ASSIGNED_STATUS(I3CS0);
            g_u32IntOccurredMask |= I3CS_INTSTS_DA_ASSIGNED;
        }        
    }
        
    if(g_u32IntSelMask & I3CS_INTEN_TRANSFER_ERR)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_TRANSFER_ERR))
        {
            DGBINT("[ INT ] TRANSFER_ERR\n");
            I3CS_CLEAR_TRANSFER_ERR_STATUS(I3CS0);
            g_u32IntOccurredMask |= I3CS_INTSTS_TRANSFER_ERR;
        }      
    }
        
    if(g_u32IntSelMask & I3CS_INTEN_READ_REQUEST)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_READ_REQUEST))
        {
            DGBINT("[ INT ] READ_REQUEST\n");
            I3CS_CLEAR_READ_REQUEST_STATUS(I3CS0);
            g_u32IntOccurredMask |= I3CS_INTSTS_READ_REQUEST;
        }        
    }
        
    if(g_u32IntSelMask & I3CS_INTEN_IBI_UPDATED)
    {
        if(I3CS_IS_INT_STATUS(I3CS0, I3CS_INTSTS_IBI_UPDATED))
        {
            DGBINT("[ INT ] IBI_UPDATED\n");
            I3CS_CLEAR_IBI_UPDATED_STATUS(I3CS0);
            g_u32IntOccurredMask |= I3CS_INTSTS_IBI_UPDATED;
        }        
    }
   
    if(g_u32IntOccurredMask & I3CS_INTSTS_RESPQ_READY)
    {
        g_u32RespStatus = (uint32_t)I3CS_ParseRespQueue(I3CS0, (uint32_t *)(&g_RespQ[0]));
    }
        
    DGBINT("[ INT EXIT ] INTSTS: 0x%08x. Occurred: 0x%08x.\n\n", I3CS0->INTSTS, g_u32IntOccurredMask);
}

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Enable HIRC clock */
    CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

    /* Wait for HIRC clock ready */
    CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

    /* Set core clock to 72MHz */
    CLK_SetCoreClock(72000000);
   
    /* Enable UART0 module clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Select UART0 module clock source as HIRC/2 and UART0 module clock divider as 1 */
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC_DIV2, CLK_CLKDIV0_UART0(1));

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Set multi-function pins for UART0 RXD and TXD */
    SET_UART0_RXD_PB12();
    SET_UART0_TXD_PB13();

    /*---------------------------------------------------------------------------------------------------------*/
    /* Initialization for sample code                                                                          */
    /*---------------------------------------------------------------------------------------------------------*/   
    /* Enable peripheral clock */
    CLK_EnableModuleClock(I3CS0_MODULE);

    /* Set multi-function pins for I3CS0 pin */
    SET_I3CS0_SDA_PA0();
    SET_I3CS0_SCL_PA1();
}

void UART_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset UART module */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 Baudrate */
    UART_Open(UART0, 115200);
}
                                                                                                                               
/*---------------------------------------------------------------------------------------------------------*/
/*  MAIN function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int main(void)
{
    uint16_t    i, u16Len;
    uint8_t     *pu8Data, u8TID;
    uint8_t     qn, u8RespQCnt;
    uint32_t    u32ActiveIntMask;
    int32_t     iErrCode = I3CS_STS_NO_ERR;

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Init System, peripheral clock and multi-function I/O */
    SYS_Init();

    /* Init UART0 for printf */
    UART_Init();
   
    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
    printf("+----------------------------------------+\n");
    printf("|    I3C0 Slave Read/Write Sample Code   |\n");
    printf("+----------------------------------------+\n\n");
            
    /* Reset I3CS0 module */
    SYS_ResetModule(I3CS0_RST);
   
    /* Initial I3CS0 default settings */
    I3CS0->SLVMID = I3CS0_MID;
    I3CS0->SLVPID = I3CS0_PID;
    I3CS_Open(I3CS0, I3CS0_SA, I3CS_SUPPORT_ENTDAA);
   
    /* Enable I3CS0 interrupts */
    g_u32IntSelMask = (I3CS_INTEN_RESPQ_READY | I3CS_INTEN_CCC_UPDATED | I3CS_INTEN_DA_ASSIGNED |
                        I3CS_INTEN_TRANSFER_ERR | I3CS_INTEN_READ_REQUEST);
    I3CS_ENABLE_INT(I3CS0, g_u32IntSelMask);
    NVIC_EnableIRQ(I3CS0_IRQn);

    /* Enable I3CS0 controller */
    I3CS_Enable(I3CS0);

    printf("# I3C0 Slave settings:\n");
    printf("    - SDA on PA.0\n");
    printf("    - SCL on PA.1\n");
    printf("    - I2C Static Address 0x%02x\n", I3CS0_SA);
    printf("    - RespQ interrupt threshold %d\n", (uint32_t)(I3CS_GET_RESPQ_THLD(I3CS0) + 1));
    printf("    - The first operation of the I3CS enable bit requires at least bus SCLx4 to become active\n");
    printf("# An I3C Master can write N-bytes data to Slave,\n");
    printf("  then perform a read request to receive the N-bytes data from Slave.\n");
    printf("    - The write data should be equal to the received data\n");
    printf("\n");
        
        
    while(1)
    {
        while(g_u32IntOccurredMask != 0)
        {
            /* Get active interrupt **ents */
            u32ActiveIntMask = g_u32IntOccurredMask;
            g_u32IntOccurredMask = 0;
            
            if(u32ActiveIntMask & I3CS_INTSTS_RESPQ_READY)
            {
                /* Process Response */

                if(g_u32RespStatus == I3CS_STS_NO_ERR)
                {
                    /* Response no error */
                    
                    u8RespQCnt = I3CS_GET_RESPQ_THLD(I3CS0) + 1;
                    
                    qn = 0; // Queue number
                    do {
                        if(I3CS_IS_RESP_RX(g_RespQ[qn]))
                        {
                            /* Master write request */
                                                        
                            u16Len = I3CS_GET_RESP_DATA_LEN(g_RespQ[qn]);
                            printf("Slave receives %d-bytes:\n\thex: ", u16Len);
                            /* Read Rx data from data port */
                            for(i=0; i<((u16Len+3)/4); i++)
                                g_RxBuf[i] = I3CS0->TXRXDAT;
                            pu8Data = (uint8_t *)(&g_RxBuf[0]);
                            for(i=0; i<u16Len; i++)
                                printf("%02x ", pu8Data[i]);
                            printf("\n\n");
                           
                            /* Set CmdQ and response data for a Master read request */
                            memcpy((uint8_t *)(&g_TxBuf[0]), (uint8_t *)(&g_RxBuf[0]), u16Len);
                            u8TID = (pu8Data[0] % 8);
                            iErrCode = I3CS_SetCmdQueueAndData(I3CS0, u8TID, (uint32_t *)&g_TxBuf[0], u16Len);
                            if(iErrCode != I3CS_STS_NO_ERR)
                                printf("\tSet TX data error, %d.\n\n", iErrCode);
                            else
                                printf("[ Set TX %d-bytes and TID %d for Master read request ]\n\n", u16Len, u8TID);
                        }
                        else
                        {
                            /* Master read request -> Slave transmits data done */
                            printf("Slave transmits ID-%d done.\n\n", (uint32_t)I3CS_GET_RESP_TID(g_RespQ[qn]));                        
                        }
                        
                        qn++;                        
                        u8RespQCnt--;
                    }while(u8RespQCnt);
                }
                else
                {                    
                    /* Response has error */
                    
                    I3CS_ProcessRespError(I3CS0, g_u32RespStatus);
                }
                    
                g_u32RespStatus = I3CS_STS_NO_ERR;
            }
            else
            {                                                   
                /* Process others interrupt event */
               
                I3CS_ProcessNoneRespInt(I3CS0, u32ActiveIntMask);
            }
        }
    }
}


使用特权

评论回复
沙发
wahahaheihei|  楼主 | 2024-1-28 18:44 | 只看该作者
I3C,全称为"Improved Inter-Integrated Circuit",是一种串行通信接口标准,旨在提供一种更高性能、更灵活且更节省能源的替代方案,用于连接芯片之间的通信。I3C 的设计目标是兼容现有的I2C(Inter-Integrated Circuit)和SMBus(System Management Bus)标准,同时增加新的特性和改进性能。

使用特权

评论回复
板凳
wahahaheihei|  楼主 | 2024-1-28 18:44 | 只看该作者
高性能和更高的数据传输速率: I3C支持更高的数据传输速率,相较于I2C,它提供更高的带宽和更短的传输时间。

使用特权

评论回复
地板
wahahaheihei|  楼主 | 2024-1-28 18:44 | 只看该作者
多主机和多从机支持: I3C引入了一种更灵活的多主机体系结构,允许多个主机设备同时与总线通信,同时支持多个从机设备。

使用特权

评论回复
5
wahahaheihei|  楼主 | 2024-1-28 18:44 | 只看该作者
动态地址分配: I3C支持动态地址分配,从而更好地管理总线上的设备地址,提高系统的可扩展性和灵活性。

使用特权

评论回复
6
wahahaheihei|  楼主 | 2024-1-28 18:44 | 只看该作者
硬件层级控制: I3C引入了硬件层级控制的概念,使得总线上的设备能够根据其在系统中的地位进行动态配置和控制。

使用特权

评论回复
7
wahahaheihei|  楼主 | 2024-1-28 18:45 | 只看该作者
低功耗: I3C设计时考虑了能源效率,支持低功耗操作,有助于延长设备电池寿命。

使用特权

评论回复
8
wahahaheihei|  楼主 | 2024-1-28 18:45 | 只看该作者
传感器融合: I3C在设计时特别关注传感器融合,为连接各种传感器提供了更好的支持,使得传感器网络更容易集成到系统中。

使用特权

评论回复
9
wahahaheihei|  楼主 | 2024-1-28 18:45 | 只看该作者
总体而言,I3C是一个面向未来的、先进的串行通信标准,旨在满足不断增长的设备互联和通信的需求。它保留了I2C和SMBus的兼容性,同时引入了许多新的特性,使得设备之间的通信更为高效和灵活。

使用特权

评论回复
10
埃娃| | 2024-1-29 10:19 | 只看该作者
这个是什么方面用的多啊

使用特权

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

本版积分规则

200

主题

2982

帖子

12

粉丝