211 lines
6.2 KiB
C
211 lines
6.2 KiB
C
/**
|
|
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
|
|
*/
|
|
/** @file main.c
|
|
*
|
|
* @author Wei-Lun Hsu
|
|
* @version 0.1
|
|
* @date 2024/08/29
|
|
* @license
|
|
* @description
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "main.h"
|
|
#include "isr.h"
|
|
//=============================================================================
|
|
// Constant Definition
|
|
//=============================================================================
|
|
/**
|
|
* if defined, transfer data using interrupt mode
|
|
* if not, transfer data using polling mode
|
|
*/
|
|
#define CONFIG_USE_I2C_INTERRUPT
|
|
|
|
#define CONFIG_REMOTE_I2C_ADDR 0xAA // slave address
|
|
#define CONFIG_DATA_BUF_LEN 64 // transmit data of length
|
|
|
|
/**
|
|
* Select I2C SCL and SDA pin
|
|
*/
|
|
#define IIC_SCL_PORT GPIOA
|
|
#define IIC_SCL_PIN GPIO_Pin_00
|
|
#define IIC_SCL_AF GPIO_AF_4
|
|
#define IIC_SDA_PORT GPIOA
|
|
#define IIC_SDA_PIN GPIO_Pin_01
|
|
#define IIC_SDA_AF GPIO_AF_4
|
|
|
|
#define I2Cx I2C0
|
|
#define I2Cx_IRQn I2C0_IRQn
|
|
|
|
#if defined(CONFIG_USE_I2C_INTERRUPT)
|
|
#define CONFIG_XFER_MODE "Interrupt"
|
|
#else
|
|
#define CONFIG_XFER_MODE "Polling"
|
|
#endif
|
|
//=============================================================================
|
|
// Macro Definition
|
|
//=============================================================================
|
|
|
|
//=============================================================================
|
|
// Structure Definition
|
|
//=============================================================================
|
|
|
|
//=============================================================================
|
|
// Global Data Definition
|
|
//=============================================================================
|
|
static uint8_t g_tx_buf[CONFIG_DATA_BUF_LEN] = {0};
|
|
static uint8_t g_rx_buf[CONFIG_DATA_BUF_LEN] = {0};
|
|
|
|
static I2C_IT_HandleTypeDef g_hI2CIT = {0};
|
|
//=============================================================================
|
|
// Private Function Definition
|
|
//=============================================================================
|
|
__INTERRUPT void I2Cx_Handler(void)
|
|
{
|
|
SAVE_IRQ_CSR_CONTEXT(); // Save CSRs
|
|
|
|
I2C_Slave_IRQHandler(&g_hI2CIT);
|
|
|
|
RESTORE_IRQ_CSR_CONTEXT(); // Restore CSRs
|
|
return;
|
|
}
|
|
|
|
|
|
/**
|
|
* Configure the pin of I2C
|
|
*/
|
|
static void _Config_IO(void)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
GPIO_InitStruct.GPIO_Pin = IIC_SCL_PIN;
|
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
|
|
GPIO_InitStruct.GPIO_AF_Mode = IIC_SCL_AF;
|
|
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
|
|
GPIO_Init(IIC_SCL_PORT, &GPIO_InitStruct);
|
|
GPIO_InitStruct.GPIO_Pin = IIC_SDA_PIN;
|
|
GPIO_InitStruct.GPIO_AF_Mode = IIC_SDA_AF;
|
|
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStruct);
|
|
|
|
return;
|
|
}
|
|
|
|
//=============================================================================
|
|
// Public Function Definition
|
|
//=============================================================================
|
|
int main(void)
|
|
{
|
|
SYSCFG_ClkInitTypeDef SysClkInit = {0};
|
|
I2C_ErrTypeDef rval = I2C_Err_OK;
|
|
int data_base = 0x50;
|
|
|
|
/* Configure system clock */
|
|
SysClkInit.ClkSource = SYSCFG_ClkSrc_FreqDiv;
|
|
SysClkInit.SysClk_Div = SYSCFG_SysClkDiv8;
|
|
SYSCFG_SysClkConfig(&SysClkInit);
|
|
|
|
sys_config_systick(SYS_TICK_1_MS);
|
|
|
|
syslog_init();
|
|
|
|
info("%s %s\nI2C-Slave (%s). The local Slave-Address is 0x%02X\n",
|
|
__DATE__, __TIME__, CONFIG_XFER_MODE, (CONFIG_REMOTE_I2C_ADDR >> 1));
|
|
|
|
/* Configure the pin of I2C */
|
|
_Config_IO();
|
|
|
|
/* Configure the parameters of I2C */
|
|
I2C_InitTypeDef init = {0};
|
|
I2C_StructInit(&init);
|
|
init.Mode = I2C_Mode_SLAVE;
|
|
init.OwnAddress = CONFIG_REMOTE_I2C_ADDR >> 1;
|
|
// init.ClockDiv = I2C_CLK_Div960;
|
|
rval = I2C_Init(I2Cx, &init);
|
|
if( rval != I2C_Err_OK )
|
|
{
|
|
err("I2C init fail !\n");
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_USE_I2C_INTERRUPT)
|
|
{ /* Setup Interrupt */
|
|
sys_irq_attr_t irq_attr = { .trig_mode = SYS_IRQ_TRIGGER_LEVEL, };
|
|
sys_register_IRQ(I2Cx_IRQn, I2Cx_Handler, &irq_attr);
|
|
|
|
g_hI2CIT.pHI2C = I2Cx;
|
|
}
|
|
#endif
|
|
|
|
do {
|
|
/* prepare data */
|
|
data_base++;
|
|
for(int i = 0; i < sizeof(g_tx_buf); i++)
|
|
{
|
|
g_tx_buf[i] = (data_base + i) & 0xFF;
|
|
}
|
|
|
|
log_color(SLOG_GREEN, " @ Start Transmitting...\n");
|
|
syslog_dump_mem("tx: ", (uint32_t*)&g_tx_buf, sizeof(g_tx_buf), 0);
|
|
|
|
/* IIC slave receive and transmit data */
|
|
#if defined(CONFIG_USE_I2C_INTERRUPT)
|
|
rval = I2C_Slave_Receive_IT(&g_hI2CIT, (uint8_t*)&g_rx_buf, (uint16_t)sizeof(g_rx_buf));
|
|
if( rval != I2C_Err_OK )
|
|
{
|
|
err("I2C master TX fail !\n");
|
|
break;
|
|
}
|
|
|
|
while( g_hI2CIT.XferMode != I2C_XferMode_Idle )
|
|
__NOP();
|
|
|
|
rval = I2C_Slave_Transmit_IT(&g_hI2CIT, (uint8_t*)&g_tx_buf, (uint16_t)sizeof(g_tx_buf));
|
|
if( rval != I2C_Err_OK )
|
|
{
|
|
err("I2C master RX fail !\n");
|
|
break;
|
|
}
|
|
|
|
while( g_hI2CIT.XferMode != I2C_XferMode_Idle )
|
|
__NOP();
|
|
|
|
#else
|
|
uint16_t length = 0;
|
|
|
|
length = sizeof(g_rx_buf);
|
|
|
|
memset((void*)&g_rx_buf, 0xAA, sizeof(g_rx_buf));
|
|
|
|
rval = I2C_Slave_Receive(I2Cx, (uint8_t*)&g_rx_buf, &length, I2C_BLOCKING);
|
|
if( rval != I2C_Err_OK )
|
|
{
|
|
err("I2C slave RX fail !\n");
|
|
break;
|
|
}
|
|
|
|
rval = I2C_Slave_Transmit(I2Cx, (uint8_t*)&g_tx_buf, (uint16_t)sizeof(g_tx_buf), I2C_BLOCKING);
|
|
if( rval != I2C_Err_OK )
|
|
{
|
|
err("I2C slave TX fail !\n");
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
/* comparative data */
|
|
syslog_dump_mem("rx: ", (uint32_t*)&g_rx_buf, sizeof(g_rx_buf), 0);
|
|
|
|
if( !memcmp(g_tx_buf, g_rx_buf, sizeof(g_tx_buf)) )
|
|
msg("done~~ \n\n");
|
|
else
|
|
{
|
|
err("Data is NOT match !\n");
|
|
break;
|
|
}
|
|
|
|
} while(1);
|
|
|
|
|
|
while(1);
|
|
return 0;
|
|
}
|