First mostly working - but untested - firmware include a working command parser baudrate modification functionality and also a untested bidirectional redirect ability for the second virtual serial device.

This commit is contained in:
klaute 2016-08-23 09:32:19 +02:00
parent 5a0e74de7a
commit 945a9c81c2
8 changed files with 381 additions and 22 deletions

View file

@ -17,8 +17,8 @@ ARCH = AVR8
F_CPU = 16000000
F_USB = $(F_CPU)
OPTIMIZATION = s
TARGET = USB2SerialMux
SRC = $(TARGET).c Descriptors.c uart/uart.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
TARGET = main
SRC = $(TARGET).c Descriptors.c uart/uart.c command_ctrl.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH = ../LUFA/LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -Iuart/
LD_FLAGS =

76
src/command_config.h Executable file
View file

@ -0,0 +1,76 @@
/*
* Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de
* Date: 08/2016
* License: GPLv3
*/
#ifndef __COMMAND_CONFIG_H__
#define __COMMAND_CONFIG_H__
/*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include "globals.h"
#include "uart/uart.h"
/*****************************************************************************/
void cc_setBaudrate(void);
void cc_getBaudrate(void);
void cc_startBootloader(void);
/*****************************************************************************/
#define CC_CMD_SET_BAUDRATE 0x0A
#define CC_CMD_GET_BAUDRATE 0x14
#define CC_CMD_START_BTLDR 0x32
/*****************************************************************************/
#define CC_CMD_SET_BAUDRATE_FUNC &cc_setBaudrate
#define CC_CMD_GET_BAUDRATE_FUNC &cc_getBaudrate
#define CC_CMD_START_BTLDR_FUNC &cc_startBootloader
/*****************************************************************************/
#define CC_CMD_SET_BAUDRATE_DATA_TO_READ 4 // set baudrate
#define CC_CMD_GET_BAUDRATE_DATA_TO_READ 0 // get baudrate
#define CC_CMD_START_BTLDR_DATA_TO_READ 0 // start bootloader
/*****************************************************************************/
#define CC_READ_DATA_MAX 64
/*****************************************************************************/
uint8_t cc_commands[] = {
CC_CMD_SET_BAUDRATE,
CC_CMD_GET_BAUDRATE,
CC_CMD_START_BTLDR,
};
void (*cc_cmd_functions[])() = {
CC_CMD_SET_BAUDRATE_FUNC,
CC_CMD_GET_BAUDRATE_FUNC,
CC_CMD_START_BTLDR_FUNC,
};
uint8_t cc_cmd_data_to_read[] = {
CC_CMD_SET_BAUDRATE_DATA_TO_READ,
CC_CMD_GET_BAUDRATE_DATA_TO_READ,
CC_CMD_START_BTLDR_DATA_TO_READ,
};
uint8_t cc_read_data[CC_READ_DATA_MAX];
/*****************************************************************************/
#endif

146
src/command_ctrl.c Executable file
View file

@ -0,0 +1,146 @@
/*
* Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de
* Date: 08/2016
* License: GPLv3
*/
/*****************************************************************************/
#include "command_ctrl.h"
#include "command_config.h"
// include user specific command control configuration and function definition
#include "command_config.h"
#include "command_functions.c"
/*****************************************************************************/
uint8_t cc_state = CC_STATE_READ_SOM1;
uint8_t cc_cmd_to_call = CC_CMD_NO_CMD;
uint8_t cc_cmd_received_correct = MSG_INCOMPLETE;
uint8_t cc_cmd_data_read_cnt = 0;
/*****************************************************************************/
void cc_init()
{
cc_state = CC_STATE_READ_SOM1;
cc_cmd_to_call = CC_CMD_NO_CMD;
cc_cmd_data_read_cnt = 0;
cc_cmd_received_correct = MSG_INCOMPLETE;
}
/*****************************************************************************/
void cc_abort()
{
// send abort message, then init
char* tmp = " ";
sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2,
MSG_TYPE_ANSWER_NOK,
MSG_EOM1, MSG_EOM2);
USB_serialStreamWriteC(tmp, strlen(tmp));
cc_init();
}
/*****************************************************************************/
void cc_processData(uint8_t c)
{
switch (cc_state)
{
//*********************************//
case CC_STATE_READ_SOM1:;
if (c == MSG_SOM1)
cc_state = CC_STATE_READ_SOM2;
else
cc_abort();
break;
//*********************************//
case CC_STATE_READ_SOM2:;
if (c == MSG_SOM2)
cc_state = CC_STATE_READ_CMD;
else
cc_abort();
break;
//*********************************//
case CC_STATE_READ_CMD:;
for (uint8_t i = 0; i < sizeof(cc_commands)/sizeof(uint8_t); i++)
{
if (cc_commands[i] == c)
{
if (cc_cmd_data_to_read[i] > 0)
cc_state = CC_STATE_READ_DATA;
else
cc_state = CC_STATE_READ_EOM1;
cc_cmd_to_call = i; // remember the index of command to call
break; // break the loop
}
}
break;
//*********************************//
case CC_STATE_READ_DATA:;
// write the variable c to the input buffer
cc_read_data[cc_cmd_data_read_cnt] = c;
if (cc_cmd_data_read_cnt >= cc_cmd_data_to_read[cc_cmd_to_call]-1)
{
cc_state = CC_STATE_READ_EOM1;
}
cc_cmd_data_read_cnt++;
break;
//*********************************//
case CC_STATE_READ_EOM1:;
if (c == MSG_EOM1)
cc_state = CC_STATE_READ_EOM2;
else
cc_abort();
break;
//*********************************//
case CC_STATE_READ_EOM2:;
if (c == MSG_EOM2)
{
cc_cmd_received_correct = MSG_COMPLETE;
} else
cc_abort();
break;
default:
cc_abort();
}
//*********************************//
if (cc_cmd_received_correct == MSG_COMPLETE)
{
// call the function using the received data
(*cc_cmd_functions[cc_cmd_to_call])();
// clear the read buffer
cc_clearReadDataBuffer();
cc_init();
}
}
/*****************************************************************************/
void cc_clearReadDataBuffer()
{
for (uint8_t i = 0; i < CC_READ_DATA_MAX; i++)
{
cc_read_data[i] = 0x00;
}
}
/*****************************************************************************/

39
src/command_ctrl.h Executable file
View file

@ -0,0 +1,39 @@
/*
* Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de
* Date: 08/2016
* License: GPLv3
*/
#ifndef __COMMAND_CTRL_H__
#define __COMMAND_CTRL_H__
#include <stdint.h>
/*****************************************************************************/
#define CC_STATE_READ_SOM1 20
#define CC_STATE_READ_SOM2 30
#define CC_STATE_READ_CMD 40
#define CC_STATE_READ_DATA 50
#define CC_STATE_READ_EOM1 60
#define CC_STATE_READ_EOM2 70
/*****************************************************************************/
#define CC_CMD_NO_CMD 0
#define MSG_INCOMPLETE 10
#define MSG_COMPLETE 20
/*****************************************************************************/
extern void USB_serialStreamWriteC(char*, uint16_t);
void cc_init(void);
void cc_abort(void);
void cc_processData(uint8_t);
void cc_clearReadDataBuffer(void);
/*****************************************************************************/
#endif

62
src/command_functions.c Executable file
View file

@ -0,0 +1,62 @@
/*
* Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de
* Date: 08/2016
* License: GPLv3
*/
/*****************************************************************************/
extern void USB_serialStreamWriteC(char*, uint16_t);
extern uint32_t eep_baudrate;
extern uint32_t baudrate;
/*****************************************************************************/
void cc_setBaudrate()
{
baudrate = (uint32_t)cc_read_data[0] << 24;
baudrate += (uint32_t)cc_read_data[1] << 16;
baudrate += (uint32_t)cc_read_data[2] << 8;
baudrate += (uint32_t)cc_read_data[3];
eeprom_busy_wait();
eeprom_write_dword(&eep_baudrate, baudrate);
eeprom_busy_wait();
uart_init( UART_BAUD_SELECT(baudrate, F_CPU) );
char* sBody = " ";
sprintf(sBody, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2);
USB_serialStreamWriteC(sBody, strlen(sBody));
}
/*****************************************************************************/
void cc_getBaudrate()
{
char* sBody = " ";
sprintf(sBody, "%c%c%c%c%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_BAUDRATE,
(uint8_t)((baudrate & 0xff000000) >> 24),
(uint8_t)((baudrate & 0xff0000) >> 16),
(uint8_t)((baudrate & 0xff00) >> 8),
(uint8_t) (baudrate & 0xff),
MSG_EOM1, MSG_EOM2);
USB_serialStreamWriteC(sBody, strlen(sBody));
}
/*****************************************************************************/
void cc_startBootloader()
{
// enable the watchdog without a time interval to use
wdt_enable(0);
// trigger watchdog
while(1) {};
}
/*****************************************************************************/

15
src/globals.h Executable file
View file

@ -0,0 +1,15 @@
/*****************************************************************************/
/* Message byte definitions: */
#define MSG_SOM1 0x3c
#define MSG_SOM2 0x3e
#define MSG_EOM1 0x0d
#define MSG_EOM2 0x0a
#define MSG_TYPE_ANSWER_OK 0x01
#define MSG_TYPE_ANSWER_NOK 0x02
#define MSG_TYPE_BAUDRATE 0x03
/*****************************************************************************/

View file

@ -34,7 +34,15 @@
* is responsible for the initial application hardware configuration.
*/
#include "USB2SerialMux.h"
#include "main.h"
/**************************************************************************************/
uint32_t EEMEM eep_baudrate;
uint32_t baudrate = 115200; // replacement for the UART_BAUDRATE definition
/**************************************************************************************/
/** Contains the current baud rate and other settings of the first virtual serial port. While this demo does not use
* the physical USART and thus does not use these settings, they must still be retained and returned to the host
@ -70,8 +78,18 @@ int main(void)
{
SetupHardware();
eeprom_busy_wait();
baudrate = eeprom_read_dword(&eep_baudrate);
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
if (baudrate == 0xffffffff)
{
eeprom_busy_wait();
baudrate = 115200;
eeprom_write_dword(&eep_baudrate, baudrate);
}
// initialize the command interpreter
cc_init();
SET_ERR_MASK(ERRMASK_USB_NOTREADY);
GlobalInterruptEnable();
@ -109,7 +127,7 @@ void SetupHardware(void)
#endif
/* UART Hardware Initialization */
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
uart_init( UART_BAUD_SELECT(baudrate, F_CPU) );
/* USB Hardware Initialization */
USB_Init();
@ -208,9 +226,6 @@ void EVENT_USB_Device_ControlRequest(void)
*/
void CDC1_Task(void)
{
char* ReportString = NULL;
static bool ActionSent = false;
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
@ -221,9 +236,6 @@ void CDC1_Task(void)
if (Endpoint_IsOUTReceived())
{
// TODO disable this line if data should be received
Endpoint_ClearOUT(); // Throw away any received data from the host at this point
/* Create a temp buffer big enough to hold the incoming endpoint packet */
uint8_t Buffer[Endpoint_BytesInEndpoint()];
@ -236,30 +248,32 @@ void CDC1_Task(void)
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearOUT();
// TODO Read the data from the host
for (uint16_t i = 0; i < DataLength; i++)
{
// process the received data and descide to do an action
// uint8_t cmd = processReceivedControlData(&Buffer, DataLength);
// if (cmd != NULL)
// {
// call(cmd)
// }
cc_processData(Buffer[i]);
}
}
}
void USB_serialStreamWriteC(char *data, uint16_t len)
{
//===========================================================================
/* Determine if data/answeres should be sent to the host
* the previous RX section should be clarify that behaviour.
*/
/* Flag management - Only allow one string to be sent per action */
if ((ReportString != NULL) && (ActionSent == false) && LineEncoding1.BaudRateBPS)
if (data != NULL && len > 0 && LineEncoding1.BaudRateBPS)
{
ActionSent = true;
/* Select the Serial Tx Endpoint */
Endpoint_SelectEndpoint(CDC1_TX_EPADDR);
/* Write the String to the Endpoint */
Endpoint_Write_Stream_LE(ReportString, strlen(ReportString), NULL);
Endpoint_Write_Stream_LE(data, len, NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();

View file

@ -41,11 +41,16 @@
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <string.h>
#include "Descriptors.h"
#include "globals.h"
#include "command_ctrl.h"
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
@ -53,7 +58,7 @@
/* UART definitions: */
#define UART_BAUD_RATE 115200
//#define UART_BAUD_RATE 115200
#define OUTPUT_BUFFER_SIZE 100
#include "uart/uart.h" // include after the definition
@ -84,5 +89,7 @@
void EVENT_USB_Device_ConfigurationChanged(void);
void EVENT_USB_Device_ControlRequest(void);
void USB_serialStreamWriteC(char*, uint16_t);
#endif