MotorControlModuleSDFM_TMS3.../Projects/EFC_UsbDriver/src/loader/ld_device.c
2024-06-07 11:04:32 +03:00

163 lines
5.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* ld_device.c
*
* Created on: 22 авг. 2023 г.
* Author: malyarenko
*/
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <sysctl.h>
#include <usb.h>
#include <usblib.h>
#include <usbdevice.h>
#include "../device_desc.h"
#include "ld_device_desc.h"
#include "ld_device.h"
static struct ld_device* ld_device_handler = NULL;
static const size_t MAX_PACKAGE_SIZE = 64;
static inline bool ld_device_cmd_init(struct ld_device* handler, const struct efc_usb_ld_config* config) {
if ((handler == NULL) || (config == NULL)) return false;
handler->cmd.rx_handle = config->cmd.rx_handle;
handler->cmd.rx_handle_param = config->cmd.rx_handle_param;
atomic_flag_test_and_set(&handler->cmd.rx_lock);
handler->cmd.tx_handle = config->cmd.tx_handle;
handler->cmd.tx_handle_param = config->cmd.tx_handle_param;
atomic_flag_clear(&handler->cmd.tx_lock);
// if (!ld_cmd_dma_init(handler)) return false;
return true;
}
bool ld_device_init(struct ld_device* device_handler, const struct efc_usb_ld_config* config) {
if ((device_handler == NULL) || (config == NULL)) return false;
// TODO: валидация
//if (!ld_device_validate_config(config)) return false;
device_handler->usb_base = USB_BASE;
device_handler->flags.connected = false;
device_handler->flags.cmd_active = true;
device_handler->reset_handle = config->reset_handle;
device_handler->reset_handle_param = config->reset_handle_param;
/* Командный интерфейс */
if (!ld_device_cmd_init(device_handler, config)) return false;
ld_device_handler = device_handler;
return true;
}
void ld_device_fini(struct ld_device* device_handler) {
if (device_handler == NULL) return;
USBDCDTerm(0);
device_handler->usb_base = 0;
ld_device_handler = NULL;
}
efc_usb_status_t efc_usb_ld_data_recv(uint8_t* buffer, size_t buffer_max_size, size_t* received_data_size, size_t* data_size_avail){
const uint32_t ep_id = IndexToUSBEP(EFC_USB_LD_EP1_O_ADDR);
/* Проверка параметров вызова */
if (NULL == buffer){
return EFC_USB_EARG;
}
/* Проверка состояния драйвера */
struct ld_device* const handler = ld_device_handler;
if ((handler == NULL) || !handler->flags.connected || !handler->flags.cmd_active){
return EFC_USB_ENOOP;
}
/* Проверка статуса EP */
const uint32_t ep_status = USBEndpointStatus(handler->usb_base, ep_id);
if ((ep_status & USB_DEV_RX_PKT_RDY) == 0){
return EFC_USB_EBUSY;
}
/* Защита от повторного чтения
const bool is_locked = atomic_flag_test_and_set(&handler->cmd.rx_lock);
if (is_locked){
return EFC_USB_EBUSY;
}
*/
USBEndpointDataGet(handler->usb_base, ep_id, buffer, &buffer_max_size);
*received_data_size = buffer_max_size;
*data_size_avail = USBEndpointDataAvail(handler->usb_base, ep_id);
if(0 == *data_size_avail){
USBDevEndpointDataAck(handler->usb_base, ep_id, true);
}
return EFC_USB_OK;
}
efc_usb_status_t efc_usb_ld_data_send(const uint8_t* header, size_t header_size, const uint8_t* data, size_t data_size){
const uint32_t ep_id = IndexToUSBEP(EFC_USB_LD_EP1_I_ADDR);
// Проверка параметров вызова
if (NULL == data && 0 < data_size){
return EFC_USB_EARG;
}
// Проверка состояния драйвера
struct ld_device* const handler = ld_device_handler;
if ((handler == NULL) || !handler->flags.connected || !handler->flags.cmd_active){
return EFC_USB_ENOOP;
}
// Проверка статуса EP
const uint32_t ep_status = USBEndpointStatus(handler->usb_base, ep_id);
if ((ep_status & USB_DEV_TX_TXPKTRDY) != 0){
return EFC_USB_EBUSY;
}
uint32_t status = USBEndpointDataPut(handler->usb_base, ep_id, header, header_size);
const uint16_t DATA_MAX_SIZE = MAX_PACKAGE_SIZE;
uint16_t sending_data_bytes = 0;
do{
// Если размер данных больше максимального размера USB буфера, то в конце нам нужно записать меньшее количество байт.
uint16_t send_bytes_count = data_size + header_size - sending_data_bytes < DATA_MAX_SIZE
? data_size + header_size - sending_data_bytes
: DATA_MAX_SIZE;
if(0 < send_bytes_count){
// Добавляем данные
const uint8_t* data_sent = data + sending_data_bytes;
status = USBEndpointDataPut(handler->usb_base, ep_id, data_sent, send_bytes_count - header_size);
}
status = USBEndpointDataSend(handler->usb_base, ep_id, USB_TRANS_IN);
uint32_t send_status = USBEndpointStatus(handler->usb_base, ep_id);
while((send_status & USB_DEV_TX_FIFO_NE) != 0){
send_status = USBEndpointStatus(handler->usb_base, ep_id);
}
if(0 != status){
return EFC_USB_ERR;
}
// Заголовок отправляется только один раз.
sending_data_bytes += send_bytes_count - header_size;
header_size = 0;
} while(sending_data_bytes < data_size);
return EFC_USB_OK;
}