- /**************************************************************************//**
- * [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);
- }
- }
- }
- }