Загрузка данных
#define SRTM_I2C_CATEGORY (0x9U)
#define SRTM_I2C_VERSION (0x0100U)
#define SRTM_I2C_RETURN_CODE_SUCEESS (0x0U)
#define SRTM_I2C_RETURN_CODE_FAIL (0x1U)
#define SRTM_I2C_RETURN_CODE_UNSUPPORTED (0x2U)
typedef struct _srtm_i2c_service
{
struct _srtm_service service;
srtm_i2c_adapter_t adapter;
} *srtm_i2c_service_t;
static srtm_status_t SRTM_I2CService_Request(srtm_service_t service, srtm_request_t request);
static srtm_status_t SRTM_I2CService_Notify(srtm_service_t service, srtm_notification_t notif);
static i2c_bus_t SRTM_I2C_SearchBus(srtm_i2c_adapter_t adapter, uint8_t busID)
{
uint8_t bus_num = adapter->bus_structure.bus_num;
i2c_bus_t busArray = adapter->bus_structure.buses;
uint8_t i;
for (i = 0U; i != bus_num; i++)
{
if (busArray[i].bus_id == busID)
{
break;
}
}
return (i == bus_num) ? NULL : (busArray + i);
}
static srtm_status_t SRTM_I2CService_ReadBus(
srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len, uint16_t flags)
{
srtm_i2c_service_t handle = (srtm_i2c_service_t)(void *)service;
srtm_i2c_adapter_t adapter = handle->adapter;
i2c_bus_t targetBus;
uint32_t base_addr;
uint8_t switch_index;
uint16_t switch_addr;
srtm_i2c_switch_channel switch_channel;
srtm_status_t status;
srtm_i2c_type_t type;
i2c_switch_t switch_inst;
targetBus = SRTM_I2C_SearchBus(adapter, busID);
base_addr = targetBus->base_addr;
switch_index = targetBus->switch_idx;
type = targetBus->type;
/*
* Switch Channel
*/
if (switch_index < adapter->bus_structure.switch_num)
{
switch_inst = &adapter->bus_structure.switches[switch_index];
switch_addr = switch_inst->slaveAddr;
switch_channel = targetBus->switch_channel;
if (switch_inst->cur_channel != switch_channel)
{
(void)adapter->switchchannel(adapter, base_addr, type, switch_addr, switch_channel);
switch_inst->cur_channel = switch_channel;
}
}
/*
* Read
*/
status = adapter->read(adapter, base_addr, type, slaveAddr, buf, len, flags); // APP_SRTM_I2C_Read
return status;
}
static srtm_status_t SRTM_I2CService_WriteBus(
srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len, uint16_t flags)
{
srtm_i2c_service_t handle = (srtm_i2c_service_t)(void *)service;
srtm_i2c_adapter_t adapter = handle->adapter;
i2c_bus_t targetBus;
uint32_t base_addr;
uint8_t switch_index;
uint16_t switch_addr;
srtm_i2c_switch_channel switch_channel;
srtm_status_t status;
srtm_i2c_type_t type;
i2c_switch_t switch_inst;
targetBus = SRTM_I2C_SearchBus(adapter, busID);
base_addr = targetBus->base_addr;
switch_index = targetBus->switch_idx;
type = targetBus->type;
/*
* Switch Channel
*/
if (switch_index < adapter->bus_structure.switch_num)
{
switch_inst = &adapter->bus_structure.switches[switch_index];
switch_addr = switch_inst->slaveAddr;
switch_channel = targetBus->switch_channel;
if (switch_inst->cur_channel != switch_channel)
{
(void)adapter->switchchannel(adapter, base_addr, type, switch_addr, switch_channel);
switch_inst->cur_channel = switch_channel;
}
}
/*
* Write
*/
status = adapter->write(adapter, base_addr, type, slaveAddr, buf, len, flags); // APP_SRTM_I2C_Write
return status;
}
srtm_service_t SRTM_I2CService_Create(srtm_i2c_adapter_t adapter)
{
srtm_i2c_service_t handle;
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
handle = (srtm_i2c_service_t)SRTM_Heap_Malloc(sizeof(struct _srtm_i2c_service));
assert(handle);
adapter->service = &handle->service;
handle->adapter = adapter;
SRTM_List_Init(&handle->service.node);
handle->service.dispatcher = NULL;
handle->service.category = SRTM_I2C_CATEGORY;
handle->service.destroy = SRTM_I2CService_Destroy;
handle->service.request = SRTM_I2CService_Request;
handle->service.notify = SRTM_I2CService_Notify;
return &handle->service;
}
void SRTM_I2CService_Destroy(srtm_service_t service)
{
srtm_i2c_service_t handle = (srtm_i2c_service_t)(void *)service;
assert(service);
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
/* Service must be unregistered from dispatcher before destroy */
assert(SRTM_List_IsEmpty(&service->node));
SRTM_Heap_Free(handle);
}
void SRTM_I2CService_Reset(srtm_service_t service, srtm_peercore_t core)
{
assert(service);
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
}
static srtm_status_t SRTM_I2CService_Request(srtm_service_t service, srtm_request_t request)
{
srtm_status_t status;
srtm_channel_t channel;
uint8_t command;
uint32_t payloadLen;
srtm_response_t response;
struct _srtm_i2c_payload *i2cReq;
struct _srtm_i2c_payload *i2cResp;
assert(service->dispatcher);
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO, "%s\r\n", __func__);
channel = SRTM_CommMessage_GetChannel(request);
command = SRTM_CommMessage_GetCommand(request);
i2cReq = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(request);
payloadLen = SRTM_CommMessage_GetPayloadLen(request);
(void)payloadLen; /* try to fix warning: variable 'payloadLen' set but not used */
assert(i2cReq);
assert((uint32_t)(i2cReq->len + sizeof(struct _srtm_i2c_payload) - sizeof(i2cReq->data[0])) <= payloadLen);
response =
SRTM_Response_Create(channel, SRTM_I2C_CATEGORY, SRTM_I2C_VERSION, command,
(uint16_t)((sizeof(struct _srtm_i2c_payload) - sizeof(i2cReq->data[0])) + i2cReq->len));
if (response == NULL)
{
return SRTM_Status_OutOfMemory;
}
i2cResp = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(response);
status = SRTM_Service_CheckVersion(service, request, SRTM_I2C_VERSION);
if (status != SRTM_Status_Success)
{
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: format error!\r\n", __func__);
i2cResp->retCode = SRTM_I2C_RETURN_CODE_UNSUPPORTED;
}
else
{
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_INFO,
"SRTM receive I2C request:cmd=%x, busID %d, slaveAddr 0x%x!, data %d bytes\r\n", command,
i2cReq->busID, i2cReq->slaveAddr, i2cReq->len);
(void)memcpy(i2cResp, i2cReq,
(sizeof(struct _srtm_i2c_payload) - sizeof(i2cReq->data[0]) + (size_t)i2cReq->len));
switch (command)
{
case (uint8_t)SRTM_I2C_CMD_READ:
status = SRTM_I2CService_ReadBus(service, i2cResp->busID, i2cResp->slaveAddr, i2cResp->data,
i2cReq->len, i2cReq->flags);
i2cResp->retCode =
status == SRTM_Status_Success ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
break;
case (uint8_t)SRTM_I2C_CMD_WRITE:
status = SRTM_I2CService_WriteBus(service, i2cResp->busID, i2cResp->slaveAddr, i2cResp->data,
i2cReq->len, i2cReq->flags);
i2cResp->retCode =
status == SRTM_Status_Success ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
break;
default:
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: command %d unsupported!\r\n", __func__, command);
assert(false);
break;
}
}
return SRTM_Dispatcher_DeliverResponse(service->dispatcher, response);
}
static srtm_status_t SRTM_I2CService_Notify(srtm_service_t service, srtm_notification_t notif)
{
SRTM_DEBUG_MESSAGE(SRTM_DEBUG_VERBOSE_WARN, "%s: command %d unsupported!\r\n", __func__,
SRTM_CommMessage_GetCommand(notif));
return SRTM_Status_ServiceNotFound;
}
static void SRTM_I2C_HandleBusRead(srtm_dispatcher_t dispatcher, void *param1, void *param2)
{
srtm_status_t status;
srtm_i2c_payload_t i2c_payload = (srtm_i2c_payload_t)param1;
srtm_service_t service = (srtm_service_t)param2;
status = SRTM_I2CService_ReadBus(service, i2c_payload->busID, i2c_payload->slaveAddr, i2c_payload->data,
(uint8_t)i2c_payload->len, i2c_payload->flags);
i2c_payload->retCode = (status == SRTM_Status_Success) ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
}
static void SRTM_I2C_HandleBusWrite(srtm_dispatcher_t dispatcher, void *param1, void *param2)
{
srtm_status_t status;
srtm_i2c_payload_t i2c_payload = (srtm_i2c_payload_t)param1;
srtm_service_t service = (srtm_service_t)param2;
status = SRTM_I2CService_WriteBus(service, i2c_payload->busID, i2c_payload->slaveAddr, i2c_payload->data,
(uint8_t)i2c_payload->len, i2c_payload->flags);
i2c_payload->retCode = (status == SRTM_Status_Success) ? SRTM_I2C_RETURN_CODE_SUCEESS : SRTM_I2C_RETURN_CODE_FAIL;
}
srtm_status_t SRTM_I2C_RequestBusRead(
srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len)
{
srtm_request_t request;
srtm_status_t status;
srtm_i2c_payload_t i2cReq;
srtm_procedure_t proc;
/*
* Allocate an SRTM message and copy necessary information
*/
request = SRTM_Request_Create(NULL, SRTM_I2C_CATEGORY, SRTM_I2C_VERSION, (uint8_t)SRTM_I2C_CMD_READ,
(uint16_t)((sizeof(struct _srtm_i2c_payload) - sizeof(uint8_t)) + len));
i2cReq = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(request);
i2cReq->busID = busID;
i2cReq->slaveAddr = slaveAddr;
i2cReq->len = len;
(void)memset(i2cReq->data, 0, len);
/*
* Call proc in sync manner
*/
proc = SRTM_Procedure_Create(SRTM_I2C_HandleBusRead, i2cReq, service);
(void)SRTM_Dispatcher_CallProc(service->dispatcher, proc, SRTM_WAIT_FOR_EVER); /*synchronized call*/
/*
* Save proc exec result
*/
(void)memcpy(buf, i2cReq->data, len);
status = (srtm_status_t)i2cReq->retCode;
/*
* Clean the allocated SRTM object
*/
SRTM_Procedure_Destroy(proc);
SRTM_Response_Destroy(request);
return status;
}
srtm_status_t SRTM_I2C_RequestBusWrite(
srtm_service_t service, uint8_t busID, uint16_t slaveAddr, uint8_t *buf, uint16_t len, uint8_t needStop)
{
srtm_request_t request;
srtm_status_t status;
srtm_i2c_payload_t i2cReq;
srtm_procedure_t proc;
/*
* Allocate an SRTM message and copy necessary information
*/
request = SRTM_Request_Create(NULL, SRTM_I2C_CATEGORY, SRTM_I2C_VERSION, (uint8_t)SRTM_I2C_CMD_WRITE,
(uint16_t)((sizeof(struct _srtm_i2c_payload) - sizeof(uint8_t)) + len));
i2cReq = (struct _srtm_i2c_payload *)(void *)SRTM_CommMessage_GetPayload(request);
i2cReq->busID = busID;
i2cReq->slaveAddr = slaveAddr;
i2cReq->len = len;
i2cReq->flags = needStop > 0U ? (SRTM_I2C_FLAG_NEED_STOP) : 0U;
(void)memcpy(i2cReq->data, buf, len);
/*
* Call proc in sync manner
*/
proc = SRTM_Procedure_Create(SRTM_I2C_HandleBusWrite, i2cReq, service);
(void)SRTM_Dispatcher_CallProc(service->dispatcher, proc, SRTM_WAIT_FOR_EVER); /*synchronized call*/
/*
* Save proc exec result
*/
status = (srtm_status_t)i2cReq->retCode;
/*
* Clean the allocated SRTM object
*/
SRTM_Procedure_Destroy(proc);
SRTM_Response_Destroy(request);
return status;
}