0
mirror of https://gitlab.com/hyperglitch/jellyfish.git synced 2025-12-26 15:16:30 +00:00
2025-06-12 10:31:43 +02:00

123 lines
3.4 KiB
C

/*
* SPDX-FileCopyrightText: 2025 Igor Brkic <igor@hyperglitch.com>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "jf_i2c.h"
#include <stdio.h>
#include "queue.h"
I2C_HandleTypeDef *hi2c_ptr = NULL;
static jf_i2c_request_t current_request = {0};
static uint8_t task_queue_buffer[sizeof(jf_i2c_request_t) * 10];
static StaticQueue_t task_queue_structure;
static QueueHandle_t task_queue;
static osThreadId_t task_handle;
static const osThreadAttr_t task_attributes = {
.name = "I2CTask",
.stack_size = 1024,
};
static void task_func(void *argument) {
(void) argument;
jf_i2c_request_t req;
while (true) {
// wait for a request
if (xQueueReceive(task_queue, &req, portMAX_DELAY) == pdTRUE) {
current_request = req; // save to global var so callbacks can notify the sender
// do the thing
if (req.cmd==JF_I2C_CMD_WRITE) {
HAL_I2C_Master_Transmit_IT(
hi2c_ptr,
req.addr<<1,
req.write_buffer,
req.size
);
}
else if (req.cmd==JF_I2C_CMD_READ) {
HAL_I2C_Master_Receive_IT(
hi2c_ptr,
req.addr<<1,
req.read_buffer,
req.size
);
}
}
}
}
void jf_i2c_handle_callback(I2C_HandleTypeDef *hi2c) {
if (current_request.notify_task==NULL) {
return;
}
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
vTaskNotifyGiveFromISR(current_request.notify_task, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void jf_i2c_handle_error_callback(I2C_HandleTypeDef *hi2c) {
}
uint8_t i2c_write_buffer[128];
uint8_t i2c_read_buffer[128];
bool jf_i2c_add_to_queue(const jf_i2c_addr_t addr, const jf_i2c_cmd_t cmd, uint8_t *write_buffer, uint8_t *read_buffer, const uint16_t size, const bool blocking) {
jf_i2c_request_t req = {
.addr = addr,
.cmd = cmd,
.write_buffer = write_buffer,
.read_buffer = read_buffer,
.size = size,
.notify_task = NULL
};
if (blocking) {
req.notify_task = xTaskGetCurrentTaskHandle();
}
const BaseType_t ret = xQueueGenericSend(task_queue, &req, portMAX_DELAY, queueSEND_TO_BACK);
if (req.notify_task!=NULL) {
// wait for the request to complete
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
}
return ret==pdPASS;
}
bool jf_i2c_add_to_queue_from_isr(const jf_i2c_addr_t addr, const jf_i2c_cmd_t cmd, uint8_t *write_buffer, uint8_t *read_buffer, const uint16_t size) {
const jf_i2c_request_t req = {
.addr = addr,
.cmd = cmd,
.write_buffer = write_buffer,
.read_buffer = read_buffer,
.size = size,
.notify_task = NULL
};
const BaseType_t ret = xQueueGenericSendFromISR(task_queue, &req, pdFALSE, queueSEND_TO_BACK);
return ret==pdPASS;
}
void jf_i2c_init(I2C_HandleTypeDef *hi2c) {
hi2c_ptr = hi2c;
task_queue = xQueueCreateStatic(
10,
sizeof(jf_i2c_request_t),
task_queue_buffer,
&task_queue_structure
);
if(task_queue == NULL) {
printf("failed to create qspi queue\r\n");
Error_Handler();
}
task_handle = osThreadNew(task_func, NULL, &task_attributes);
printf("I2C task initialized\r\n");
}