USB VCP Cli (#237)
* Core: ring buffer. * Api: usb vcp. F3: vcp glue code. * Applications: cli draft version. * Cli: basic working version, includes help and version commands * HAL: vcp on f2 * Makefile: update openocd conf * F3: vcp rx with freertos stream * Cli: help * Cli: standard commands, api-hal-uid * Power: cli poweroff.
This commit is contained in:
10
firmware/targets/Inc/api-hal-uid.h
Normal file
10
firmware/targets/Inc/api-hal-uid.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Get platform UID size in bytes */
|
||||
size_t api_hal_uid_size();
|
||||
|
||||
/* Get const pointer to UID */
|
||||
const uint8_t* api_hal_uid();
|
24
firmware/targets/Inc/api-hal-vcp.h
Normal file
24
firmware/targets/Inc/api-hal-vcp.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Init VCP HAL
|
||||
* Allocates ring buffer and initializes state
|
||||
*/
|
||||
void api_hal_vcp_init();
|
||||
|
||||
/* Recieve data from VCP
|
||||
* Waits till some data arrives, never returns 0
|
||||
* @param buffer - pointer to buffer
|
||||
* @param size - buffer size
|
||||
* @return items copied in buffer, 0 if channel closed
|
||||
*/
|
||||
size_t api_hal_vcp_rx(uint8_t* buffer, size_t size);
|
||||
|
||||
/* Transmit data to VCP
|
||||
* @param buffer - pointer to buffer
|
||||
* @param size - buffer size
|
||||
*/
|
||||
void api_hal_vcp_tx(uint8_t* buffer, size_t size);
|
@@ -5,3 +5,6 @@
|
||||
#include "api-hal-pwm.h"
|
||||
#include "api-hal-task.h"
|
||||
#include "api-hal-tim.h"
|
||||
#include "api-hal-power.h"
|
||||
#include "api-hal-vcp.h"
|
||||
#include "api-hal-uid.h"
|
@@ -51,8 +51,8 @@
|
||||
/* USER CODE BEGIN EXPORTED_DEFINES */
|
||||
/* Define size for the receive and transmit buffer over CDC */
|
||||
/* It's up to user to redefine and/or remove those define */
|
||||
#define APP_RX_DATA_SIZE 2048
|
||||
#define APP_TX_DATA_SIZE 2048
|
||||
#define APP_RX_DATA_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
|
||||
#define APP_TX_DATA_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
|
||||
|
||||
/* USER CODE END EXPORTED_DEFINES */
|
||||
|
||||
|
@@ -104,6 +104,7 @@ int main(void)
|
||||
/* USER CODE BEGIN 2 */
|
||||
MX_FATFS_Init();
|
||||
delay_us_init_DWT();
|
||||
api_hal_vcp_init();
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Init scheduler */
|
||||
|
@@ -51,6 +51,12 @@
|
||||
|
||||
/* USER CODE BEGIN PRIVATE_TYPES */
|
||||
|
||||
extern void _api_hal_vcp_init();
|
||||
extern void _api_hal_vcp_deinit();
|
||||
extern void _api_hal_vcp_control_line(uint8_t state);
|
||||
extern void _api_hal_vcp_rx_callback(char* buffer, size_t size);
|
||||
extern void _api_hal_vcp_tx_complete(size_t size);
|
||||
|
||||
/* USER CODE END PRIVATE_TYPES */
|
||||
|
||||
/**
|
||||
@@ -156,6 +162,7 @@ static int8_t CDC_Init_FS(void)
|
||||
/* Set Application Buffers */
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
|
||||
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
|
||||
_api_hal_vcp_init();
|
||||
return (USBD_OK);
|
||||
/* USER CODE END 3 */
|
||||
}
|
||||
@@ -167,6 +174,7 @@ static int8_t CDC_Init_FS(void)
|
||||
static int8_t CDC_DeInit_FS(void)
|
||||
{
|
||||
/* USER CODE BEGIN 4 */
|
||||
_api_hal_vcp_deinit();
|
||||
return (USBD_OK);
|
||||
/* USER CODE END 4 */
|
||||
}
|
||||
@@ -181,63 +189,34 @@ static int8_t CDC_DeInit_FS(void)
|
||||
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
|
||||
{
|
||||
/* USER CODE BEGIN 5 */
|
||||
switch(cmd)
|
||||
{
|
||||
case CDC_SEND_ENCAPSULATED_COMMAND:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_GET_ENCAPSULATED_RESPONSE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_SET_COMM_FEATURE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_GET_COMM_FEATURE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_CLEAR_COMM_FEATURE:
|
||||
|
||||
break;
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Line Coding Structure */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Offset | Field | Size | Value | Description */
|
||||
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
|
||||
/* 4 | bCharFormat | 1 | Number | Stop bits */
|
||||
/* 0 - 1 Stop bit */
|
||||
/* 1 - 1.5 Stop bits */
|
||||
/* 2 - 2 Stop bits */
|
||||
/* 5 | bParityType | 1 | Number | Parity */
|
||||
/* 0 - None */
|
||||
/* 1 - Odd */
|
||||
/* 2 - Even */
|
||||
/* 3 - Mark */
|
||||
/* 4 - Space */
|
||||
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
|
||||
/*******************************************************************************/
|
||||
case CDC_SET_LINE_CODING:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_GET_LINE_CODING:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_SET_CONTROL_LINE_STATE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_SEND_BREAK:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (cmd == CDC_SEND_ENCAPSULATED_COMMAND) {
|
||||
} else if (cmd == CDC_GET_ENCAPSULATED_RESPONSE) {
|
||||
} else if (cmd == CDC_SET_COMM_FEATURE) {
|
||||
} else if (cmd == CDC_GET_COMM_FEATURE) {
|
||||
} else if (cmd == CDC_CLEAR_COMM_FEATURE) {
|
||||
} else if (cmd == CDC_SET_LINE_CODING) {
|
||||
/*******************************************************************************/
|
||||
/* Line Coding Structure */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Offset | Field | Size | Value | Description */
|
||||
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
|
||||
/* 4 | bCharFormat | 1 | Number | Stop bits */
|
||||
/* 0 - 1 Stop bit */
|
||||
/* 1 - 1.5 Stop bits */
|
||||
/* 2 - 2 Stop bits */
|
||||
/* 5 | bParityType | 1 | Number | Parity */
|
||||
/* 0 - None */
|
||||
/* 1 - Odd */
|
||||
/* 2 - Even */
|
||||
/* 3 - Mark */
|
||||
/* 4 - Space */
|
||||
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
|
||||
/*******************************************************************************/
|
||||
} else if (cmd == CDC_GET_LINE_CODING) {
|
||||
} else if (cmd == CDC_SET_CONTROL_LINE_STATE) {
|
||||
_api_hal_vcp_control_line(((USBD_SetupReqTypedef*)pbuf)->wValue);
|
||||
} else if (cmd == CDC_SEND_BREAK) {
|
||||
} else {
|
||||
}
|
||||
|
||||
return (USBD_OK);
|
||||
@@ -262,7 +241,7 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
|
||||
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
|
||||
_api_hal_vcp_rx_callback((char*)Buf, *Len);
|
||||
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
|
||||
return (USBD_OK);
|
||||
/* USER CODE END 6 */
|
||||
@@ -287,7 +266,8 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
|
||||
if (hcdc->TxState != 0){
|
||||
return USBD_BUSY;
|
||||
}
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
|
||||
memcpy(UserTxBufferFS, Buf, Len);
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, Len);
|
||||
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
|
||||
/* USER CODE END 7 */
|
||||
return result;
|
||||
@@ -310,8 +290,8 @@ static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
|
||||
uint8_t result = USBD_OK;
|
||||
/* USER CODE BEGIN 13 */
|
||||
UNUSED(Buf);
|
||||
UNUSED(Len);
|
||||
UNUSED(epnum);
|
||||
_api_hal_vcp_tx_complete(*Len);
|
||||
/* USER CODE END 13 */
|
||||
return result;
|
||||
}
|
||||
|
10
firmware/targets/f2/api-hal/api-hal-uid.c
Normal file
10
firmware/targets/f2/api-hal/api-hal-uid.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <api-hal-uid.h>
|
||||
#include <stm32l4xx.h>
|
||||
|
||||
size_t api_hal_uid_size() {
|
||||
return 96/8;
|
||||
}
|
||||
|
||||
const uint8_t* api_hal_uid() {
|
||||
return (const uint8_t *)UID_BASE;
|
||||
}
|
92
firmware/targets/f2/api-hal/api-hal-vcp.c
Normal file
92
firmware/targets/f2/api-hal/api-hal-vcp.c
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <api-hal-vcp.h>
|
||||
#include <usbd_cdc_if.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <stream_buffer.h>
|
||||
|
||||
#define API_HAL_VCP_RX_BUFFER_SIZE 600
|
||||
|
||||
typedef struct {
|
||||
StreamBufferHandle_t rx_stream;
|
||||
osSemaphoreId_t tx_semaphore;
|
||||
volatile bool alive;
|
||||
volatile bool underrun;
|
||||
} ApiHalVcp;
|
||||
|
||||
ApiHalVcp api_hal_vcp;
|
||||
|
||||
static const uint8_t ascii_soh = 0x01;
|
||||
static const uint8_t ascii_eot = 0x04;
|
||||
|
||||
void _api_hal_vcp_init();
|
||||
void _api_hal_vcp_deinit();
|
||||
void _api_hal_vcp_control_line(uint8_t state);
|
||||
void _api_hal_vcp_rx_callback(const uint8_t* buffer, size_t size);
|
||||
void _api_hal_vcp_tx_complete(size_t size);
|
||||
|
||||
void api_hal_vcp_init() {
|
||||
api_hal_vcp.rx_stream = xStreamBufferCreate(API_HAL_VCP_RX_BUFFER_SIZE, 1);
|
||||
api_hal_vcp.tx_semaphore = osSemaphoreNew(1, 1, NULL);
|
||||
api_hal_vcp.alive = false;
|
||||
api_hal_vcp.underrun = false;
|
||||
}
|
||||
|
||||
void _api_hal_vcp_init() {
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_deinit() {
|
||||
api_hal_vcp.alive = false;
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_control_line(uint8_t state) {
|
||||
// bit 0: DTR state, bit 1: RTS state
|
||||
// bool dtr = state & 0b01;
|
||||
bool rts = state & 0b10;
|
||||
|
||||
if (rts) {
|
||||
api_hal_vcp.alive = true;
|
||||
_api_hal_vcp_rx_callback(&ascii_soh, 1); // SOH
|
||||
} else {
|
||||
api_hal_vcp.alive = false;
|
||||
_api_hal_vcp_rx_callback(&ascii_eot, 1); // EOT
|
||||
}
|
||||
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_rx_callback(const uint8_t* buffer, size_t size) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
size_t ret = xStreamBufferSendFromISR(api_hal_vcp.rx_stream, buffer, size, &xHigherPriorityTaskWoken);
|
||||
if (ret != size) {
|
||||
api_hal_vcp.underrun = true;
|
||||
}
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_tx_complete(size_t size) {
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
size_t api_hal_vcp_rx(uint8_t* buffer, size_t size) {
|
||||
return xStreamBufferReceive(api_hal_vcp.rx_stream, buffer, size, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void api_hal_vcp_tx(uint8_t* buffer, size_t size) {
|
||||
while (size > 0 && api_hal_vcp.alive) {
|
||||
furi_check(osSemaphoreAcquire(api_hal_vcp.tx_semaphore, osWaitForever) == osOK);
|
||||
|
||||
size_t batch_size = size;
|
||||
if (batch_size > APP_TX_DATA_SIZE) {
|
||||
batch_size = APP_TX_DATA_SIZE;
|
||||
}
|
||||
|
||||
if (CDC_Transmit_FS(buffer, batch_size) == USBD_OK) {
|
||||
size -= batch_size;
|
||||
buffer += batch_size;
|
||||
} else {
|
||||
// Shouldn't be there
|
||||
osDelay(100);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
TOOLCHAIN = arm
|
||||
|
||||
DEBUG_AGENT = set -m; st-util -n --semihosting
|
||||
DEBUG_AGENT = openocd -f interface/stlink-v2.cfg -c "transport select hla_swd" -f target/stm32l4x.cfg -c "init"
|
||||
|
||||
BOOT_ADDRESS = 0x08000000
|
||||
FW_ADDRESS = 0x08008000
|
||||
|
@@ -51,8 +51,8 @@
|
||||
/* USER CODE BEGIN EXPORTED_DEFINES */
|
||||
/* Define size for the receive and transmit buffer over CDC */
|
||||
/* It's up to user to redefine and/or remove those define */
|
||||
#define APP_RX_DATA_SIZE 2048
|
||||
#define APP_TX_DATA_SIZE 2048
|
||||
#define APP_RX_DATA_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
|
||||
#define APP_TX_DATA_SIZE CDC_DATA_HS_MAX_PACKET_SIZE
|
||||
|
||||
/* USER CODE END EXPORTED_DEFINES */
|
||||
|
||||
|
@@ -111,6 +111,7 @@ int main(void)
|
||||
/* USER CODE BEGIN 2 */
|
||||
MX_FATFS_Init();
|
||||
delay_us_init_DWT();
|
||||
api_hal_vcp_init();
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Init scheduler */
|
||||
|
@@ -51,6 +51,12 @@
|
||||
|
||||
/* USER CODE BEGIN PRIVATE_TYPES */
|
||||
|
||||
extern void _api_hal_vcp_init();
|
||||
extern void _api_hal_vcp_deinit();
|
||||
extern void _api_hal_vcp_control_line(uint8_t state);
|
||||
extern void _api_hal_vcp_rx_callback(char* buffer, size_t size);
|
||||
extern void _api_hal_vcp_tx_complete(size_t size);
|
||||
|
||||
/* USER CODE END PRIVATE_TYPES */
|
||||
|
||||
/**
|
||||
@@ -156,6 +162,7 @@ static int8_t CDC_Init_FS(void)
|
||||
/* Set Application Buffers */
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);
|
||||
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);
|
||||
_api_hal_vcp_init();
|
||||
return (USBD_OK);
|
||||
/* USER CODE END 3 */
|
||||
}
|
||||
@@ -167,6 +174,7 @@ static int8_t CDC_Init_FS(void)
|
||||
static int8_t CDC_DeInit_FS(void)
|
||||
{
|
||||
/* USER CODE BEGIN 4 */
|
||||
_api_hal_vcp_deinit();
|
||||
return (USBD_OK);
|
||||
/* USER CODE END 4 */
|
||||
}
|
||||
@@ -181,63 +189,34 @@ static int8_t CDC_DeInit_FS(void)
|
||||
static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
|
||||
{
|
||||
/* USER CODE BEGIN 5 */
|
||||
switch(cmd)
|
||||
{
|
||||
case CDC_SEND_ENCAPSULATED_COMMAND:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_GET_ENCAPSULATED_RESPONSE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_SET_COMM_FEATURE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_GET_COMM_FEATURE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_CLEAR_COMM_FEATURE:
|
||||
|
||||
break;
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Line Coding Structure */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Offset | Field | Size | Value | Description */
|
||||
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
|
||||
/* 4 | bCharFormat | 1 | Number | Stop bits */
|
||||
/* 0 - 1 Stop bit */
|
||||
/* 1 - 1.5 Stop bits */
|
||||
/* 2 - 2 Stop bits */
|
||||
/* 5 | bParityType | 1 | Number | Parity */
|
||||
/* 0 - None */
|
||||
/* 1 - Odd */
|
||||
/* 2 - Even */
|
||||
/* 3 - Mark */
|
||||
/* 4 - Space */
|
||||
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
|
||||
/*******************************************************************************/
|
||||
case CDC_SET_LINE_CODING:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_GET_LINE_CODING:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_SET_CONTROL_LINE_STATE:
|
||||
|
||||
break;
|
||||
|
||||
case CDC_SEND_BREAK:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (cmd == CDC_SEND_ENCAPSULATED_COMMAND) {
|
||||
} else if (cmd == CDC_GET_ENCAPSULATED_RESPONSE) {
|
||||
} else if (cmd == CDC_SET_COMM_FEATURE) {
|
||||
} else if (cmd == CDC_GET_COMM_FEATURE) {
|
||||
} else if (cmd == CDC_CLEAR_COMM_FEATURE) {
|
||||
} else if (cmd == CDC_SET_LINE_CODING) {
|
||||
/*******************************************************************************/
|
||||
/* Line Coding Structure */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Offset | Field | Size | Value | Description */
|
||||
/* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
|
||||
/* 4 | bCharFormat | 1 | Number | Stop bits */
|
||||
/* 0 - 1 Stop bit */
|
||||
/* 1 - 1.5 Stop bits */
|
||||
/* 2 - 2 Stop bits */
|
||||
/* 5 | bParityType | 1 | Number | Parity */
|
||||
/* 0 - None */
|
||||
/* 1 - Odd */
|
||||
/* 2 - Even */
|
||||
/* 3 - Mark */
|
||||
/* 4 - Space */
|
||||
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
|
||||
/*******************************************************************************/
|
||||
} else if (cmd == CDC_GET_LINE_CODING) {
|
||||
} else if (cmd == CDC_SET_CONTROL_LINE_STATE) {
|
||||
_api_hal_vcp_control_line(((USBD_SetupReqTypedef*)pbuf)->wValue);
|
||||
} else if (cmd == CDC_SEND_BREAK) {
|
||||
} else {
|
||||
}
|
||||
|
||||
return (USBD_OK);
|
||||
@@ -262,7 +241,7 @@ static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)
|
||||
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
|
||||
_api_hal_vcp_rx_callback((char*)Buf, *Len);
|
||||
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
|
||||
return (USBD_OK);
|
||||
/* USER CODE END 6 */
|
||||
@@ -287,7 +266,8 @@ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
|
||||
if (hcdc->TxState != 0){
|
||||
return USBD_BUSY;
|
||||
}
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
|
||||
memcpy(UserTxBufferFS, Buf, Len);
|
||||
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, Len);
|
||||
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
|
||||
/* USER CODE END 7 */
|
||||
return result;
|
||||
@@ -310,8 +290,8 @@ static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum)
|
||||
uint8_t result = USBD_OK;
|
||||
/* USER CODE BEGIN 13 */
|
||||
UNUSED(Buf);
|
||||
UNUSED(Len);
|
||||
UNUSED(epnum);
|
||||
_api_hal_vcp_tx_complete(*Len);
|
||||
/* USER CODE END 13 */
|
||||
return result;
|
||||
}
|
||||
|
10
firmware/targets/f3/api-hal/api-hal-uuid.c
Normal file
10
firmware/targets/f3/api-hal/api-hal-uuid.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <api-hal-uid.h>
|
||||
#include <stm32wbxx.h>
|
||||
|
||||
size_t api_hal_uid_size() {
|
||||
return 64/8;
|
||||
}
|
||||
|
||||
const uint8_t* api_hal_uid() {
|
||||
return (const uint8_t *)UID64_BASE;
|
||||
}
|
92
firmware/targets/f3/api-hal/api-hal-vcp.c
Normal file
92
firmware/targets/f3/api-hal/api-hal-vcp.c
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <api-hal-vcp.h>
|
||||
#include <usbd_cdc_if.h>
|
||||
#include <flipper_v2.h>
|
||||
#include <stream_buffer.h>
|
||||
|
||||
#define API_HAL_VCP_RX_BUFFER_SIZE 600
|
||||
|
||||
typedef struct {
|
||||
StreamBufferHandle_t rx_stream;
|
||||
osSemaphoreId_t tx_semaphore;
|
||||
volatile bool alive;
|
||||
volatile bool underrun;
|
||||
} ApiHalVcp;
|
||||
|
||||
ApiHalVcp api_hal_vcp;
|
||||
|
||||
static const uint8_t ascii_soh = 0x01;
|
||||
static const uint8_t ascii_eot = 0x04;
|
||||
|
||||
void _api_hal_vcp_init();
|
||||
void _api_hal_vcp_deinit();
|
||||
void _api_hal_vcp_control_line(uint8_t state);
|
||||
void _api_hal_vcp_rx_callback(const uint8_t* buffer, size_t size);
|
||||
void _api_hal_vcp_tx_complete(size_t size);
|
||||
|
||||
void api_hal_vcp_init() {
|
||||
api_hal_vcp.rx_stream = xStreamBufferCreate(API_HAL_VCP_RX_BUFFER_SIZE, 1);
|
||||
api_hal_vcp.tx_semaphore = osSemaphoreNew(1, 1, NULL);
|
||||
api_hal_vcp.alive = false;
|
||||
api_hal_vcp.underrun = false;
|
||||
}
|
||||
|
||||
void _api_hal_vcp_init() {
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_deinit() {
|
||||
api_hal_vcp.alive = false;
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_control_line(uint8_t state) {
|
||||
// bit 0: DTR state, bit 1: RTS state
|
||||
// bool dtr = state & 0b01;
|
||||
bool rts = state & 0b10;
|
||||
|
||||
if (rts) {
|
||||
api_hal_vcp.alive = true;
|
||||
_api_hal_vcp_rx_callback(&ascii_soh, 1); // SOH
|
||||
} else {
|
||||
api_hal_vcp.alive = false;
|
||||
_api_hal_vcp_rx_callback(&ascii_eot, 1); // EOT
|
||||
}
|
||||
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_rx_callback(const uint8_t* buffer, size_t size) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
size_t ret = xStreamBufferSendFromISR(api_hal_vcp.rx_stream, buffer, size, &xHigherPriorityTaskWoken);
|
||||
if (ret != size) {
|
||||
api_hal_vcp.underrun = true;
|
||||
}
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
void _api_hal_vcp_tx_complete(size_t size) {
|
||||
osSemaphoreRelease(api_hal_vcp.tx_semaphore);
|
||||
}
|
||||
|
||||
size_t api_hal_vcp_rx(uint8_t* buffer, size_t size) {
|
||||
return xStreamBufferReceive(api_hal_vcp.rx_stream, buffer, size, portMAX_DELAY);
|
||||
}
|
||||
|
||||
void api_hal_vcp_tx(uint8_t* buffer, size_t size) {
|
||||
while (size > 0 && api_hal_vcp.alive) {
|
||||
furi_check(osSemaphoreAcquire(api_hal_vcp.tx_semaphore, osWaitForever) == osOK);
|
||||
|
||||
size_t batch_size = size;
|
||||
if (batch_size > APP_TX_DATA_SIZE) {
|
||||
batch_size = APP_TX_DATA_SIZE;
|
||||
}
|
||||
|
||||
if (CDC_Transmit_FS(buffer, batch_size) == USBD_OK) {
|
||||
size -= batch_size;
|
||||
buffer += batch_size;
|
||||
} else {
|
||||
// Shouldn't be there
|
||||
osDelay(100);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "api-hal-gpio.h"
|
||||
#include "api-hal-delay.h"
|
||||
#include "api-hal-pwm.h"
|
||||
#include "api-hal-task.h"
|
||||
#include "api-hal-tim.h"
|
@@ -270,6 +270,7 @@ Mcu.Pin12=PA2
|
||||
PD0.GPIOParameters=GPIO_Speed,PinState,GPIO_Label
|
||||
Mcu.Pin10=PA0
|
||||
SH.GPXTI10.ConfNb=1
|
||||
USB_DEVICE.APP_RX_DATA_SIZE=512
|
||||
TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
|
||||
PC3.GPIO_Label=PC3
|
||||
PA3.PinState=GPIO_PIN_SET
|
||||
@@ -453,7 +454,7 @@ OSC_IN.GPIOParameters=GPIO_Label
|
||||
PB12.Locked=true
|
||||
ProjectManager.DeletePrevious=true
|
||||
PB10.Locked=true
|
||||
USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS,MANUFACTURER_STRING,PRODUCT_STRING_CDC_FS
|
||||
USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS,MANUFACTURER_STRING,PRODUCT_STRING_CDC_FS,APP_RX_DATA_SIZE,APP_TX_DATA_SIZE
|
||||
TIM16.Channel=TIM_CHANNEL_1
|
||||
RCC.AHB2CLKDivider=RCC_SYSCLK_DIV2
|
||||
RCC.FamilyName=M
|
||||
@@ -528,6 +529,7 @@ PA13.Locked=true
|
||||
RF1.Mode=RF1_Activate
|
||||
PB7.Mode=Asynchronous
|
||||
NVIC.EXTI9_5_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
|
||||
USB_DEVICE.APP_TX_DATA_SIZE=512
|
||||
PA14.Signal=SYS_JTCK-SWCLK
|
||||
PB2.GPIO_Label=PB2
|
||||
PC6.GPIOParameters=GPIO_Label
|
||||
|
@@ -1,6 +1,6 @@
|
||||
TOOLCHAIN = arm
|
||||
|
||||
DEBUG_AGENT = openocd -f interface/stlink-v2.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "init" -c "reset halt"
|
||||
DEBUG_AGENT = openocd -f interface/stlink.cfg -c "transport select hla_swd" -f target/stm32wbx.cfg -c "init"
|
||||
|
||||
BOOT_ADDRESS = 0x08000000
|
||||
FW_ADDRESS = 0x08008000
|
||||
|
Reference in New Issue
Block a user