1
0
mirror of https://github.com/peterantypas/maiana.git synced 2025-05-29 05:40:15 -07:00

Rudimentary serial commands for web API integration

This commit is contained in:
Peter Antypas 2016-06-25 22:35:02 -07:00
parent 33b02d07eb
commit 4ca6cddf9e
12 changed files with 376 additions and 37 deletions

View File

@ -171,7 +171,7 @@
</fileInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
<entry excluding="src/stm32f3-stdperiph/stm32f30x_wwdg.c|src/stm32f3-stdperiph/stm32f30x_rtc.c|src/stm32f3-stdperiph/stm32f30x_pwr.c|src/stm32f3-stdperiph/stm32f30x_opamp.c|src/stm32f3-stdperiph/stm32f30x_flash.c|src/stm32f3-stdperiph/stm32f30x_dma.c|src/stm32f3-stdperiph/stm32f30x_dbgmcu.c|src/stm32f3-stdperiph/stm32f30x_dac.c|src/stm32f3-stdperiph/stm32f30x_crc.c|src/stm32f3-stdperiph/stm32f30x_comp.c|src/stm32f3-stdperiph/stm32f30x_can.c|src/stm32f3-stdperiph/stm32f30x_adc.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="system"/>
<entry excluding="src/stm32f3-stdperiph/stm32f30x_wwdg.c|src/stm32f3-stdperiph/stm32f30x_rtc.c|src/stm32f3-stdperiph/stm32f30x_pwr.c|src/stm32f3-stdperiph/stm32f30x_opamp.c|src/stm32f3-stdperiph/stm32f30x_dma.c|src/stm32f3-stdperiph/stm32f30x_dbgmcu.c|src/stm32f3-stdperiph/stm32f30x_dac.c|src/stm32f3-stdperiph/stm32f30x_crc.c|src/stm32f3-stdperiph/stm32f30x_comp.c|src/stm32f3-stdperiph/stm32f30x_can.c|src/stm32f3-stdperiph/stm32f30x_adc.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="system"/>
</sourceEntries>
</configuration>
</storageModule>
@ -333,7 +333,7 @@
</fileInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
<entry excluding="src/stm32f3-stdperiph/stm32f30x_wwdg.c|src/stm32f3-stdperiph/stm32f30x_rtc.c|src/stm32f3-stdperiph/stm32f30x_pwr.c|src/stm32f3-stdperiph/stm32f30x_opamp.c|src/stm32f3-stdperiph/stm32f30x_flash.c|src/stm32f3-stdperiph/stm32f30x_dma.c|src/stm32f3-stdperiph/stm32f30x_dbgmcu.c|src/stm32f3-stdperiph/stm32f30x_dac.c|src/stm32f3-stdperiph/stm32f30x_crc.c|src/stm32f3-stdperiph/stm32f30x_comp.c|src/stm32f3-stdperiph/stm32f30x_can.c|src/stm32f3-stdperiph/stm32f30x_adc.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="system"/>
<entry excluding="src/stm32f3-stdperiph/stm32f30x_wwdg.c|src/stm32f3-stdperiph/stm32f30x_rtc.c|src/stm32f3-stdperiph/stm32f30x_pwr.c|src/stm32f3-stdperiph/stm32f30x_opamp.c|src/stm32f3-stdperiph/stm32f30x_dma.c|src/stm32f3-stdperiph/stm32f30x_dbgmcu.c|src/stm32f3-stdperiph/stm32f30x_dac.c|src/stm32f3-stdperiph/stm32f30x_crc.c|src/stm32f3-stdperiph/stm32f30x_comp.c|src/stm32f3-stdperiph/stm32f30x_can.c|src/stm32f3-stdperiph/stm32f30x_adc.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="system"/>
</sourceEntries>
</configuration>
</storageModule>

View File

@ -0,0 +1,12 @@
#!/bin/bash
BIN=ais_transponder.bin
# Write the metadata first, before any reset
if [ $? -eq 0 ] then
st-flash write $BIN 0x08004000
else
echo "Flashing failed"
fi

View File

@ -9,6 +9,7 @@ C_SRCS += \
CPP_SRCS += \
../src/AISMessages.cpp \
../src/ChannelManager.cpp \
../src/CommandProcessor.cpp \
../src/DataTerminal.cpp \
../src/DebugPrinter.cpp \
../src/EEPROM.cpp \
@ -35,6 +36,7 @@ CPP_SRCS += \
OBJS += \
./src/AISMessages.o \
./src/ChannelManager.o \
./src/CommandProcessor.o \
./src/DataTerminal.o \
./src/DebugPrinter.o \
./src/EEPROM.o \
@ -65,6 +67,7 @@ C_DEPS += \
CPP_DEPS += \
./src/AISMessages.d \
./src/ChannelManager.d \
./src/CommandProcessor.d \
./src/DataTerminal.d \
./src/DebugPrinter.d \
./src/EEPROM.d \

View File

@ -5,6 +5,7 @@
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../system/src/stm32f3-stdperiph/stm32f30x_exti.c \
../system/src/stm32f3-stdperiph/stm32f30x_flash.c \
../system/src/stm32f3-stdperiph/stm32f30x_gpio.c \
../system/src/stm32f3-stdperiph/stm32f30x_i2c.c \
../system/src/stm32f3-stdperiph/stm32f30x_iwdg.c \
@ -17,6 +18,7 @@ C_SRCS += \
OBJS += \
./system/src/stm32f3-stdperiph/stm32f30x_exti.o \
./system/src/stm32f3-stdperiph/stm32f30x_flash.o \
./system/src/stm32f3-stdperiph/stm32f30x_gpio.o \
./system/src/stm32f3-stdperiph/stm32f30x_i2c.o \
./system/src/stm32f3-stdperiph/stm32f30x_iwdg.o \
@ -29,6 +31,7 @@ OBJS += \
C_DEPS += \
./system/src/stm32f3-stdperiph/stm32f30x_exti.d \
./system/src/stm32f3-stdperiph/stm32f30x_flash.d \
./system/src/stm32f3-stdperiph/stm32f30x_gpio.d \
./system/src/stm32f3-stdperiph/stm32f30x_i2c.d \
./system/src/stm32f3-stdperiph/stm32f30x_iwdg.d \

View File

@ -0,0 +1,268 @@
/*
* CommandProcessor.cpp
*
* Created on: Jun 24, 2016
* Author: peter
*/
#include "CommandProcessor.hpp"
#include <cstring>
#include "EEPROM.hpp"
#include <cstdio>
#include "globals.h"
#include "stm32f30x.h"
CommandProcessor &CommandProcessor::instance()
{
static CommandProcessor __instance;
return __instance;
}
CommandProcessor::CommandProcessor()
{
}
void CommandProcessor::init()
{
EventQueue::instance().addObserver(this, REQUEST_EVENT|RESET_EVENT);
}
void CommandProcessor::processEvent(const Event &e)
{
if ( e.type == RESET_EVENT ) {
NVIC_SystemReset ();
return;
}
switch(e.request.operation) {
case OP_GET:
if ( strcmp(e.request.field, "mmsi") == 0 )
returnMMSI();
else if ( strcmp(e.request.field, "name") == 0 )
returnName();
else if ( strcmp(e.request.field, "callsign") == 0 )
returnCallSign();
else if ( strcmp(e.request.field, "beam") == 0 )
returnBeam();
else if ( strcmp(e.request.field, "length") == 0 )
returnLength();
else if ( strcmp(e.request.field, "mode") == 0 )
returnMode();
else if ( strcmp(e.request.field, "vesseldata") == 0 )
returnVesselData();
else if ( strcmp(e.request.field, "version") == 0 )
returnVersion();
else if ( strcmp(e.request.field, "status") == 0 )
returnStatus();
else
sendError("Unknown field");
break;
case OP_SET:
if ( strcmp(e.request.field, "mmsi") == 0 )
setMMSI(atoi(e.request.value));
else if ( strcmp(e.request.field, "name") == 0 )
setName(e.request.value);
else if ( strcmp(e.request.field, "callsign") == 0 )
setCallSign(e.request.value);
else if ( strcmp(e.request.field, "beam") == 0 )
setBeam(atoi(e.request.value));
else if ( strcmp(e.request.field, "length") == 0 )
setLength(atoi(e.request.value));
else if ( strcmp(e.request.field, "mode") == 0 )
setMode(e.request.value);
else if ( strcmp(e.request.field, "vesseldata") == 0 )
setVesselData(e.request.value);
else
sendError("Unknown field");
break;
}
}
void CommandProcessor::sendError(const char *err)
{
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = false;
strcpy(reply->response.data, err);
EventQueue::instance().push(reply);
}
void CommandProcessor::sendEmptyReply(bool success)
{
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = success;
reply->response.data[0] = 0;
EventQueue::instance().push(reply);
}
void CommandProcessor::returnVersion()
{
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = true;
strcpy(reply->response.data, REVISION);
EventQueue::instance().push(reply);
}
void CommandProcessor::returnMMSI()
{
StationData data;
EEPROM::instance().readStationData(data);
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = true;
sprintf(reply->response.data, "%lu", data.mmsi);
EventQueue::instance().push(reply);
}
void CommandProcessor::returnCallSign()
{
StationData data;
EEPROM::instance().readStationData(data);
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = true;
sprintf(reply->response.data, "%s", data.callsign);
EventQueue::instance().push(reply);
}
void CommandProcessor::returnName()
{
StationData data;
EEPROM::instance().readStationData(data);
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = true;
sprintf(reply->response.data, "%s", data.name);
EventQueue::instance().push(reply);
}
void CommandProcessor::returnBeam()
{
StationData data;
EEPROM::instance().readStationData(data);
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = true;
sprintf(reply->response.data, "%d", data.beam);
EventQueue::instance().push(reply);
}
void CommandProcessor::returnLength()
{
StationData data;
EEPROM::instance().readStationData(data);
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = true;
sprintf(reply->response.data, "%d", data.len);
EventQueue::instance().push(reply);
}
void CommandProcessor::returnMode()
{
}
void CommandProcessor::returnVesselData()
{
StationData data;
EEPROM::instance().readStationData(data);
Event *reply = EventPool::instance().newEvent(RESPONSE_EVENT);
reply->response.success = true;
sprintf(reply->response.data, "%lu,%s,%s,%d,%d", data.mmsi, data.name, data.callsign, data.beam, data.len);
EventQueue::instance().push(reply);
}
void CommandProcessor::returnStatus()
{
}
void CommandProcessor::setMMSI(uint32_t mmsi)
{
StationData data;
EEPROM::instance().readStationData(data);
data.mmsi = mmsi;
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
void CommandProcessor::setName(const char* name)
{
StationData data;
EEPROM::instance().readStationData(data);
strcpy(data.name, name);
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
void CommandProcessor::setCallSign(const char *callsign)
{
StationData data;
EEPROM::instance().readStationData(data);
strcpy(data.callsign, callsign);
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
void CommandProcessor::setBeam(uint8_t beam)
{
StationData data;
EEPROM::instance().readStationData(data);
data.beam = beam;
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
void CommandProcessor::setLength(uint8_t len)
{
StationData data;
EEPROM::instance().readStationData(data);
data.len = len;
EEPROM::instance().writeStationData(data);
sendEmptyReply(true);
}
void CommandProcessor::setVesselData(const char *data)
{
sendEmptyReply(true);
}
void CommandProcessor::setMode(const char *mode)
{
if (strcmp (mode, "dfu") == 0)
{
FLASH_Unlock ();
FLASH_Status status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
if ( status != FLASH_COMPLETE ) {
sendError("Unable to unlock flash");
return;
}
FLASH_ErasePage (METADATA_ADDRESS);
status = FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
if ( status != FLASH_COMPLETE ) {
sendError("Unable to erase metadata page");
return;
}
FLASH_Lock ();
FLASH_WaitForLastOperation (FLASH_ER_PRG_TIMEOUT);
if ( status != FLASH_COMPLETE ) {
sendError("Unable to lock flash");
return;
}
//sendEmptyReply (true);
Event *e = EventPool::instance().newEvent(RESET_EVENT);
EventQueue::instance().push(e);
}
else
sendError("Unrecognized mode");
}

View File

@ -0,0 +1,46 @@
/*
* CommandProcessor.hpp
*
* Created on: Jun 24, 2016
* Author: peter
*/
#ifndef COMMANDPROCESSOR_HPP_
#define COMMANDPROCESSOR_HPP_
#include "EventQueue.hpp"
class CommandProcessor : public EventConsumer
{
public:
static CommandProcessor &instance();
void init();
void processEvent(const Event &);
private:
CommandProcessor();
void returnMMSI();
void returnName();
void returnCallSign();
void returnBeam();
void returnLength();
void returnMode();
void returnVesselData();
void returnStatus();
void returnVersion();
void setMMSI(uint32_t mmsi);
void setName(const char* name);
void setCallSign(const char *callsign);
void setBeam(uint8_t beam);
void setLength(uint8_t len);
void setVesselData(const char *data);
void setMode(const char *mode);
void sendError(const char* err);
void sendEmptyReply(bool success);
};
#endif /* COMMANDPROCESSOR_HPP_ */

View File

@ -86,7 +86,7 @@ void DataTerminal::processEvent(const Event &e)
void DataTerminal::processCharacter(char c)
{
if ( c == 13 ) {
if ( c == '\n' ) {
mCmdBuffer[mCmdBuffPos] = 0;
mCmdBuffPos = 0;
processCommand();
@ -104,22 +104,26 @@ void DataTerminal::processCommand()
string s(mCmdBuffer);
Utils::trim(s);
Utils::tokenize(s, ' ', mCmdTokens);
printf2("Got command: %s\r\n", s.c_str());
if ( mCmdTokens[0] == "set" && mCmdTokens.size() >= 3 ) {
// TODO: Extract field and value and queue a command event
if ( mCmdTokens[0] == "set" && mCmdTokens.size() >= 2 ) {
Event *e = EventPool::instance().newEvent(REQUEST_EVENT);
e->request.operation = OP_SET;
strncpy(e->request.field, mCmdTokens[1].c_str(), sizeof e->request.field);
if ( mCmdTokens.size() > 2 )
strncpy(e->request.value, mCmdTokens[2].c_str(), sizeof e->request.value);
else
e->request.value[0] = 0;
EventQueue::instance().push(e);
}
else if ( mCmdTokens[0] == "get" && mCmdTokens.size() >= 2 ) {
// TODO: Extract field
Event *e = EventPool::instance().newEvent(REQUEST_EVENT);
e->request.operation = OP_GET;
strncpy(e->request.field, mCmdTokens[1].c_str(), sizeof e->request.field);
EventQueue::instance().push(e);
}
}
void write_char(USART_TypeDef* USARTx, char c)

View File

@ -15,18 +15,17 @@
*/
typedef enum {
UNKNOWN_EVENT = 0, // Invalid, not a real event id
GPS_NMEA_SENTENCE = 1, // A NMEA sentence was received from the GPS.
GPS_FIX_EVENT = 2, // The GPS obtained a fix.
CLOCK_EVENT = 4, // One pulse per second as triggered by GPS. This is a convenient 1 Hz "wall" clock, as it carries UTC.
AIS_PACKET_EVENT = 8, // A packet was just decoded (not necessarily valid, must still be CRC checked, etc)
INTERROGATION_EVENT = 16,
DEBUG_EVENT = 32,
KEYPRESS_EVENT = 64,
REQUEST_EVENT = 128,
RESPONSE_EVENT = 256
//GPS_ERROR_EVENT = 64, // A GPS failure
//TRX_ERROR_EVENT = 128 // A radio failure
UNKNOWN_EVENT = 0x0000, // Invalid, not a real event id
GPS_NMEA_SENTENCE = 0x0001, // A NMEA sentence was received from the GPS.
GPS_FIX_EVENT = 0x0002, // The GPS obtained a fix.
CLOCK_EVENT = 0x0004, // One pulse per second as triggered by GPS. This is a convenient 1 Hz "wall" clock, as it carries UTC.
AIS_PACKET_EVENT = 0x0008, // A packet was just decoded (not necessarily valid, must still be CRC checked, etc)
INTERROGATION_EVENT = 0x0010, // Received AIS message 15
DEBUG_EVENT = 0x0020,
KEYPRESS_EVENT = 0x0040,
REQUEST_EVENT = 0x0080,
RESPONSE_EVENT = 0x00100,
RESET_EVENT = 0x00200
}
EventType;

View File

@ -12,7 +12,7 @@
#include "TXPowerSettings.h"
#define MODEL "SEAWAIS_02"
#define REVISION "0.6.0"
#define REVISION "0.6.2"
@ -89,4 +89,7 @@
*/
#define MULTIPLEXED_OUTPUT 1
#define METADATA_ADDRESS 0x08003800
#define APPLICATION_ADDRESS 0x08004000
#endif /* GLOBALS_H_ */

View File

@ -22,6 +22,7 @@
#include "TXScheduler.hpp"
#include "DebugPrinter.hpp"
#include "EEPROM.hpp"
#include "CommandProcessor.hpp"
// ----------------------------------------------------------------------------
//
@ -61,12 +62,14 @@ main(int argc, char* argv[])
#ifdef DEBUG
// Disable buffered memory writes to debug imprecise bus faults
SCnSCB->ACTLR |= SCnSCB_ACTLR_DISDEFWBUF_Msk;
trace_printf("ACTLR: %.8x\n", SCnSCB->ACTLR);
//trace_printf("ACTLR: %.8x\n", SCnSCB->ACTLR);
#endif
printf2("Software revision: %s\r\n", REVISION);
EEPROM::instance().init();
/*
* TODO: Move this out of here
struct StationData __d;
__d.mmsi = 987654321;
__d.len = 0;
@ -79,7 +82,7 @@ main(int argc, char* argv[])
EventQueue::instance().init();
EventPool::instance().init();
TXPacketPool::instance().init();
CommandProcessor::instance().init();
LEDManager::instance().clear();
TXScheduler txScheduler;
@ -124,9 +127,6 @@ main(int argc, char* argv[])
EventQueue::instance().dispatch();
IWDG_ReloadCounter();
}
// If execution jumps here, something is seriously fucked up!!!
assert(false);
}

View File

@ -70,7 +70,7 @@ void DataTerminal::init()
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_Init(&NVIC_InitStruct);
//write("[SYSTEM][Waiting for transfer]\r\n");
write("[DFU]Waiting for transfer\r\n");
}
DataTerminal::DataTerminal()
@ -208,7 +208,7 @@ void DataTerminal::unlockFlash()
trace_printf("Mock flash unlock\n");
#else
FLASH_Unlock();
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
#endif
}
@ -218,7 +218,7 @@ void DataTerminal::lockFlash()
trace_printf("Mock flash lock\n");
#else
FLASH_Lock();
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
#endif
}
@ -230,11 +230,11 @@ void DataTerminal::flushPage()
#else
trace_printf("Writing Flash page at %.8x\n", mWriteAddress);
FLASH_ErasePage(mWriteAddress);
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
char *p = mCurrPage;
for ( size_t i = 0; i < FLASH_PAGE_SIZE; i += 4, p += 4) {
FLASH_ProgramWord(mWriteAddress + i, *(uint32_t*)p);
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
}
trace_printf("Wrote Flash page at %.8x\n", mWriteAddress);
@ -249,11 +249,11 @@ void DataTerminal::flushMetadata()
trace_printf("Mock write for metadata page at %.8x\n", METADATA_ADDRESS);
#else
FLASH_ErasePage(METADATA_ADDRESS);
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
char *p = (char*)&mMetadata;
for ( size_t i = 0; i < sizeof mMetadata; i += 4, p += 4 ) {
FLASH_ProgramWord(METADATA_ADDRESS + i, *(uint32_t*)p);
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
}
#endif
}

View File

@ -50,12 +50,11 @@ Timer __timer;
void erase()
{
FLASH_Unlock();
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
FLASH_ErasePage(METADATA_ADDRESS);
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
FLASH_Lock();
FLASH_WaitForLastOperation(0);
FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
}
int
@ -74,13 +73,15 @@ main(int argc, char* argv[])
enterUARTMode();
}
#if 0
else {
if ( !verifyApplicationChecksum(*metadata) ) {
trace_printf("The software is corrupt. Entering UART mode\n");
enterUARTMode();
}
}
#endif
trace_printf("Found software rev. %s\n", metadata->revision);
#endif