1
0
Fork 0
mirror of https://github.com/EdgeTX/edgetx.git synced 2025-07-26 01:35:16 +03:00

Added support for flashing AVR multi on horus targets (#6888)

* Added support for flashing AVR multi on horus targets

taranis soft serial

Added support for flashing AVR multi on horus targets

taranis soft serial

* Added support for multi V2 signature (hex code)

* Check multi signature before flashing

* small clean-up

* Cosmetics

* Fix v2 signature check

* Cosmetics
This commit is contained in:
Raphael Coeffic 2019-10-16 15:29:10 +02:00 committed by 3djc
parent f1d8083064
commit aaafe445db
26 changed files with 544 additions and 88 deletions

View file

@ -220,6 +220,7 @@ void onSdManagerMenu(const char * result)
FrskyDeviceFirmwareUpdate device(SPORT_MODULE);
device.flashFirmware(lfn);
}
#if defined(MULTIMODULE)
#if defined(INTERNAL_MODULE_MULTI)
else if (result == STR_FLASH_INTERNAL_MULTI) {
getSelectionFullPath(lfn);
@ -230,6 +231,7 @@ void onSdManagerMenu(const char * result)
getSelectionFullPath(lfn);
multiFlashFirmware(EXTERNAL_MODULE, lfn);
}
#endif
#if defined(BLUETOOTH)
else if (result == STR_FLASH_BLUETOOTH_MODULE) {
getSelectionFullPath(lfn);

View file

@ -26,8 +26,6 @@
#define UPDATE_MULTI_EXT_BIN ".bin"
//#define DEBUG_EXT_MODULE_FLASH
class MultiFirmwareUpdateDriver
{
public:
@ -39,6 +37,7 @@ class MultiFirmwareUpdateDriver
virtual bool getByte(uint8_t& byte) const = 0;
virtual void sendByte(uint8_t byte) const = 0;
virtual void clear() const = 0;
virtual void deinit() const {}
private:
bool getRxByte(uint8_t& byte) const;
@ -47,6 +46,7 @@ class MultiFirmwareUpdateDriver
const char * getDeviceSignature(uint8_t* signature) const;
const char * loadAddress(uint32_t offset) const;
const char * progPage(uint8_t* buffer, uint16_t size) const;
void leaveProgMode() const;
};
#if defined(INTERNAL_MODULE_MULTI)
@ -77,16 +77,21 @@ class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver
{
intmoduleFifo.clear();
}
void deinit() const override
{
clear();
}
};
static const MultiInternalUpdateDriver multiInternalUpdateDriver;
#endif
class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
class MultiExternalSoftSerialUpdateDriver: public MultiFirmwareUpdateDriver
{
public:
MultiExternalUpdateDriver() = default;
MultiExternalSoftSerialUpdateDriver() = default;
protected:
void init() const override
@ -102,7 +107,7 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
#endif
EXTERNAL_MODULE_ON();
telemetryPortInit(57600, TELEMETRY_SERIAL_DEFAULT);
telemetryPortInvertedInit(57600);
}
bool getByte(uint8_t& byte) const override
@ -119,9 +124,15 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
{
telemetryClearFifo();
}
void deinit() const override
{
telemetryPortInvertedInit(0);
clear();
}
};
static const MultiExternalUpdateDriver multiExternalUpdateDriver;
static const MultiExternalSoftSerialUpdateDriver multiExternalSoftSerialUpdateDriver;
bool MultiFirmwareUpdateDriver::getRxByte(uint8_t& byte) const
{
@ -150,10 +161,10 @@ bool MultiFirmwareUpdateDriver::checkRxByte(uint8_t byte) const
const char * MultiFirmwareUpdateDriver::waitForInitialSync() const
{
clear();
uint8_t byte;
int retries = 1000;
clear();
do {
// Send sync request
sendByte(STK_GET_SYNC);
@ -214,16 +225,14 @@ const char * MultiFirmwareUpdateDriver::loadAddress(uint32_t offset) const
const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size) const
{
sendByte(STK_PROG_PAGE);
// page size 256
sendByte(1);
sendByte(0);
// page size
sendByte(size >> 8);
sendByte(size & 0xFF);
// flash/eeprom flag
sendByte(0);
// #if defined(DEBUG_EXT_MODULE_FLASH)
// TRACE("writing at 0x%X", writeOffset << 1);
// #endif
for (uint16_t i=0; i < size; i++) {
sendByte(buffer[i]);
}
@ -245,6 +254,16 @@ const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size)
return nullptr;
}
void MultiFirmwareUpdateDriver::leaveProgMode() const
{
sendByte(STK_LEAVE_PROGMODE);
sendByte(CRC_EOP);
// eat last sync byte
checkRxByte(STK_INSYNC);
deinit();
}
const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* label) const
{
const char* result = nullptr;
@ -255,24 +274,39 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab
RTOS_WAIT_MS(500);
result = waitForInitialSync();
if (result != nullptr)
if (result) {
leaveProgMode();
return result;
}
unsigned char signature[4]; // 3 bytes signature + STK_OK
result = getDeviceSignature(signature);
if (result != nullptr)
if (result) {
leaveProgMode();
return result;
}
uint8_t buffer[256]; // page size = 256
uint32_t writeOffset = 0x1000; // start offset (word address)
uint8_t buffer[256];
uint16_t pageSize = 128;
uint32_t writeOffset = 0;
if (signature[0] != 0x1E) {
leaveProgMode();
return "Wrong signature";
}
if (signature[1] == 0x55 && signature[2] == 0xAA) {
pageSize = 256;
writeOffset = 0x1000; // start offset (word address)
}
while (!f_eof(file)) {
drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize);
UINT count=0;
memclear(buffer, 256);
if (f_read(file, buffer, 256, &count) != FR_OK) {
memclear(buffer, pageSize);
if (f_read(file, buffer, pageSize, &count) != FR_OK) {
result = "Error reading file";
break;
}
@ -283,28 +317,23 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab
clear();
result = loadAddress(writeOffset);
if (result != nullptr) {
if (result) {
break;
}
result = progPage(buffer, 256);
if (result != nullptr) {
result = progPage(buffer, pageSize);
if (result) {
break;
}
writeOffset += 128; // page / 2
writeOffset += pageSize / 2;
}
if (f_eof(file)) {
drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize);
}
sendByte(STK_LEAVE_PROGMODE);
sendByte(CRC_EOP);
// eat last sync byte
checkRxByte(STK_INSYNC);
leaveProgMode();
return result;
}
@ -316,19 +345,9 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab
#define MULTI_SIGN_TELEM_INVERSION_OFFSET 13
#define MULTI_SIGN_VERSION_OFFSET 15
const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * filename)
const char * MultiFirmwareInformation::readV1Signature(const char * buffer)
{
FIL file;
f_open(&file, filename, FA_READ);
char buffer[MULTI_SIGN_SIZE];
UINT count;
f_lseek(&file, f_size(&file) - MULTI_SIGN_SIZE);
if (f_read(&file, buffer, MULTI_SIGN_SIZE, &count) != FR_OK || count != MULTI_SIGN_SIZE) {
return "Error reading file";
}
if(!memcmp(buffer, "multi-stm", 9))
if (!memcmp(buffer, "multi-stm", 9))
boardType = FIRMWARE_MULTI_STM;
else if (!memcmp(buffer, "multi-avr", 9))
boardType = FIRMWARE_MULTI_AVR;
@ -348,9 +367,9 @@ const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char *
bootloaderCheck = false;
if(buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 't')
telemetryType = FIRMWARE_MULTI_TELEM_MULTI;
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_STATUS;
else if (buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 's')
telemetryType = FIRMWARE_MULTI_TELEM_STATUS;
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY;
else
telemetryType = FIRMWARE_MULTI_TELEM_NONE;
@ -362,23 +381,115 @@ const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char *
return nullptr;
}
const char * MultiFirmwareInformation::readV2Signature(const char * buffer)
{
// new format
uint32_t options = 0;
const char * beg = buffer + 7;
const char * cursor = beg;
while (cursor - beg < 8) {
options <<= 4;
if (*cursor >= '0' && *cursor <= '9')
options |= *cursor - '0';
else if (*cursor >= 'a' && *cursor <= 'f')
options |= *cursor - 'a' + 10;
else if (*cursor >= 'A' && *cursor <= 'F')
options |= *cursor - 'A' + 10;
else
break; // should be '-'
cursor++;
}
if (cursor - beg < 8)
return "Invalid signature";
const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
boardType = options & 0x3;
optibootSupport = options & 0x80 ? true : false;
telemetryInversion = options & 0x200 ? true : false;
bootloaderCheck = options & 0x100 ? true : false;
telemetryType = FIRMWARE_MULTI_TELEM_NONE;
if (options & 0x400)
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_STATUS;
if (options & 0x800)
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY;
return nullptr;
}
const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * filename)
{
FIL file;
const char * result = nullptr;
if (f_open(&file, filename, FA_READ) != FR_OK)
return "Error opening file";
const char * ext = getFileExtension(filename);
if (ext && strcasecmp(ext, UPDATE_MULTI_EXT_BIN)) {
return "Wrong file extension";
const char * err = readMultiFirmwareInformation(&file);
f_close(&file);
return err;
}
const char * MultiFirmwareInformation::readMultiFirmwareInformation(FIL * file)
{
char buffer[MULTI_SIGN_SIZE];
UINT count;
if (f_size(file) < MULTI_SIGN_SIZE)
return "File too small";
f_lseek(file, f_size(file) - MULTI_SIGN_SIZE);
if (f_read(file, buffer, MULTI_SIGN_SIZE, &count) != FR_OK || count != MULTI_SIGN_SIZE) {
return "Error reading file";
}
if (!memcmp(buffer, "multi-x", 7)) {
return readV2Signature(buffer);
}
return readV1Signature(buffer);
}
bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
{
FIL file;
if (f_open(&file, filename, FA_READ) != FR_OK) {
return "Error opening file";
POPUP_WARNING("Not a valid file");
return false;
}
MultiFirmwareInformation firmwareFile;
if (firmwareFile.readMultiFirmwareInformation(&file)) {
f_close(&file);
POPUP_WARNING("Not a valid file");
return false;
}
f_lseek(&file, 0);
if (moduleIdx == EXTERNAL_MODULE) {
if (!firmwareFile.isMultiExternalFirmware()) {
f_close(&file);
POPUP_WARNING(STR_NEEDS_FILE);
SET_WARNING_INFO(STR_EXT_MULTI_SPEC, strlen(STR_EXT_MULTI_SPEC), 0);
return false;
}
}
else {
if (!firmwareFile.isMultiInternalFirmware()) {
f_close(&file);
POPUP_WARNING(STR_NEEDS_FILE);
SET_WARNING_INFO(STR_INT_MULTI_SPEC, strlen(STR_INT_MULTI_SPEC), 0);
return false;
}
}
const MultiFirmwareUpdateDriver* driver = &multiExternalSoftSerialUpdateDriver;
#if defined(INTERNAL_MODULE_MULTI)
if (moduleIdx == INTERNAL_MODULE)
driver = &multiInternalUpdateDriver;
#endif
pausePulses();
#if defined(INTERNAL_MODULE_MULTI)
@ -397,14 +508,7 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
watchdogSuspend(2000);
RTOS_WAIT_MS(2000);
// TODO: real update here
const MultiFirmwareUpdateDriver* driver = &multiExternalUpdateDriver;
#if defined(INTERNAL_MODULE_MULTI)
if (moduleIdx == INTERNAL_MODULE)
driver = &multiInternalUpdateDriver;
#endif
result = driver->flashFirmware(&file, getBasename(filename));
const char * result = driver->flashFirmware(&file, getBasename(filename));
f_close(&file);
AUDIO_PLAY(AU_SPECIAL_SOUND_BEEP1 );
@ -425,7 +529,9 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
/* wait 2s off */
watchdogSuspend(2000);
RTOS_WAIT_MS(2000);
telemetryClearFifo();
// reset telemetry protocol
telemetryInit(255);
#if defined(INTERNAL_MODULE_MULTI)
if (intPwr) {
@ -439,9 +545,8 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
setupPulsesExternalModule();
}
//state = SPORT_IDLE;
resumePulses();
return result;
return result == nullptr;
}
#endif

View file

@ -21,6 +21,8 @@
#ifndef OPENTX_MULTI_FIRMWARE_H
#define OPENTX_MULTI_FIRMWARE_H
#include "ff.h"
/* Signature format is multi-[board type]-[bootloader support][check for bootloader][multi telemetry type][telemetry inversion][debug]-[firmware version]
Where:
[board type] is avr, stm, or orx
@ -36,15 +38,15 @@
class MultiFirmwareInformation {
public:
enum MultiFirmwareBoardType {
FIRMWARE_MULTI_AVR = 0,
FIRMWARE_MULTI_STM,
FIRMWARE_MULTI_AVR,
FIRMWARE_MULTI_ORX,
};
enum MultiFirmwareTelemetryType {
FIRMWARE_MULTI_TELEM_MULTI,
FIRMWARE_MULTI_TELEM_STATUS,
FIRMWARE_MULTI_TELEM_NONE,
FIRMWARE_MULTI_TELEM_NONE = 0,
FIRMWARE_MULTI_TELEM_MULTI_STATUS, // erSkyTX
FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY, // OpenTX
};
bool isMultiStmFirmware() const
@ -69,15 +71,16 @@ class MultiFirmwareInformation {
bool isMultiInternalFirmware() const
{
return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == false && optibootSupport == true && telemetryType == FIRMWARE_MULTI_TELEM_STATUS);
return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == false && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY);
}
bool isMultiExternalFirmware() const
{
return (telemetryInversion == false && optibootSupport == true && telemetryType == FIRMWARE_MULTI_TELEM_STATUS);
return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == true && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY);
}
const char * readMultiFirmwareInformation(const char * filename);
const char * readMultiFirmwareInformation(FIL * file);
private:
uint8_t boardType;
@ -89,8 +92,11 @@ class MultiFirmwareInformation {
uint8_t firmwareVersionMinor;
uint8_t firmwareVersionRevision;
uint8_t firmwareVersionSubRevision;
const char * readV1Signature(const char * buffer);
const char * readV2Signature(const char * buffer);
};
const char* multiFlashFirmware(uint8_t module, const char * filename);
bool multiFlashFirmware(uint8_t module, const char * filename);
#endif //OPENTX_MULTI_FIRMWARE_H

View file

@ -83,5 +83,8 @@ void check_intmodule_heartbeat()
extern "C" void INTMODULE_HEARTBEAT_EXTI_IRQHandler()
{
check_intmodule_heartbeat();
#if defined(TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT)
check_telemetry_exti();
#endif
}
#endif

View file

@ -133,6 +133,10 @@ extern "C" void ROTARY_ENCODER_EXTI_IRQHandler1(void)
#if !defined(BOOT) && defined(INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER)
check_intmodule_heartbeat();
#endif
#if !defined(BOOT) && defined(TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER)
check_telemetry_exti();
#endif
}
#if defined(ROTARY_ENCODER_EXTI_IRQn2)

View file

@ -120,6 +120,7 @@ void boardInit()
HAPTIC_RCC_APB2Periph |
INTMODULE_RCC_APB2Periph |
EXTMODULE_RCC_APB2Periph |
TELEMETRY_RCC_APB2Periph |
BT_RCC_APB2Periph |
BACKLIGHT_RCC_APB2Periph,
ENABLE);

View file

@ -568,6 +568,9 @@ bool telemetryGetByte(uint8_t * byte);
void telemetryClearFifo();
extern uint32_t telemetryErrors;
// soft-serial
void telemetryPortInvertedInit(uint32_t baudrate);
// Sport update driver
#if defined(PCBX10) && !defined(RADIO_T16)
void sportUpdatePowerOn();

View file

@ -365,6 +365,7 @@
// Telemetry
#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1)
#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2
#define TELEMETRY_RCC_APB2Periph RCC_APB2Periph_TIM10
#define TELEMETRY_DIR_GPIO GPIOD
#define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_4 // PD.04
#define TELEMETRY_GPIO GPIOD
@ -374,6 +375,15 @@
#define TELEMETRY_GPIO_PinSource_RX GPIO_PinSource6
#define TELEMETRY_GPIO_AF GPIO_AF_USART2
#define TELEMETRY_USART USART2
#define TELEMETRY_EXTI_PortSource EXTI_PortSourceGPIOD
#define TELEMETRY_EXTI_PinSource EXTI_PinSource6
#define TELEMETRY_EXTI_LINE EXTI_Line6
#define TELEMETRY_EXTI_IRQn EXTI9_5_IRQn
#define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler
#define TELEMETRY_EXTI_TRIGGER EXTI_Trigger_Rising
#define TELEMETRY_TIMER TIM11
#define TELEMETRY_TIMER_IRQn TIM1_TRG_COM_TIM11_IRQn
#define TELEMETRY_TIMER_IRQHandler TIM1_TRG_COM_TIM11_IRQHandler
#if defined(PCBX12S)
#define TELEMETRY_DMA_Stream_RX DMA1_Stream5
#define TELEMETRY_DMA_Channel_RX DMA_Channel_4

View file

@ -28,6 +28,17 @@ DMAFifo<TELEMETRY_FIFO_SIZE> telemetryDMAFifo __DMA (TELEMETRY_DMA_Stream_RX);
uint8_t telemetryFifoMode;
#endif
static void telemetryInitDirPin()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN;
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
GPIO_ResetBits(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
}
void telemetryPortInit(uint32_t baudrate, uint8_t mode)
{
if (baudrate == 0) {
@ -55,11 +66,7 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
GPIO_ResetBits(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
telemetryInitDirPin();
USART_InitStructure.USART_BaudRate = baudrate;
if (mode & TELEMETRY_SERIAL_8E2) {
@ -126,6 +133,95 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
#endif
}
// soft serial vars
static uint8_t rxBitCount;
static uint8_t rxByte;
void telemetryPortInvertedInit(uint32_t baudrate)
{
if (baudrate == 0) {
NVIC_DisableIRQ(TELEMETRY_EXTI_IRQn);
NVIC_DisableIRQ(TELEMETRY_TIMER_IRQn);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER;
EXTI_InitStructure.EXTI_LineCmd = DISABLE;
EXTI_Init(&EXTI_InitStructure);
return;
}
rxBitCount = 0;
// configure bit sample timer
RCC->APB2ENR |= RCC_APB2ENR_TIM11EN;
TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS
TELEMETRY_TIMER->CCER = 0;
TELEMETRY_TIMER->CCMR1 = 0;
TELEMETRY_TIMER->CR1 = TIM_CR1_CEN;
TELEMETRY_TIMER->DIER = TIM_DIER_UIE;
NVIC_SetPriority(TELEMETRY_TIMER_IRQn, 0);
NVIC_EnableIRQ(TELEMETRY_TIMER_IRQn);
// init TELEMETRY_RX_GPIO_PIN
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Pin = TELEMETRY_RX_GPIO_PIN;
GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure);
telemetryInitDirPin();
// Connect EXTI line to TELEMETRY RX pin
SYSCFG_EXTILineConfig(TELEMETRY_EXTI_PortSource, TELEMETRY_EXTI_PinSource);
// Configure EXTI for raising edge (start bit)
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_SetPriority(TELEMETRY_EXTI_IRQn, 0);
NVIC_EnableIRQ(TELEMETRY_EXTI_IRQn);
}
void telemetryPortInvertedRxBit()
{
if (rxBitCount < 8) {
if (rxBitCount == 0) {
TELEMETRY_TIMER->ARR = 34;
rxByte = 0;
}
else {
rxByte >>= 1;
}
if (GPIO_ReadInputDataBit(TELEMETRY_GPIO, TELEMETRY_RX_GPIO_PIN) == Bit_RESET)
rxByte |= 0x80;
++rxBitCount;
}
else if (rxBitCount == 8) {
telemetryNoDMAFifo.push(rxByte);
rxBitCount = 0;
// disable timer
TELEMETRY_TIMER->CR1 &= ~TIM_CR1_CEN;
// re-enable start bit interrupt
EXTI->IMR |= EXTI_IMR_MR6;
}
}
void telemetryPortSetDirectionOutput()
{
TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN; // output enable
@ -253,6 +349,29 @@ extern "C" void TELEMETRY_USART_IRQHandler(void)
}
}
extern "C" void TELEMETRY_EXTI_IRQHandler(void)
{
if (EXTI_GetITStatus(TELEMETRY_EXTI_LINE) != RESET) {
if (rxBitCount == 0) {
TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps
TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN;
// disable start bit interrupt
EXTI->IMR &= ~EXTI_IMR_MR6;
}
EXTI_ClearITPendingBit(TELEMETRY_EXTI_LINE);
}
}
extern "C" void TELEMETRY_TIMER_IRQHandler()
{
TELEMETRY_TIMER->SR &= ~TIM_SR_UIF;
telemetryPortInvertedRxBit();
}
// TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp
bool telemetryGetByte(uint8_t * byte)
{

View file

@ -192,6 +192,8 @@ void check_intmodule_heartbeat();
#define check_intmodule_heartbeat()
#endif
void check_telemetry_exti();
// SBUS
int sbusGetByte(uint8_t * byte);
@ -680,6 +682,9 @@ bool telemetryGetByte(uint8_t * byte);
void telemetryClearFifo();
extern uint32_t telemetryErrors;
// soft-serial
void telemetryPortInvertedInit(uint32_t baudrate);
// PCBREV driver
#if defined(PCBX7)
#define IS_PCBREV_40() (GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN) == Bit_SET)

View file

@ -1284,6 +1284,23 @@
#define TELEMETRY_DMA_TX_FLAG_TC DMA_IT_TCIF6
#define TELEMETRY_USART_IRQHandler USART2_IRQHandler
#define TELEMETRY_USART_IRQn USART2_IRQn
#define TELEMETRY_EXTI_PortSource EXTI_PortSourceGPIOD
#define TELEMETRY_EXTI_PinSource EXTI_PinSource6
#define TELEMETRY_EXTI_LINE EXTI_Line6
#define TELEMETRY_EXTI_IRQn EXTI9_5_IRQn
#define TELEMETRY_EXTI_TRIGGER EXTI_Trigger_Rising
#if defined(RADIO_X7)
#define TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER
#elif defined(PCBXLITE) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019)
#define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler
#else
#define TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT
#endif
#define TELEMETRY_TIMER TIM11
#define TELEMETRY_TIMER_IRQn TIM1_TRG_COM_TIM11_IRQn
#define TELEMETRY_TIMER_IRQHandler TIM1_TRG_COM_TIM11_IRQHandler
// PCBREV
#if defined(PCBX7)

View file

@ -23,6 +23,17 @@
Fifo<uint8_t, TELEMETRY_FIFO_SIZE> telemetryFifo;
uint32_t telemetryErrors = 0;
static void telemetryInitDirPin()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN;
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
TELEMETRY_DIR_INPUT();
}
void telemetryPortInit(uint32_t baudrate, uint8_t mode)
{
if (baudrate == 0) {
@ -48,11 +59,7 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
TELEMETRY_DIR_INPUT();
telemetryInitDirPin();
USART_DeInit(TELEMETRY_USART);
USART_InitTypeDef USART_InitStructure;
@ -77,6 +84,110 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
}
// soft serial vars
static uint8_t rxBitCount;
static uint8_t rxByte;
//TODO:
// - only 57600 supported for now
// - handle other bitrates as well?
//
void telemetryPortInvertedInit(uint32_t baudrate)
{
if (baudrate == 0) {
//TODO:
// - handle conflict with HEARTBEAT disabled for trainer input...
// - probably need to stop trainer input/output and restore after this is closed
#if !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER) && !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT)
NVIC_DisableIRQ(TELEMETRY_EXTI_IRQn);
#endif
NVIC_DisableIRQ(TELEMETRY_TIMER_IRQn);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER;
EXTI_InitStructure.EXTI_LineCmd = DISABLE;
EXTI_Init(&EXTI_InitStructure);
return;
}
rxBitCount = 0;
// configure bit sample timer
RCC->APB2ENR |= RCC_APB2ENR_TIM11EN;
TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS
TELEMETRY_TIMER->CCER = 0;
TELEMETRY_TIMER->CCMR1 = 0;
TELEMETRY_TIMER->CR1 = TIM_CR1_CEN;
TELEMETRY_TIMER->DIER = TIM_DIER_UIE;
NVIC_SetPriority(TELEMETRY_TIMER_IRQn, 0);
NVIC_EnableIRQ(TELEMETRY_TIMER_IRQn);
// init TELEMETRY_RX_GPIO_PIN
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Pin = TELEMETRY_RX_GPIO_PIN;
GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure);
telemetryInitDirPin();
// Connect EXTI line to TELEMETRY RX pin
SYSCFG_EXTILineConfig(TELEMETRY_EXTI_PortSource, TELEMETRY_EXTI_PinSource);
// Configure EXTI for raising edge (start bit)
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
//TODO:
// - handle conflict with HEARTBEAT disabled for trainer input...
// - probably need to stop trainer input/output and restore after this is closed
#if !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER) && !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT)
NVIC_SetPriority(TELEMETRY_EXTI_IRQn, 0);
NVIC_EnableIRQ(TELEMETRY_EXTI_IRQn);
#endif
}
void telemetryPortInvertedRxBit()
{
if (rxBitCount < 8) {
if (rxBitCount == 0) {
TELEMETRY_TIMER->ARR = 34;
rxByte = 0;
}
else {
rxByte >>= 1;
}
if (GPIO_ReadInputDataBit(TELEMETRY_GPIO, TELEMETRY_RX_GPIO_PIN) == Bit_RESET)
rxByte |= 0x80;
++rxBitCount;
}
else if (rxBitCount == 8) {
telemetryFifo.push(rxByte);
rxBitCount = 0;
// disable timer
TELEMETRY_TIMER->CR1 &= ~TIM_CR1_CEN;
// re-enable start bit interrupt
EXTI->IMR |= EXTI_IMR_MR6;
}
}
void telemetryPortSetDirectionOutput()
{
TELEMETRY_DIR_OUTPUT();
@ -217,6 +328,36 @@ extern "C" void TELEMETRY_USART_IRQHandler(void)
}
}
void check_telemetry_exti()
{
if (EXTI_GetITStatus(TELEMETRY_EXTI_LINE) != RESET) {
if (rxBitCount == 0) {
TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps
TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN;
// disable start bit interrupt
EXTI->IMR &= ~EXTI_IMR_MR6;
}
EXTI_ClearITPendingBit(TELEMETRY_EXTI_LINE);
}
}
#if defined(TELEMETRY_EXTI_IRQHandler)
extern "C" void TELEMETRY_EXTI_IRQHandler(void)
{
check_telemetry_exti();
}
#endif
extern "C" void TELEMETRY_TIMER_IRQHandler()
{
TELEMETRY_TIMER->SR &= ~TIM_SR_UIF;
telemetryPortInvertedRxBit();
}
// TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp
bool telemetryGetByte(uint8_t * byte)
{

View file

@ -35,6 +35,7 @@ extern uint8_t currentTrainerMode;
void checkTrainerSignalWarning();
void checkTrainerSettings();
void forceResetTrainerSettings();
// Needs to be inlined to avoid slow function calls in ISR routines
inline void captureTrainerPulses(uint16_t capture)

View file

@ -677,6 +677,9 @@ const char STR_PROTOCOL_INVALID[] = TR_PROTOCOL_INVALID;
const char STR_MODULE_STATUS[] = TR_MODULE_STATUS;
const char STR_MODULE_SYNC[] = TR_MODULE_SYNC;
const char STR_MULTI_SERVOFREQ[] = TR_MULTI_SERVOFREQ;
const char STR_NEEDS_FILE[] = TR_NEEDS_FILE;
const char STR_EXT_MULTI_SPEC[] = TR_EXT_MULTI_SPEC;
const char STR_INT_MULTI_SPEC[] = TR_INT_MULTI_SPEC;
#endif
#if LCD_W < 212

View file

@ -537,6 +537,9 @@ extern const char STR_WAITING_FOR_TX[];
#define STR_UPDATE_LIST STR_DELAYDOWN
#endif
extern const char STR_NEEDS_FILE[];
extern const char STR_EXT_MULTI_SPEC[];
extern const char STR_INT_MULTI_SPEC[];
extern const char STR_CAT_NOT_EMPTY[];
extern const char STR_WARNING[];
extern const char STR_STORAGE_WARNING[];

View file

@ -714,6 +714,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spektální an. (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spektální an. (INT)"
#define TR_SDCARD_FULL "Plná SD karta"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Nekompatibilní"
#define TR_WARNING "KONTROLA"
#define TR_EEPROMWARN "EEPROM"

View file

@ -716,6 +716,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD-Karte voll"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Nicht kompatibel"
#define TR_WARNING "WARNUNG"
#define TR_EEPROMWARN "EEPROM"

View file

@ -715,6 +715,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD card full"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Incompatible"
#define TR_WARNING "WARNING"
#define TR_EEPROMWARN "EEPROM"

View file

@ -739,6 +739,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD Card Full"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Incompatible"
#define TR_WARNING "AVISO"
#define TR_EEPROMWARN "EEPROM"

View file

@ -733,6 +733,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD Card Full"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Incompatible"
#define TR_WARNING "WARNING"
#define TR_EEPROMWARN "FINSKA"

View file

@ -736,6 +736,9 @@
#define TR_SPECTRUM_ANALYSER_EXT TR("Spectre (EXT)", "Analyseur spectre (EXT)")
#define TR_SPECTRUM_ANALYSER_INT TR("Spectre (INT)", "Analyseur spectre (INT)")
#define TR_SDCARD_FULL "Carte SD pleine"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Incompatible"
#define TR_WARNING "ALERTE"
#define TR_EEPROMWARN "EEPROM"

View file

@ -734,6 +734,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD Card Piena"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Incompatibile"
#define TR_WARNING "AVVISO"
#define TR_EEPROMWARN "EEPROM"

View file

@ -721,6 +721,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD-Kaart vol"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Niet compatibel"
#define TR_WARNING "MELDING"
#define TR_EEPROMWARN "EEPROM"

View file

@ -734,6 +734,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "Karta Pełna "
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Niekompatybilne"
#define TR_WARNING "UWAGA"
#define TR_EEPROMWARN "EEPROM"

View file

@ -724,6 +724,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD Card Full"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Incompativel"
#define TR_WARNING "AVISO"
#define TR_EEPROMWARN "EEPROM"

View file

@ -733,6 +733,9 @@
#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)"
#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)"
#define TR_SDCARD_FULL "SD-kort Fullt"
#define TR_NEEDS_FILE "NEEDS FILE"
#define TR_EXT_MULTI_SPEC "opentx-inv"
#define TR_INT_MULTI_SPEC "stm-opentx-noinv"
#define TR_INCOMPATIBLE "Inkompatibel"
#define TR_WARNING "VARNING"
#define TR_EEPROMWARN "EEPROM"