blob: 78c3d09e61e9bf23a492a23a1533c78f475d9c0a [file] [log] [blame]
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Standard C Included Files */
#include <string.h>
/* FreeRTOS kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "semphr.h"
/* SDK Included Files */
#include "board.h"
#include "fsl_debug_console.h"
#include "fsl_i2c.h"
#include "fsl_i2c_freertos.h"
#include "pin_mux.h"
#include "clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define EXAMPLE_I2C_MASTER_BASE I2C2
#define EXAMPLE_I2C_MASTER_IRQN I2C2_IRQn
#define EXAMPLE_I2C_MASTER_CLK_FREQ \
CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / (CLOCK_GetRootPreDivider(kCLOCK_RootI2c2)) / \
(CLOCK_GetRootPostDivider(kCLOCK_RootI2c2)) / 5 /* SYSTEM PLL1 DIV5 */
#define EXAMPLE_I2C_SLAVE_BASE I2C2
#define EXAMPLE_I2C_SLAVE_IRQN I2C2_IRQn
#define EXAMPLE_I2C_SLAVE_CLK_FREQ \
CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / (CLOCK_GetRootPreDivider(kCLOCK_RootI2c2)) / \
(CLOCK_GetRootPostDivider(kCLOCK_RootI2c2)) / 5 /* SYSTEM PLL1 DIV5 */
#define SINGLE_BOARD 0
#define BOARD_TO_BOARD 1
#define EXAMPLE_CONNECT_I2C BOARD_TO_BOARD
#if (EXAMPLE_CONNECT_I2C == BOARD_TO_BOARD)
#define isMASTER 0
#define isSLAVE 1
#define I2C_MASTER_SLAVE isMASTER
#endif
#if (EXAMPLE_CONNECT_I2C == BOARD_TO_BOARD)
#define EXAMPLE_I2C_DEALY_COUNT 1000u
#endif
#define EXAMPLE_I2C_MASTER ((I2C_Type *)EXAMPLE_I2C_MASTER_BASE)
#define EXAMPLE_I2C_SLAVE ((I2C_Type *)EXAMPLE_I2C_SLAVE_BASE)
#define I2C_MASTER_SLAVE_ADDR_7BIT (0x7EU)
#define I2C_BAUDRATE (100000) /* 100K */
#define I2C_DATA_LENGTH (32) /* MAX is 256 */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
uint8_t g_slave_buff[I2C_DATA_LENGTH];
uint8_t g_master_buff[I2C_DATA_LENGTH];
i2c_master_handle_t *g_m_handle;
i2c_slave_handle_t g_s_handle;
SemaphoreHandle_t i2c_sem;
/*******************************************************************************
* Definitions
******************************************************************************/
/* Task priorities. */
#define slave_task_PRIORITY (configMAX_PRIORITIES - 1)
#define master_task_PRIORITY (configMAX_PRIORITIES - 2)
/*******************************************************************************
* Prototypes
******************************************************************************/
static void slave_task(void *pvParameters);
#if ((I2C_MASTER_SLAVE == isMaster) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
static void master_task(void *pvParameters);
#endif
/*******************************************************************************
* Code
******************************************************************************/
int main(void)
{
/* Init board hardware. */
/* Board specific RDC settings */
BOARD_RdcInit();
BOARD_InitBootPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
BOARD_InitMemory();
CLOCK_SetRootMux(kCLOCK_RootI2c2, kCLOCK_I2cRootmuxSysPll1Div5); /* Set I2C source to SysPLL1 Div5 160MHZ */
CLOCK_SetRootDivider(kCLOCK_RootI2c2, 1U, 4U); /* Set root clock to 160MHZ / 4 = 40MHZ */
NVIC_SetPriority(EXAMPLE_I2C_SLAVE_IRQN, 2);
NVIC_SetPriority(EXAMPLE_I2C_MASTER_IRQN, 3);
PRINTF("\r\n==FreeRTOS I2C example start.==\r\n");
#if (EXAMPLE_CONNECT_I2C == SINGLE_BOARD)
PRINTF("This example use one i2c instance as master and another as slave on one board.\r\n");
#elif (EXAMPLE_CONNECT_I2C == BOARD_TO_BOARD)
PRINTF("This example use two boards to connect with one as master and another as slave.\r\n");
#endif
if (xTaskCreate(slave_task, "Slave_task", configMINIMAL_STACK_SIZE + 100, NULL, slave_task_PRIORITY, NULL) !=
pdPASS)
{
PRINTF("Failed to create slave task");
while (1)
;
}
vTaskStartScheduler();
for (;;)
;
}
/*!
* @brief Data structure and callback function for slave I2C communication.
*/
typedef struct _callback_message_t
{
status_t async_status;
SemaphoreHandle_t sem;
} callback_message_t;
#if (I2C_MASTER_SLAVE == isSLAVE)
static void i2c_slave_callback(I2C_Type *base, i2c_slave_transfer_t *xfer, void *userData)
{
callback_message_t *cb_msg = (callback_message_t *)userData;
BaseType_t reschedule = 0;
switch (xfer->event)
{
/* Transmit request */
case kI2C_SlaveTransmitEvent:
/* Update information for transmit process */
xfer->data = g_slave_buff;
xfer->dataSize = I2C_DATA_LENGTH;
break;
/* Receive request */
case kI2C_SlaveReceiveEvent:
/* Update information for received process */
xfer->data = g_slave_buff;
xfer->dataSize = I2C_DATA_LENGTH;
break;
/* Transfer done */
case kI2C_SlaveCompletionEvent:
cb_msg->async_status = xfer->completionStatus;
xSemaphoreGiveFromISR(cb_msg->sem, &reschedule);
portYIELD_FROM_ISR(reschedule);
break;
default:
break;
}
}
#endif
/*!
* @brief Task responsible for slave I2C communication.
*/
static void slave_task(void *pvParameters)
{
#if ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
i2c_slave_config_t slaveConfig;
#endif
callback_message_t cb_msg = {0};
cb_msg.sem = xSemaphoreCreateBinary();
if (cb_msg.sem == NULL)
{
PRINTF("I2C slave: Error creating semaphore\r\n");
vTaskSuspend(NULL);
}
i2c_sem = cb_msg.sem;
#if ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
/* Set up I2C slave */
/*
* slaveConfig.addressingMode = kI2C_Address7bit;
* slaveConfig.enableGeneralCall = false;
* slaveConfig.enableWakeUp = false;
* slaveConfig.enableBaudRateCtl = false;
* slaveConfig.enableSlave = true;
*/
I2C_SlaveGetDefaultConfig(&slaveConfig);
slaveConfig.slaveAddress = I2C_MASTER_SLAVE_ADDR_7BIT;
#if defined(FSL_FEATURE_SOC_I2C_COUNT) && FSL_FEATURE_SOC_I2C_COUNT
slaveConfig.addressingMode = kI2C_Address7bit;
slaveConfig.upperAddress = 0; /* not used for this example */
I2C_SlaveInit(EXAMPLE_I2C_SLAVE, &slaveConfig, EXAMPLE_I2C_SLAVE_CLK_FREQ);
#endif
#if defined(FSL_FEATURE_SOC_II2C_COUNT) && FSL_FEATURE_SOC_II2C_COUNT
I2C_SlaveInit(EXAMPLE_I2C_SLAVE, &slaveConfig);
#endif
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
g_slave_buff[i] = 0;
}
memset(&g_s_handle, 0, sizeof(g_s_handle));
I2C_SlaveTransferCreateHandle(EXAMPLE_I2C_SLAVE, &g_s_handle, i2c_slave_callback, &cb_msg);
I2C_SlaveTransferNonBlocking(EXAMPLE_I2C_SLAVE, &g_s_handle, kI2C_SlaveCompletionEvent);
#endif /* ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD)) */
#if ((I2C_MASTER_SLAVE == isMASTER) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
if (xTaskCreate(master_task, "Master_task", configMINIMAL_STACK_SIZE + 124, NULL, master_task_PRIORITY, NULL) !=
pdPASS)
{
PRINTF("Failed to create master task");
vTaskSuspend(NULL);
}
#endif /* ((I2C_MASTER_SLAVE == isMASTER) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD)) */
/* Wait for transfer to finish */
if (xSemaphoreTake(cb_msg.sem, portMAX_DELAY) != pdTRUE)
{
PRINTF("Failed to take semaphore.\r\n");
}
#if ((I2C_MASTER_SLAVE == isSLAVE) || (EXAMPLE_CONNECT_DSPI == SINGLE_BOARD))
if (cb_msg.async_status == kStatus_Success)
{
PRINTF("I2C slave transfer completed successfully. \r\n\r\n");
}
else
{
PRINTF("I2C slave transfer completed with error. \r\n\r\n");
}
#if (EXAMPLE_CONNECT_I2C == SINGLE_BOARD)
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
if (g_slave_buff[i] != g_master_buff[i])
{
PRINTF("\r\nError occurred in this transfer ! \r\n");
break;
}
}
#endif
PRINTF("Slave received data :");
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", g_slave_buff[i]);
}
PRINTF("\r\n\r\n");
#if (EXAMPLE_CONNECT_I2C == SINGLE_BOARD)
/* Set up slave ready to send data to master. */
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
g_slave_buff[i] = ~g_slave_buff[i];
}
PRINTF("This time , slave will send data: :");
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", g_slave_buff[i]);
}
PRINTF("\r\n\r\n");
#endif
#endif
/* Wait for transfer to finish */
if (xSemaphoreTake(cb_msg.sem, portMAX_DELAY) != pdTRUE)
{
PRINTF("Failed to take semaphore.\r\n");
}
#if (EXAMPLE_CONNECT_I2C == BOARD_TO_BOARD)
PRINTF("\r\nEnd of FreeRTOS I2C example.\r\n");
#endif
vTaskSuspend(NULL);
}
#if ((I2C_MASTER_SLAVE == isMaster) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))
static void master_task(void *pvParameters)
{
i2c_rtos_handle_t master_rtos_handle;
i2c_master_config_t masterConfig;
i2c_master_transfer_t masterXfer;
uint32_t sourceClock;
status_t status;
/* Set up i2c master to send data to slave */
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
g_master_buff[i] = i;
}
PRINTF("Master will send data :");
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", g_master_buff[i]);
}
PRINTF("\r\n\r\n");
/*
* masterConfig.baudRate_Bps = 100000U;
* masterConfig.enableStopHold = false;
* masterConfig.glitchFilterWidth = 0U;
* masterConfig.enableMaster = true;
*/
I2C_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Bps = I2C_BAUDRATE;
sourceClock = EXAMPLE_I2C_MASTER_CLK_FREQ;
status = I2C_RTOS_Init(&master_rtos_handle, EXAMPLE_I2C_MASTER, &masterConfig, sourceClock);
if (status != kStatus_Success)
{
PRINTF("I2C master: error during init, %d", status);
}
g_m_handle = &master_rtos_handle.drv_handle;
memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = I2C_MASTER_SLAVE_ADDR_7BIT;
masterXfer.direction = kI2C_Write;
masterXfer.subaddress = 0;
masterXfer.subaddressSize = 0;
masterXfer.data = g_master_buff;
masterXfer.dataSize = I2C_DATA_LENGTH;
masterXfer.flags = kI2C_TransferDefaultFlag;
status = I2C_RTOS_Transfer(&master_rtos_handle, &masterXfer);
if (status != kStatus_Success)
{
PRINTF("I2C master: error during write transaction, %d", status);
}
#if (EXAMPLE_CONNECT_I2C == BOARD_TO_BOARD)
/* Delay to wait slave is ready */
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
#endif
/* Set up master to receive data from slave. */
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
g_master_buff[i] = 0;
}
masterXfer.slaveAddress = I2C_MASTER_SLAVE_ADDR_7BIT;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = 0;
masterXfer.subaddressSize = 0;
masterXfer.data = g_master_buff;
masterXfer.dataSize = I2C_DATA_LENGTH;
masterXfer.flags = kI2C_TransferDefaultFlag;
status = I2C_RTOS_Transfer(&master_rtos_handle, &masterXfer);
if (status != kStatus_Success)
{
PRINTF("I2C master: error during read transaction, %d", status);
}
#if (EXAMPLE_CONNECT_DSPI == BOARD_TO_BOARD)
else
{
xSemaphoreGive(i2c_sem);
}
#endif
#if (EXAMPLE_CONNECT_I2C == SINGLE_BOARD)
/* Transfer completed. Check the data. */
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
if (g_slave_buff[i] != g_master_buff[i])
{
PRINTF("\r\nError occurred in the transfer ! \r\n");
break;
}
}
#endif
PRINTF("Master received data :");
for (uint32_t i = 0; i < I2C_DATA_LENGTH; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", g_master_buff[i]);
}
PRINTF("\r\n\r\n");
PRINTF("\r\nEnd of FreeRTOS I2C example.\r\n");
vTaskSuspend(NULL);
}
#endif //((I2C_MASTER_SLAVE == isMaster) || (EXAMPLE_CONNECT_I2C == SINGLE_BOARD))