diff --git a/Firmware/Chameleon-Mini/Chameleon-Mini.c b/Firmware/Chameleon-Mini/Chameleon-Mini.c index a4579f09..87d2fa89 100644 --- a/Firmware/Chameleon-Mini/Chameleon-Mini.c +++ b/Firmware/Chameleon-Mini/Chameleon-Mini.c @@ -19,22 +19,19 @@ int main(void) { if (SystemTick100ms()) { LEDTick(); // this has to be the first function called here, since it is time-critical - the functions below may have non-negligible runtimes! PinTick(); - RandomTick(); TerminalTick(); ButtonTick(); - LogTick(); ApplicationTick(); + LogTick(); CommandLineTick(); AntennaLevelTick(); - LEDHook(LED_POWERED, LED_ON); } - - TerminalTask(); - LogTask(); ApplicationTask(); CodecTask(); + LogTask(); + TerminalTask(); } } diff --git a/Firmware/Chameleon-Mini/Chameleon-Mini.h b/Firmware/Chameleon-Mini/Chameleon-Mini.h index f2c6aafa..0af59fe5 100644 --- a/Firmware/Chameleon-Mini/Chameleon-Mini.h +++ b/Firmware/Chameleon-Mini/Chameleon-Mini.h @@ -18,6 +18,7 @@ #include "Random.h" #include "Button.h" #include "Log.h" +#include "LiveLogTick.h" #include "AntennaLevel.h" #include "Settings.h" diff --git a/Firmware/Chameleon-Mini/LUFAConfig.h b/Firmware/Chameleon-Mini/LUFAConfig.h index 4060c234..aa5ec1a5 100644 --- a/Firmware/Chameleon-Mini/LUFAConfig.h +++ b/Firmware/Chameleon-Mini/LUFAConfig.h @@ -67,12 +67,16 @@ #define USE_FLASH_DESCRIPTORS // #define USE_EEPROM_DESCRIPTORS // #define NO_INTERNAL_SERIAL +#undef NO_INTERNAL_SERIAL #define FIXED_CONTROL_ENDPOINT_SIZE 8 // #define DEVICE_STATE_AS_GPIOR {Insert Value Here} #define FIXED_NUM_CONFIGURATIONS 1 // #define CONTROL_ONLY_DEVICE -#define MAX_ENDPOINT_INDEX 5 +#ifndef MAX_ENDPOINT_INDEX + #define MAX_ENDPOINT_INDEX 4 // 5 +#endif // #define NO_DEVICE_REMOTE_WAKEUP // #define NO_DEVICE_SELF_POWER +#undef NO_DEVICE_SELF_POWER #endif diff --git a/Firmware/Chameleon-Mini/LiveLogTick.h b/Firmware/Chameleon-Mini/LiveLogTick.h new file mode 100644 index 00000000..1f99cf09 --- /dev/null +++ b/Firmware/Chameleon-Mini/LiveLogTick.h @@ -0,0 +1,121 @@ +/* LiveLogTick.h : Handle flushing of live logging buffers out through USB + * by an atomic code block with interrupts disabled. + * If there are many logs being generated at once, this will maintain + * consistency in the returned buffers and prevent the contents of + * USB serial data from getting jumbled or concatenated. + */ + +#ifndef __LIVE_LOG_TICK_H__ +#define __LIVE_LOG_TICK_H__ + +#include +#include +#include +#include +#include + +#include "LUFADescriptors.h" + +#include "Log.h" +#include "Terminal/Terminal.h" + +#define cli_memory() __asm volatile( "cli" ::: "memory" ) +#define sei_memory() __asm volatile( "sei" ::: "memory" ) + +#ifndef FLUSH_LOGS_ON_SPACE_ERROR + #define FLUSH_LOGS_ON_SPACE_ERROR (1) +#endif + +typedef struct LogBlockListNode { + uint8_t *logBlockStart; + uint8_t logBlockSize; + struct LogBlockListNode *nextBlock; +} LogBlockListNode; + +extern LogBlockListNode *LogBlockListBegin; +extern LogBlockListNode *LogBlockListEnd; +extern uint8_t LogBlockListElementCount; + +#define LIVE_LOGGER_POST_TICKS (3) +extern uint8_t LiveLogModePostTickCount; + +INLINE bool AtomicAppendLogBlock(LogEntryEnum logCode, uint16_t sysTickTime, const uint8_t *logData, uint8_t logDataSize); +INLINE void FreeLogBlocks(void); +INLINE bool AtomicLiveLogTick(void); +INLINE bool LiveLogTick(void); + +INLINE bool +AtomicAppendLogBlock(LogEntryEnum logCode, uint16_t sysTickTime, const uint8_t *logData, uint8_t logDataSize) { + bool status = true; + if((logDataSize + 4 > LogMemLeft) && (LogMemPtr != LogMem)) { + if(FLUSH_LOGS_ON_SPACE_ERROR) { + LiveLogTick(); + FreeLogBlocks(); + } + status = false; + } + else if(logDataSize + 4 <= LogMemLeft) { + LogBlockListNode *logBlock = (LogBlockListNode *) malloc(sizeof(LogBlockListNode)); + logBlock->logBlockStart = LogMemPtr; + logBlock->logBlockSize = logDataSize + 4; + logBlock->nextBlock = NULL; + *(LogMemPtr++) = logCode; + *(LogMemPtr++) = logDataSize; + *(LogMemPtr++) = (uint8_t) (sysTickTime >> 8); + *(LogMemPtr++) = (uint8_t) (sysTickTime >> 0); + memcpy(LogMemPtr, logData, logDataSize); + LogMemPtr += logDataSize; + LogMemLeft -= logDataSize + 4; + if(LogBlockListBegin != NULL && LogBlockListEnd != NULL) { + LogBlockListEnd->nextBlock = logBlock; + LogBlockListEnd = logBlock; + } + else { + LogBlockListBegin = LogBlockListEnd = logBlock; + } + ++LogBlockListElementCount; + } + else { + status = false; + } + return status; +} + +INLINE void +FreeLogBlocks(void) { + LogMemPtr = &LogMem[0]; + LogBlockListNode *logBlockCurrent = LogBlockListBegin; + LogBlockListNode *logBlockNext = NULL; + while(logBlockCurrent != NULL) { + logBlockNext = logBlockCurrent->nextBlock; + LogMemLeft += logBlockCurrent->logBlockSize; + free(logBlockCurrent); + logBlockCurrent = logBlockNext; + } + LogBlockListBegin = LogBlockListEnd = NULL; + LogBlockListElementCount = 0; +} + +INLINE bool +AtomicLiveLogTick(void) { + bool status; + status = LiveLogTick(); + return status; +} + +INLINE bool +LiveLogTick(void) { + bool status = LogBlockListBegin == NULL; + LogBlockListNode *logBlockCurrent = LogBlockListBegin; + while(logBlockCurrent != NULL && LogBlockListElementCount > 0) { + TerminalFlushBuffer(); + TerminalSendBlock(logBlockCurrent->logBlockStart, logBlockCurrent->logBlockSize); + TerminalFlushBuffer(); + logBlockCurrent = logBlockCurrent->nextBlock; + } + FreeLogBlocks(); + LiveLogModePostTickCount = 0x00; + return status; +} + +#endif diff --git a/Firmware/Chameleon-Mini/Log.c b/Firmware/Chameleon-Mini/Log.c index 721cd741..5bc34496 100644 --- a/Firmware/Chameleon-Mini/Log.c +++ b/Firmware/Chameleon-Mini/Log.c @@ -1,22 +1,29 @@ #include "Log.h" +#include "LiveLogTick.h" #include "Settings.h" #include "Terminal/Terminal.h" #include "System.h" #include "Map.h" #include "LEDHook.h" -static uint8_t LogMem[LOG_SIZE]; -static uint8_t *LogMemPtr; -static uint16_t LogMemLeft; +uint8_t LogMem[LOG_SIZE]; +uint8_t *LogMemPtr; +uint16_t LogMemLeft; + static uint16_t LogFRAMAddr = FRAM_LOG_START_ADDR; static uint8_t EEMEM LogFRAMAddrValid = false; static bool EnableLogSRAMtoFRAM = false; LogFuncType CurrentLogFunc; +LogBlockListNode *LogBlockListBegin = NULL; +LogBlockListNode *LogBlockListEnd = NULL; +uint8_t LogBlockListElementCount = 0; +uint8_t LiveLogModePostTickCount = 0; + static const MapEntryType PROGMEM LogModeMap[] = { { .Id = LOG_MODE_OFF, .Text = "OFF" }, { .Id = LOG_MODE_MEMORY, .Text = "MEMORY" }, - { .Id = LOG_MODE_LIVE, .Text = "LIVE" } + { .Id = LOG_MODE_LIVE, .Text = "LIVE" } }; static void LogFuncOff(LogEntryEnum Entry, const void *Data, uint8_t Length) { @@ -50,12 +57,12 @@ static void LogFuncMemory(LogEntryEnum Entry, const void *Data, uint8_t Length) static void LogFuncLive(LogEntryEnum Entry, const void *Data, uint8_t Length) { uint16_t SysTick = SystemGetSysTick(); - - TerminalSendByte((uint8_t) Entry); - TerminalSendByte((uint8_t) Length); - TerminalSendByte((uint8_t)(SysTick >> 8)); - TerminalSendByte((uint8_t)(SysTick >> 0)); - TerminalSendBlock(Data, Length); + //TerminalSendByte((uint8_t) Entry); + //TerminalSendByte((uint8_t) Length); + //TerminalSendByte((uint8_t)(SysTick >> 8)); + //TerminalSendByte((uint8_t)(SysTick >> 0)); + //TerminalSendBlock(Data, Length); + AtomicAppendLogBlock(Entry, SysTick, Data, Length); } void LogInit(void) { @@ -79,6 +86,9 @@ void LogInit(void) { } void LogTick(void) { + if (GlobalSettings.ActiveSettingPtr->LogMode == LOG_MODE_LIVE && + (++LiveLogModePostTickCount % LIVE_LOGGER_POST_TICKS) == 0) + AtomicLiveLogTick(); if (EnableLogSRAMtoFRAM) LogSRAMToFRAM(); } diff --git a/Firmware/Chameleon-Mini/Log.h b/Firmware/Chameleon-Mini/Log.h index b6e49bbf..9d74a03d 100644 --- a/Firmware/Chameleon-Mini/Log.h +++ b/Firmware/Chameleon-Mini/Log.h @@ -8,6 +8,10 @@ #define FRAM_LOG_START_ADDR 0x4002 // directly after the address #define FRAM_LOG_SIZE 0x3FFE // the whole second half (minus the 2 Bytes of Address) +extern uint8_t LogMem[LOG_SIZE]; +extern uint8_t *LogMemPtr; +extern uint16_t LogMemLeft; + /** Enum for log entry type. \note Every entry type has a specific integer value, which can be found in the source code. */ typedef enum { /* Generic */ diff --git a/Firmware/Chameleon-Mini/Makefile b/Firmware/Chameleon-Mini/Makefile index 4555d517..1efe4478 100644 --- a/Firmware/Chameleon-Mini/Makefile +++ b/Firmware/Chameleon-Mini/Makefile @@ -107,8 +107,11 @@ SRC += Codec/ISO15693.c SRC += Application/Vicinity.c Application/Sl2s2002.c Application/TITagitstandard.c Application/ISO15693-A.c Application/EM4233.c SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) LUFA_PATH = ../LUFA -CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -DFLASH_DATA_ADDR=$(FLASH_DATA_ADDR) -DFLASH_DATA_SIZE=$(FLASH_DATA_SIZE) -DSPM_HELPER_ADDR=$(SPM_HELPER_ADDR) -DBUILD_DATE=$(BUILD_DATE) -DCOMMIT_ID=\"$(COMMIT_ID)\" $(SETTINGS) -LD_FLAGS = -Wl,--section-start=.flashdata=$(FLASH_DATA_ADDR) -Wl,--section-start=.spmhelper=$(SPM_HELPER_ADDR) +CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -DFLASH_DATA_ADDR=$(FLASH_DATA_ADDR) -DFLASH_DATA_SIZE=$(FLASH_DATA_SIZE) \ + -DSPM_HELPER_ADDR=$(SPM_HELPER_ADDR) -DBUILD_DATE=$(BUILD_DATE) -DCOMMIT_ID=\"$(COMMIT_ID)\" $(SETTINGS) \ + -D__AVR_ATxmega128A4U__ -D__PROG_TYPES_COMPAT__ -DMAX_ENDPOINT_INDEX=4 \ + -std=gnu99 -Werror=implicit-function-declaration +LD_FLAGS = $(CC_FLAGS) -Wl,--section-start=.flashdata=$(FLASH_DATA_ADDR) -Wl,--section-start=.spmhelper=$(SPM_HELPER_ADDR) OBJDIR = Bin OBJECT_FILES = @@ -128,6 +131,7 @@ AVRDUDE_WRITE_EEPROM_LATEST = -U eeprom:w:Latest/Chameleon-Mini.eep # Default target all: + $(CROSS)-size --mcu=atmega128 -C $(TARGET).elf # Include LUFA build script makefiles include $(LUFA_PATH)/Build/lufa_core.mk diff --git a/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/Firmware/Chameleon-Mini/Terminal/CommandLine.c index 286e04d2..b4ada80a 100644 --- a/Firmware/Chameleon-Mini/Terminal/CommandLine.c +++ b/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -360,7 +360,7 @@ static const CommandStatusType PROGMEM StatusTable[] = { STATUS_TABLE_ENTRY(COMMAND_ERR_TIMEOUT_ID, COMMAND_ERR_TIMEOUT), }; -static uint16_t BufferIdx; +uint16_t TerminalBufferIdx = 0; void (*CommandLinePendingTaskTimeout)(void) = NO_FUNCTION; // gets called on Timeout static bool TaskPending = false; @@ -476,7 +476,7 @@ static void DecodeCommand(void) { } void CommandLineInit(void) { - BufferIdx = 0; + TerminalBufferIdx = 0; } bool CommandLineProcessByte(uint8_t Byte) { @@ -487,24 +487,24 @@ bool CommandLineProcessByte(uint8_t Byte) { } /* Prevent buffer overflow and account for '\0' */ - if (BufferIdx < TERMINAL_BUFFER_SIZE - 1) { - TerminalBuffer[BufferIdx++] = Byte; + if (TerminalBufferIdx < TERMINAL_BUFFER_SIZE - 1) { + TerminalBuffer[TerminalBufferIdx++] = Byte; } } else if (Byte == '\r') { /* Process on \r. Terminate string and decode. */ - TerminalBuffer[BufferIdx] = '\0'; - BufferIdx = 0; + TerminalBuffer[TerminalBufferIdx] = '\0'; + TerminalBufferIdx = 0; if (!TaskPending) DecodeCommand(); } else if (Byte == '\b') { /* Backspace. Delete last character in buffer. */ - if (BufferIdx > 0) { - BufferIdx--; + if (TerminalBufferIdx > 0) { + TerminalBufferIdx--; } } else if (Byte == 0x1B) { /* Drop buffer on escape */ - BufferIdx = 0; + TerminalBufferIdx = 0; } else { /* Ignore other chars */ } diff --git a/Firmware/Chameleon-Mini/Terminal/Terminal.c b/Firmware/Chameleon-Mini/Terminal/Terminal.c index 0c927eaa..badd240d 100644 --- a/Firmware/Chameleon-Mini/Terminal/Terminal.c +++ b/Firmware/Chameleon-Mini/Terminal/Terminal.c @@ -27,7 +27,7 @@ USB_ClassInfo_CDC_Device_t TerminalHandle = { } }; -uint8_t TerminalBuffer[TERMINAL_BUFFER_SIZE]; +uint8_t TerminalBuffer[TERMINAL_BUFFER_SIZE] = { 0x00 }; TerminalStateEnum TerminalState = TERMINAL_UNINITIALIZED; static uint8_t TerminalInitDelay = INIT_DELAY; diff --git a/Firmware/Chameleon-Mini/Terminal/Terminal.h b/Firmware/Chameleon-Mini/Terminal/Terminal.h index 53413aff..b59088f1 100644 --- a/Firmware/Chameleon-Mini/Terminal/Terminal.h +++ b/Firmware/Chameleon-Mini/Terminal/Terminal.h @@ -26,6 +26,7 @@ typedef enum { } TerminalStateEnum; extern uint8_t TerminalBuffer[TERMINAL_BUFFER_SIZE]; +extern uint16_t TerminalBufferIdx; extern USB_ClassInfo_CDC_Device_t TerminalHandle; extern TerminalStateEnum TerminalState; @@ -49,4 +50,10 @@ void EVENT_USB_Device_ControlRequest(void); INLINE void TerminalSendChar(char c) { CDC_Device_SendByte(&TerminalHandle, c); } INLINE void TerminalSendByte(uint8_t Byte) { CDC_Device_SendByte(&TerminalHandle, Byte); } +INLINE void TerminalFlushBuffer(void) { + CDC_Device_Flush(&TerminalHandle); + TerminalBufferIdx = 0; + TerminalBuffer[TerminalBufferIdx] = '\0'; +} + #endif /* TERMINAL_H_ */