wip rx handler

This commit is contained in:
2018-04-01 00:45:47 +02:00
parent 6338d3d1b4
commit 896df82e27
23 changed files with 937 additions and 36 deletions
+35
View File
@@ -0,0 +1,35 @@
//
// Created by MightyPork on 2018/03/31.
//
#include "debug.h"
#include "main.h"
#include <stdarg.h>
#include "usart.h"
#define BUFLEN 128
static char buff[BUFLEN];
void dbg(const char *format, ...)
{
MX_USART_DmaWaitReady();
va_list args;
va_start (args, format);
uint32_t count = (uint32_t) vsprintf (buff, format, args);
if (count < BUFLEN - 2) {
buff[count++] = '\r';
buff[count++] = '\n';
buff[count] = 0;
}
va_end (args);
MX_USART_DmaSend((uint8_t *) buff, count);
// char c;
// char* ptr = buff;
// while ((c = *ptr++) != 0) {
// txchar(c);
// }
// txchar('\r');
// txchar('\n');
}
View File
+111
View File
@@ -0,0 +1,111 @@
//
// Created by MightyPork on 2018/03/31.
//
#include <string.h>
#include "debug.h"
#include "msg_queue.h"
#include "gex_gateway.h"
#include "main.h"
#include "minmax.h"
#include "payload_parser.h"
// USB RX
enum URX_STATE {
URXS_IDLE = 0,
URXS_MSG4SLAVE = 1,
};
#define MAX_FRAME_LEN 512
static enum URX_STATE urx_state = URXS_IDLE;
static uint32_t msg4slave_len = 0; // total len to be collected
static uint32_t msg4slave_already = 0; // already collected len
static uint8_t msg4slave[MAX_FRAME_LEN]; // equal buffer size in GEX
static uint8_t msg4slave_addr = 0;
static uint8_t msg4slave_cksum = 0;
#define MAGIC_GW_COMMAND 0x47U // 'G'
enum GW_CMD {
CMD_GET_ID = 'i', // 105
CMD_MSG4SLAVE = 'm', // 109
};
void respond_gw_id(); // TODO impl
void start_slave_cmd(uint8_t slave_addr, uint16_t frame_len, uint8_t cksum)
{
msg4slave_len = frame_len;
msg4slave_already = 0;
msg4slave_addr = slave_addr;
msg4slave_cksum = cksum;
}
/** called from the main loop, periodically */
void gw_process(void)
{
static uint8_t buffer[MQ_SLOT_LEN];
while (mq_read(&usb_rxq, buffer)) { // greedy - handle as many as possible
if (urx_state == URXS_IDLE) {
PayloadParser pp = pp_start(buffer, MQ_SLOT_LEN, NULL);
// handle binary commands for the gateway
// magic twice, one inverted - denotes a gateway command
uint16_t magic1 = pp_u8(&pp);
uint16_t magic2 = pp_u8(&pp);
if (magic1 == MAGIC_GW_COMMAND && magic2 == ~MAGIC_GW_COMMAND) {
// third byte is the command code
switch (pp_u8(&pp)) {
case CMD_GET_ID:
respond_gw_id();
break;
case CMD_MSG4SLAVE:;
uint8_t slave_addr = pp_u8(&pp);
uint16_t frame_len = pp_u16(&pp);
uint8_t cksum = pp_u8(&pp);
if (frame_len > MAX_FRAME_LEN) {
dbg("Frame too big!");
break;
}
start_slave_cmd(slave_addr, frame_len, cksum);
dbg("Collecting frame for slave %02x: %d bytes", (int)slave_addr, (int)frame_len);
urx_state = URXS_MSG4SLAVE;
break;
}
} else {
// Bad frame??
dbg("Bad USB frame, starts %x", buffer[0]);
}
}
else if (urx_state == URXS_MSG4SLAVE) {
uint32_t wanted = MIN(msg4slave_len-msg4slave_already, MQ_SLOT_LEN);
memcpy(&msg4slave[msg4slave_already], buffer, wanted);
msg4slave_already += wanted;
if (wanted < MQ_SLOT_LEN) {
// this was the end
uint8_t ck = 0;
for (int i = 0; i < msg4slave_len; i++) {
ck ^= msg4slave[i];
}
ck = ~ck;
if (ck != msg4slave_cksum) {
dbg("Checksum mismatch!");
}
else {
dbg("Verified, sending a %d B frame to slave.", (int) msg4slave_len);
// TODO send to slave
}
urx_state = URXS_IDLE;
}
}
}
}
+18 -9
View File
@@ -47,6 +47,7 @@
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <gex_gateway.h>
#include "main.h"
#include "stm32f1xx_hal.h"
#include "dma.h"
@@ -54,6 +55,7 @@
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
#include "debug.h"
/* USER CODE BEGIN Includes */
@@ -105,25 +107,32 @@ int main(void)
/* USER CODE END SysInit */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOD);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USB_DEVICE_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
MX_GPIO_Init();
MX_DMA_Init();
MX_USB_DEVICE_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
dbg("Main loop starts.");
/* Infinite loop */
/* USER CODE BEGIN WHILE */
int cnt = 0;
while (1)
{
if (cnt++ > 10000) {
GPIOC->ODR ^= (1 << 13);
cnt = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
gw_process();
}
/* USER CODE END 3 */
+67
View File
@@ -0,0 +1,67 @@
//
// Created by MightyPork on 2018/03/31.
//
#include "main.h"
#include <stdbool.h>
#include <string.h>
#include "debug.h"
#include "msg_queue.h"
// the two USB messaging queues
MQueue usb_rxq;
MQueue usb_txq;
void mq_init(MQueue *mq)
{
mq->lr = MQ_LEN-1;
}
bool mq_can_post(MQueue *mq)
{
return mq->nw != mq->lr;
}
bool mq_post(MQueue *mq, const uint8_t *buffer, uint32_t len)
{
if (!mq_can_post(mq)) {
dbg("FULL!");
return false;
}
if (len >= MQ_SLOT_LEN) {
dbg("mq post too long!");
return false;
}
memcpy(mq->slots[mq->nw].packet, buffer, len);
// pad with zeros
if (len < MQ_SLOT_LEN) memset(mq->slots[mq->nw].packet+len, 0, MQ_SLOT_LEN - len);
mq->nw++;
if (mq->nw == MQ_LEN) mq->nw = 0;
return true;
}
bool mq_can_read(MQueue *mq)
{
// handle LR at the end, NW at 0 (initial state)
if (mq->lr == MQ_LEN-1) return mq->nw > 0;
// wrap-around - if LR not at the end, always have some to read
if (mq->nw <= mq->lr) return true;
// forward - one between
return mq->lr < mq->nw - 1;
}
bool mq_read(MQueue *mq, uint8_t *buffer)
{
if (!mq_can_read(mq)) {
return false;
}
mq->lr++;
if (mq->lr == MQ_LEN) mq->lr = 0;
memcpy(buffer, mq->slots[mq->lr].packet, MQ_SLOT_LEN);
return true;
}
+100
View File
@@ -0,0 +1,100 @@
#include <string.h>
#include "payload_builder.h"
#define pb_check_capacity(pb, needed) \
if ((pb)->current + (needed) > (pb)->end) { \
if ((pb)->full_handler == NULL || !(pb)->full_handler(pb, needed)) (pb)->ok = 0; \
}
/** Write from a buffer */
bool pb_buf(PayloadBuilder *pb, const uint8_t *buf, uint32_t len)
{
pb_check_capacity(pb, len);
if (!pb->ok) return false;
memcpy(pb->current, buf, len);
pb->current += len;
return true;
}
/** Write s zero terminated string */
bool pb_string(PayloadBuilder *pb, const char *str)
{
uint32_t len = (uint32_t) strlen(str);
pb_check_capacity(pb, len+1);
if (!pb->ok) return false;
memcpy(pb->current, str, len+1);
pb->current += len+1;
return true;
}
/** Write uint8_t to the buffer */
bool pb_u8(PayloadBuilder *pb, uint8_t byte)
{
pb_check_capacity(pb, 1);
if (!pb->ok) return false;
*pb->current++ = byte;
return true;
}
/** Write uint16_t to the buffer. */
bool pb_u16(PayloadBuilder *pb, uint16_t word)
{
pb_check_capacity(pb, 2);
if (!pb->ok) return false;
if (pb->bigendian) {
*pb->current++ = (uint8_t) ((word >> 8) & 0xFF);
*pb->current++ = (uint8_t) (word & 0xFF);
} else {
*pb->current++ = (uint8_t) (word & 0xFF);
*pb->current++ = (uint8_t) ((word >> 8) & 0xFF);
}
return true;
}
/** Write uint32_t to the buffer. */
bool pb_u32(PayloadBuilder *pb, uint32_t word)
{
pb_check_capacity(pb, 4);
if (!pb->ok) return false;
if (pb->bigendian) {
*pb->current++ = (uint8_t) ((word >> 24) & 0xFF);
*pb->current++ = (uint8_t) ((word >> 16) & 0xFF);
*pb->current++ = (uint8_t) ((word >> 8) & 0xFF);
*pb->current++ = (uint8_t) (word & 0xFF);
} else {
*pb->current++ = (uint8_t) (word & 0xFF);
*pb->current++ = (uint8_t) ((word >> 8) & 0xFF);
*pb->current++ = (uint8_t) ((word >> 16) & 0xFF);
*pb->current++ = (uint8_t) ((word >> 24) & 0xFF);
}
return true;
}
/** Write int8_t to the buffer. */
bool pb_i8(PayloadBuilder *pb, int8_t byte)
{
return pb_u8(pb, ((union conv8){.i8 = byte}).u8);
}
/** Write int16_t to the buffer. */
bool pb_i16(PayloadBuilder *pb, int16_t word)
{
return pb_u16(pb, ((union conv16){.i16 = word}).u16);
}
/** Write int32_t to the buffer. */
bool pb_i32(PayloadBuilder *pb, int32_t word)
{
return pb_u32(pb, ((union conv32){.i32 = word}).u32);
}
/** Write 4-byte float to the buffer. */
bool pb_float(PayloadBuilder *pb, float f)
{
return pb_u32(pb, ((union conv32){.f32 = f}).u32);
}
+121
View File
@@ -0,0 +1,121 @@
#include "payload_parser.h"
#define pp_check_capacity(pp, needed) \
if ((pp)->current + (needed) > (pp)->end) { \
if ((pp)->empty_handler == NULL || !(pp)->empty_handler(pp, needed)) {(pp)->ok = 0;} ; \
}
void pp_skip(PayloadParser *pp, uint32_t num)
{
pp->current += num;
}
uint8_t pp_u8(PayloadParser *pp)
{
pp_check_capacity(pp, 1);
if (!pp->ok) return 0;
return *pp->current++;
}
uint16_t pp_u16(PayloadParser *pp)
{
pp_check_capacity(pp, 2);
if (!pp->ok) return 0;
uint16_t x = 0;
if (pp->bigendian) {
x |= *pp->current++ << 8;
x |= *pp->current++;
} else {
x |= *pp->current++;
x |= *pp->current++ << 8;
}
return x;
}
uint32_t pp_u32(PayloadParser *pp)
{
pp_check_capacity(pp, 4);
if (!pp->ok) return 0;
uint32_t x = 0;
if (pp->bigendian) {
x |= (uint32_t) (*pp->current++ << 24);
x |= (uint32_t) (*pp->current++ << 16);
x |= (uint32_t) (*pp->current++ << 8);
x |= *pp->current++;
} else {
x |= *pp->current++;
x |= (uint32_t) (*pp->current++ << 8);
x |= (uint32_t) (*pp->current++ << 16);
x |= (uint32_t) (*pp->current++ << 24);
}
return x;
}
const uint8_t *pp_tail(PayloadParser *pp, uint32_t *length)
{
int32_t len = (int) (pp->end - pp->current);
if (!pp->ok || len <= 0) {
if (length != NULL) *length = 0;
return NULL;
}
if (length != NULL) {
*length = (uint32_t) len;
}
return pp->current;
}
/** Read int8_t from the payload. */
int8_t pp_i8(PayloadParser *pp)
{
return ((union conv8) {.u8 = pp_u8(pp)}).i8;
}
/** Read int16_t from the payload. */
int16_t pp_i16(PayloadParser *pp)
{
return ((union conv16) {.u16 = pp_u16(pp)}).i16;
}
/** Read int32_t from the payload. */
int32_t pp_i32(PayloadParser *pp)
{
return ((union conv32) {.u32 = pp_u32(pp)}).i32;
}
/** Read 4-byte float from the payload. */
float pp_float(PayloadParser *pp)
{
return ((union conv32) {.u32 = pp_u32(pp)}).f32;
}
/** Read a zstring */
uint32_t pp_string(PayloadParser *pp, char *buffer, uint32_t maxlen)
{
pp_check_capacity(pp, 1);
uint32_t len = 0;
while (len < maxlen-1 && pp->current != pp->end) {
char c = *buffer++ = *pp->current++;
if (c == 0) break;
len++;
}
*buffer = 0;
return len;
}
/** Read a buffer */
uint32_t pp_buf(PayloadParser *pp, uint8_t *buffer, uint32_t maxlen)
{
uint32_t len = 0;
while (len < maxlen && pp->current != pp->end) {
*buffer++ = *pp->current++;
len++;
}
return len;
}
+35 -5
View File
@@ -49,6 +49,7 @@
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
#include <stdbool.h>
#include "gpio.h"
#include "dma.h"
@@ -77,12 +78,13 @@ void MX_USART1_UART_Init(void)
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// we don't use Rx
// GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
// GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
// LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 DMA Init */
/* USART1_TX Init */
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
@@ -98,6 +100,9 @@ void MX_USART1_UART_Init(void)
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MDATAALIGN_BYTE);
// the USART address
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_4, LL_USART_DMA_GetRegAddr(USART1));
USART_InitStruct.BaudRate = 115200;
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
@@ -109,10 +114,35 @@ void MX_USART1_UART_Init(void)
LL_USART_ConfigAsyncMode(USART1);
LL_USART_Enable(USART1);
}
/* USER CODE BEGIN 1 */
static volatile bool usart_dma_first = true;
/** Wait for the last DMA request to finish - so the buffer can be re-filled with new content */
void MX_USART_DmaWaitReady(void)
{
if (!usart_dma_first) {
// wait for the last transfer to finish
while (!LL_DMA_IsActiveFlag_TC4(DMA1));
}
LL_USART_DisableDMAReq_TX(USART1);
}
/** Send new content using DMA */
void MX_USART_DmaSend(uint8_t *buffer, uint32_t length)
{
usart_dma_first = false;
LL_USART_EnableDMAReq_TX(USART1);
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);
LL_DMA_ClearFlag_TC4(DMA1);
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_4, (uint32_t) buffer);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, length);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
}
/* USER CODE END 1 */
+4
View File
@@ -48,6 +48,7 @@
*/
/* Includes ------------------------------------------------------------------*/
#include <debug.h>
#include "usbd_cdc_if.h"
/* USER CODE BEGIN INCLUDE */
@@ -293,6 +294,9 @@ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
/* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
//
return (USBD_OK);
/* USER CODE END 6 */
}
+12 -11
View File
@@ -48,6 +48,7 @@
*/
/* Includes ------------------------------------------------------------------*/
#include <inttypes.h>
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_conf.h"
@@ -91,10 +92,10 @@
* @{
*/
#define USBD_VID 4617
#define USBD_VID 0x1209
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#define USBD_PID_FS 19553
#define USBD_MANUFACTURER_STRING "MightyPork"
#define USBD_PID_FS 0x4c61
#define USBD_PRODUCT_STRING_FS "GEX wireless dongle"
#define USBD_SERIALNUMBER_STRING_FS "00000000001A"
#define USBD_CONFIGURATION_STRING_FS "CDC Config"
@@ -290,14 +291,14 @@ uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *l
*/
uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == USBD_SPEED_HIGH)
{
USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
}
char buff[27];
sprintf(buff, "%08"PRIX32"-%08"PRIX32"-%08"PRIX32,
LL_GetUID_Word0(),
LL_GetUID_Word1(),
LL_GetUID_Word2()
);
USBD_GetString ((uint8_t *) &buff[0], USBD_StrDesc, length);
return USBD_StrDesc;
}