I'm writing an application that communicates with multiple identical peripherals on different I2C busses using DMA.
I set up four Flexcomm interfaces (2,3,4,5) as I2C DMA, but am running into a small problem with the I2C DMA Handle User Data Pointer.
Since everything is identical I want a single callback function that receives a user data pointer, and since they're identical I'd like to make an array of data items.
i.e.
struct my_user_data user_data[4];
What I'm running into is that the Peripherals page won't let me use
&user_data[0]
as a valid user data pointer.
I seem to be forced to doing:
struct my_user_data *p_user_data_0 = &user_data[0];
struct my_user_data *p_user_data_1 = &user_data[1];
struct my_user_data *p_user_data_2 = &user_data[2];
struct my_user_data *p_user_data_3 = &user_data[3];
And using them in the peripherals page.
Is there an easier way to do this?
已解决! 转到解答。
Hi Hang,
This was the solution I provided in my initial post, yes?
So the correct answer is there is no way to directly put an array element in the Peripherals tab, you either
Correct?
Glenn
To streamline the use of a single callback function for multiple I2C peripherals with DMA, you can maintain an array of user data pointers and set them directly when initializing each I2C DMA handle. This approach avoids the need to declare individual pointer variables for each I2C instance.
1. Define the User Data Structure and Array:
Define your user data structure and create an array to store user data for each I2C instance.
struct my_user_data {
// Add your specific fields here
int some_field;
};
struct my_user_data user_data[4];
2. Declare the I2C DMA Handles:
Declare an array of i2c_master_dma_handle_t to store handles for each I2C instance.
i2c_master_dma_handle_t i2c_dma_handles[4];
3. Initialize I2C DMA Handles with a Loop:
Use a loop to initialize the I2C instances and set the user data pointers.
// Array of I2C base addresses for the Flexcomm interfaces
I2C_Type *i2c_bases[4] = {I2C2, I2C3, I2C4, I2C5};
for (int i = 0; i < 4; i++) {
// Initialize the I2C instance (configure I2C peripheral, clock, etc.)
I2C_MasterInit(i2c_bases[i], &i2c_master_config, CLOCK_GetFreq(kCLOCK_Flexcomm2 + i));
// Initialize the DMA for this I2C instance
I2C_MasterCreateHandleDMA(i2c_bases[i], &i2c_dma_handles[i], i2c_master_dma_callback, &user_data[i], &dma_handle);
}
4. Define the Callback Function:
Define a callback function that can handle callbacks for any of the I2C instances.
void i2c_master_dma_callback(I2C_Type *base, i2c_master_dma_handle_t *handle, status_t status, void *userData) {
struct my_user_data *data = (struct my_user_data *)userData;
// Process the callback using the user data
// Example: data->some_field = status;
}
BR
Hang
Hi Hang,
I was hoping for a solution that allows me to continue to use the Peripherals page in MCUXpressoIDE.
I take it that if you want to use an array of user data, you have to initialize everything manually?
Regards,
Glenn
If you want to use Peripherals Page.
You would assign these pointers in the Peripherals page. This allows the tool to generate the correct initialization code while keeping your setup manageable.
A Hybrid Approach: Using Peripherals Page with Manual Adjustments
To maintain the benefits of the Peripherals page while achieving your goal of using an array, you could use a hybrid approach:
1. Configure the I2C Peripherals in the Peripherals Page:
• Use the Peripherals page to set up the basic I2C configurations and DMA handles. Assign the static pointers (p_user_data_0, etc.) as user data.
2. Manually Adjust the User Data Pointers:
• After the code is generated, add a small section in your application to reassign the user data pointers to elements of your array.
Here’s how it might look in practice:
// Define your user data array
struct my_user_data user_data[4];
// Configure I2C in the Peripherals page, assign static pointers p_user_data_0, p_user_data_1, etc.
// After the generated initialization code, reassign pointers
p_user_data_0 = &user_data[0];
p_user_data_1 = &user_data[1];
p_user_data_2 = &user_data[2];
p_user_data_3 = &user_data[3];
BR
Hang
Hi Hang,
This was the solution I provided in my initial post, yes?
So the correct answer is there is no way to directly put an array element in the Peripherals tab, you either
Correct?
Glenn