mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-12 17:57:53 +00:00
Merge f13701b1204e97cd65e4de4f32c34c5fa7cb2c53 into dd3f8b4717c03dc2f86701191dc8b265d4706751
This commit is contained in:
commit
13fe91c432
@ -179,12 +179,26 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
packet[0] = 0x56;
|
||||
for(uint8_t ch=0; ch<14; ch++)
|
||||
{
|
||||
/*if((Model.limits[ch].flags & CH_FAILSAFE_EN))
|
||||
#ifdef AFHDS2A_FAILSAFE
|
||||
int8_t failsafe = AFHDS2AFailsafe[ch];
|
||||
//
|
||||
if(failsafe != -1)
|
||||
{
|
||||
packet[9 + ch*2] = Servo_data[CH_AETR[ch]] & 0xff;
|
||||
packet[10+ ch*2] = (Servo_data[CH_AETR[ch]] >> 8) & 0xff;
|
||||
//
|
||||
if (failsafe > AFHDS2AFailsafeMAX)
|
||||
failsafe = AFHDS2AFailsafeMAX;
|
||||
//
|
||||
if (failsafe < AFHDS2AFailsafeMIN)
|
||||
failsafe = AFHDS2AFailsafeMIN;
|
||||
//
|
||||
double scale = (float)failsafe/(float)100;
|
||||
int16_t failsafeMicros = 1500 + ((float)512 * scale);
|
||||
//
|
||||
packet[9 + ch*2] = failsafeMicros & 0xff;
|
||||
packet[10+ ch*2] = ( failsafeMicros >> 8) & 0xff;
|
||||
}
|
||||
else*/
|
||||
else
|
||||
#endif
|
||||
{
|
||||
packet[9 + ch*2] = 0xff;
|
||||
packet[10+ ch*2] = 0xff;
|
||||
|
@ -21,8 +21,11 @@
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
uint8_t chanskip;
|
||||
uint8_t seq_last_sent;
|
||||
uint8_t seq_last_rcvd;
|
||||
//uint8_t seq_last_sent;
|
||||
//uint8_t seq_last_rcvd;
|
||||
|
||||
uint8_t FrX_send_seq ;
|
||||
uint8_t FrX_receive_seq ;
|
||||
|
||||
static void __attribute__((unused)) set_start(uint8_t ch )
|
||||
{
|
||||
@ -151,13 +154,7 @@ static void __attribute__((unused)) frskyX_data_frame()
|
||||
packet[9+i+2]=chan_1>>4;
|
||||
}
|
||||
|
||||
packet[21] = seq_last_sent << 4 | seq_last_rcvd;//8 at start
|
||||
if (seq_last_sent < 0x08 && seq_last_rcvd < 8)
|
||||
seq_last_sent = (seq_last_sent + 1) % 4;
|
||||
else if (seq_last_rcvd == 0x00)
|
||||
seq_last_sent = 1;
|
||||
else
|
||||
seq_last_rcvd = 8;
|
||||
packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
|
||||
|
||||
if(sub_protocol & 1 )// in X8 mode send only 8ch every 9ms
|
||||
lpass = 0 ;
|
||||
@ -210,9 +207,9 @@ uint16_t ReadFrSkyX()
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteData(packet, packet[0]+1);
|
||||
//
|
||||
frskyX_data_frame();
|
||||
// frskyX_data_frame();
|
||||
state++;
|
||||
return 5500;
|
||||
return 5200;
|
||||
case FRSKY_DATA2:
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
@ -221,7 +218,7 @@ uint16_t ReadFrSkyX()
|
||||
case FRSKY_DATA3:
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
state++;
|
||||
return 3000;
|
||||
return 3100;
|
||||
case FRSKY_DATA4:
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
|
||||
@ -240,8 +237,10 @@ uint16_t ReadFrSkyX()
|
||||
// restart sequence on missed packet - might need count or timeout instead of one missed
|
||||
if(packet_count>100)
|
||||
{//~1sec
|
||||
seq_last_sent = 0;
|
||||
seq_last_rcvd = 8;
|
||||
// seq_last_sent = 0;
|
||||
// seq_last_rcvd = 8;
|
||||
FrX_send_seq = 0x08 ;
|
||||
// FrX_receive_seq = 0 ;
|
||||
packet_count=0;
|
||||
#if defined TELEMETRY
|
||||
telemetry_lost=1;
|
||||
@ -249,8 +248,13 @@ uint16_t ReadFrSkyX()
|
||||
}
|
||||
CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO
|
||||
}
|
||||
frskyX_data_frame();
|
||||
if ( FrX_send_seq != 0x08 )
|
||||
{
|
||||
FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
|
||||
}
|
||||
state = FRSKY_DATA1;
|
||||
return 300;
|
||||
return 500;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -279,8 +283,10 @@ uint16_t initFrSkyX()
|
||||
state = FRSKY_DATA1;
|
||||
initialize_data(0);
|
||||
}
|
||||
seq_last_sent = 0;
|
||||
seq_last_rcvd = 8;
|
||||
// seq_last_sent = 0;
|
||||
// seq_last_rcvd = 8;
|
||||
FrX_send_seq = 0x08 ;
|
||||
FrX_receive_seq = 0 ;
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
@ -19,7 +19,7 @@
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 1
|
||||
#define VERSION_REVISION 6
|
||||
#define VERSION_PATCH_LEVEL 21
|
||||
#define VERSION_PATCH_LEVEL 22
|
||||
//******************
|
||||
// Protocols
|
||||
//******************
|
||||
@ -393,7 +393,7 @@ enum CC2500_POWER
|
||||
CC2500_POWER_16 = 0xFE, // 0dbm
|
||||
CC2500_POWER_17 = 0xFF // +1dbm
|
||||
};
|
||||
#define CC2500_HIGH_POWER CC2500_POWER_16
|
||||
#define CC2500_HIGH_POWER CC2500_POWER_17
|
||||
#define CC2500_LOW_POWER CC2500_POWER_13
|
||||
#define CC2500_RANGE_POWER CC2500_POWER_1
|
||||
#define CC2500_BIND_POWER CC2500_POWER_1
|
||||
|
@ -23,6 +23,11 @@
|
||||
#include <avr/pgmspace.h>
|
||||
//#define DEBUG_TX
|
||||
//#define USE_MY_CONFIG
|
||||
|
||||
#ifdef ARDUINO_AVR_XMEGA32D4
|
||||
#include "MultiOrange.h"
|
||||
#endif
|
||||
|
||||
#include "Multiprotocol.h"
|
||||
|
||||
//Multiprotocol module configuration file
|
||||
@ -106,6 +111,19 @@ uint8_t RX_num;
|
||||
uint8_t calData[48];
|
||||
#endif
|
||||
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
uint8_t BootTimer ;
|
||||
uint8_t BootState ;
|
||||
uint8_t NotBootChecking ;
|
||||
uint8_t BootCount ;
|
||||
|
||||
#define BOOT_WAIT_30_IDLE 0
|
||||
#define BOOT_WAIT_30_DATA 1
|
||||
#define BOOT_WAIT_20 2
|
||||
#define BOOT_READY 3
|
||||
|
||||
#endif
|
||||
|
||||
//Channel mapping for protocols
|
||||
const uint8_t CH_AETR[]={AILERON, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8, AUX9, AUX10};
|
||||
const uint8_t CH_TAER[]={THROTTLE, AILERON, ELEVATOR, RUDDER, AUX1, AUX2, AUX3, AUX4, AUX5, AUX6, AUX7, AUX8};
|
||||
@ -154,7 +172,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||
uint8_t pktt[MAX_PKT];//telemetry receiving packets
|
||||
#ifdef BASH_SERIAL
|
||||
// For bit-bashed serial output
|
||||
#define TXBUFFER_SIZE 128
|
||||
#define TXBUFFER_SIZE 192
|
||||
volatile struct t_serial_bash
|
||||
{
|
||||
uint8_t head ;
|
||||
@ -164,7 +182,7 @@ uint8_t pkt[MAX_PKT];//telemetry receiving packets
|
||||
uint8_t speed ;
|
||||
} SerialControl ;
|
||||
#else
|
||||
#define TXBUFFER_SIZE 64
|
||||
#define TXBUFFER_SIZE 96
|
||||
volatile uint8_t tx_buff[TXBUFFER_SIZE];
|
||||
volatile uint8_t tx_head=0;
|
||||
volatile uint8_t tx_tail=0;
|
||||
@ -392,12 +410,142 @@ void setup()
|
||||
protocol=0;
|
||||
servo_max_100=SERIAL_MAX_100; servo_min_100=SERIAL_MIN_100;
|
||||
servo_max_125=SERIAL_MAX_125; servo_min_125=SERIAL_MIN_125;
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
Mprotocol_serial_init(1); // Configure serial and enable RX interrupt
|
||||
#else
|
||||
Mprotocol_serial_init(); // Configure serial and enable RX interrupt
|
||||
#endif
|
||||
#endif //ENABLE_SERIAL
|
||||
}
|
||||
servo_mid=servo_min_100+servo_max_100; //In fact 2* mid_value
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
void pollBoot()
|
||||
{
|
||||
uint8_t rxchar ;
|
||||
uint8_t lState = BootState ;
|
||||
uint8_t millisTime = millis() ; // Call this once only
|
||||
#ifdef ORANGE_TX
|
||||
if ( USARTC0.STATUS & USART_RXCIF_bm )
|
||||
#elif defined STM32_BOARD
|
||||
if ( USART2_BASE->SR & USART_SR_RXNE )
|
||||
#else
|
||||
if ( UCSR0A & ( 1 << RXC0 ) )
|
||||
#endif
|
||||
{
|
||||
rxchar = UDR0 ;
|
||||
BootCount += 1 ;
|
||||
if ( ( lState == BOOT_WAIT_30_IDLE ) || ( lState == BOOT_WAIT_30_DATA ) )
|
||||
{
|
||||
if ( lState == BOOT_WAIT_30_IDLE ) // Waiting for 0x30
|
||||
{
|
||||
BootTimer = millisTime ; // Start timeout
|
||||
}
|
||||
if ( rxchar == 0x30 )
|
||||
{
|
||||
lState = BOOT_WAIT_20 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
lState = BOOT_WAIT_30_DATA ;
|
||||
}
|
||||
}
|
||||
else if ( lState == BOOT_WAIT_20 ) // Waiting for 0x20
|
||||
{
|
||||
if ( rxchar == 0x20 )
|
||||
{
|
||||
lState = BOOT_READY ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // No byte received
|
||||
{
|
||||
if ( lState != BOOT_WAIT_30_IDLE ) // Something received
|
||||
{
|
||||
uint8_t time = millisTime - BootTimer ;
|
||||
if ( time > 5 )
|
||||
{
|
||||
#ifdef STM32_BOARD
|
||||
if ( BootCount > 4 )
|
||||
#else
|
||||
if ( BootCount > 2 )
|
||||
#endif
|
||||
{ // Run normally
|
||||
NotBootChecking = 0xFF ;
|
||||
Mprotocol_serial_init( 0 ) ;
|
||||
}
|
||||
else if ( lState == BOOT_READY )
|
||||
{
|
||||
#ifdef STM32_BOARD
|
||||
#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
|
||||
#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */
|
||||
#define __I volatile /*!< defines 'read only' permissions */
|
||||
#define __IO volatile /*!< defines 'read / write' permissions */
|
||||
typedef struct
|
||||
{
|
||||
__I uint32_t CPUID; /*!< Offset: 0x00 CPU ID Base Register */
|
||||
__IO uint32_t ICSR; /*!< Offset: 0x04 Interrupt Control State Register */
|
||||
__IO uint32_t VTOR; /*!< Offset: 0x08 Vector Table Offset Register */
|
||||
__IO uint32_t AIRCR; /*!< Offset: 0x0C Application Interrupt / Reset Control Register */
|
||||
__IO uint32_t SCR; /*!< Offset: 0x10 System Control Register */
|
||||
__IO uint32_t CCR; /*!< Offset: 0x14 Configuration Control Register */
|
||||
__IO uint8_t SHP[12]; /*!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */
|
||||
__IO uint32_t SHCSR; /*!< Offset: 0x24 System Handler Control and State Register */
|
||||
__IO uint32_t CFSR; /*!< Offset: 0x28 Configurable Fault Status Register */
|
||||
__IO uint32_t HFSR; /*!< Offset: 0x2C Hard Fault Status Register */
|
||||
__IO uint32_t DFSR; /*!< Offset: 0x30 Debug Fault Status Register */
|
||||
__IO uint32_t MMFAR; /*!< Offset: 0x34 Mem Manage Address Register */
|
||||
__IO uint32_t BFAR; /*!< Offset: 0x38 Bus Fault Address Register */
|
||||
__IO uint32_t AFSR; /*!< Offset: 0x3C Auxiliary Fault Status Register */
|
||||
__I uint32_t PFR[2]; /*!< Offset: 0x40 Processor Feature Register */
|
||||
__I uint32_t DFR; /*!< Offset: 0x48 Debug Feature Register */
|
||||
__I uint32_t ADR; /*!< Offset: 0x4C Auxiliary Feature Register */
|
||||
__I uint32_t MMFR[4]; /*!< Offset: 0x50 Memory Model Feature Register */
|
||||
__I uint32_t ISAR[5]; /*!< Offset: 0x60 ISA Feature Register */
|
||||
} SCB_Type;
|
||||
#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
|
||||
#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */
|
||||
#define SCB_AIRCR_PRIGROUP_Msk (7ul << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
|
||||
#define SCB_AIRCR_SYSRESETREQ_Msk (1ul << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
|
||||
|
||||
// NVIC_SystemReset() ;
|
||||
//static __INLINE void NVIC_SystemReset(void)
|
||||
{
|
||||
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
|
||||
(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
|
||||
SCB_AIRCR_SYSRESETREQ_Msk) ; /* Keep priority group unchanged */
|
||||
asm("dsb");
|
||||
while(1) ; /* wait until reset */
|
||||
}
|
||||
#else
|
||||
cli(); // Disable global int due to RW of 16 bits registers
|
||||
void (*p)() ;
|
||||
#ifndef ORANGE_TX
|
||||
p = (void (*)())0x3F00 ; // Word address (0x7E00 byte)
|
||||
#else
|
||||
p = (void (*)())0x4000 ; // Word address (0x8000 byte)
|
||||
#endif
|
||||
(*p)() ;
|
||||
// go to boot
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
lState = BOOT_WAIT_30_IDLE ;
|
||||
BootCount = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BootState = lState ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Main
|
||||
// Protocol scheduler
|
||||
void loop()
|
||||
@ -485,6 +633,13 @@ void loop()
|
||||
uint8_t Update_All()
|
||||
{
|
||||
#ifdef ENABLE_SERIAL
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( (mode_select==MODE_SERIAL) && (NotBootChecking == 0) )
|
||||
{
|
||||
pollBoot() ;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(mode_select==MODE_SERIAL && IS_RX_FLAG_on) // Serial mode and something has been received
|
||||
{
|
||||
update_serial_data(); // Update protocol and data
|
||||
@ -1093,7 +1248,11 @@ void modules_reset()
|
||||
prev_power=0xFD; // unused power value
|
||||
}
|
||||
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
void Mprotocol_serial_init( uint8_t boot )
|
||||
#else
|
||||
void Mprotocol_serial_init()
|
||||
#endif
|
||||
{
|
||||
#ifdef ORANGE_TX
|
||||
PORTC.OUTSET = 0x08 ;
|
||||
@ -1103,16 +1262,41 @@ void Mprotocol_serial_init()
|
||||
USARTC0.BAUDCTRLB = 0 ;
|
||||
|
||||
USARTC0.CTRLB = 0x18 ;
|
||||
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCF) | 0x10 ;
|
||||
USARTC0.CTRLA = (USARTC0.CTRLA & 0xCC) | 0x11 ;
|
||||
USARTC0.CTRLC = 0x2B ;
|
||||
UDR0 ;
|
||||
#ifdef INVERT_SERIAL
|
||||
PORTC.PIN3CTRL |= 0x40 ;
|
||||
#endif
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( boot )
|
||||
{
|
||||
USARTC0.BAUDCTRLB = 0 ;
|
||||
USARTC0.BAUDCTRLA = 33 ; // 57600
|
||||
USARTC0.CTRLA = (USARTC0.CTRLA & 0xC0) ;
|
||||
USARTC0.CTRLC = 0x03 ; // 8 bit, no parity, 1 stop
|
||||
USARTC0.CTRLB = 0x18 ; // Enable Tx and Rx
|
||||
PORTC.PIN3CTRL &= ~0x40 ;
|
||||
}
|
||||
#endif // CHECK_FOR_BOOTLOADER
|
||||
#elif defined STM32_BOARD
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( boot )
|
||||
{
|
||||
usart2_begin(57600,SERIAL_8N1);
|
||||
USART2_BASE->CR1 &= ~USART_CR1_RXNEIE ;
|
||||
(void)UDR0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
usart2_begin(100000,SERIAL_8E2);
|
||||
USART2_BASE->CR1 |= USART_CR1_PCE_BIT;
|
||||
}
|
||||
#else
|
||||
usart2_begin(100000,SERIAL_8E2);
|
||||
usart3_begin(100000,SERIAL_8E2);
|
||||
USART2_BASE->CR1 |= USART_CR1_PCE_BIT;
|
||||
#endif // CHECK_FOR_BOOTLOADER
|
||||
usart3_begin(100000,SERIAL_8E2);
|
||||
USART3_BASE->CR1 &= ~ USART_CR1_RE;//disable
|
||||
USART2_BASE->CR1 &= ~ USART_CR1_TE;//disable transmit
|
||||
#else
|
||||
@ -1132,6 +1316,16 @@ void Mprotocol_serial_init()
|
||||
initTXSerial( SPEED_100K ) ;
|
||||
#endif //TELEMETRY
|
||||
#endif //DEBUG_TX
|
||||
#ifdef CHECK_FOR_BOOTLOADER
|
||||
if ( boot )
|
||||
{
|
||||
UBRR0H = 0 ;
|
||||
UBRR0L = 33 ; // 57600
|
||||
UCSR0C &= ~_BV(UPM01) ; // No parity
|
||||
UCSR0B &= ~_BV(RXCIE0);// No rx interrupt
|
||||
UCSR0A |= _BV(U2X0); //Double speed mode USART0
|
||||
}
|
||||
#endif // CHECK_FOR_BOOTLOADER
|
||||
#endif //ORANGE_TX
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define SYMAX_FLAG_VIDEO 0x02
|
||||
#define SYMAX_FLAG_PICTURE 0x04
|
||||
#define SYMAX_FLAG_HEADLESS 0x08
|
||||
#define SYMAX_XTRM_RATES 0x10
|
||||
|
||||
#define SYMAX_PAYLOADSIZE 10 // receive data pipes set to this size, but unused
|
||||
#define SYMAX_MAX_PACKET_LENGTH 16 // X11,X12,X5C-1 10-byte, X5C 16-byte
|
||||
@ -58,6 +59,7 @@ static void __attribute__((unused)) SYMAX_read_controls()
|
||||
{
|
||||
// Protocol is registered AETRF, that is
|
||||
// Aileron is channel 1, Elevator - 2, Throttle - 3, Rudder - 4, Flip control - 5
|
||||
// Extended (trim-added) Rates - 6, Photo - 7, Video - 8, Headless - 9
|
||||
aileron = convert_channel_s8b(AILERON);
|
||||
elevator = convert_channel_s8b(ELEVATOR);
|
||||
throttle = convert_channel_8b(THROTTLE);
|
||||
@ -67,6 +69,9 @@ static void __attribute__((unused)) SYMAX_read_controls()
|
||||
// Channel 5
|
||||
if (Servo_AUX1)
|
||||
flags = SYMAX_FLAG_FLIP;
|
||||
// Channel 6
|
||||
if (Servo_AUX2)
|
||||
flags |= SYMAX_XTRM_RATES;
|
||||
// Channel 7
|
||||
if (Servo_AUX3)
|
||||
flags |= SYMAX_FLAG_PICTURE;
|
||||
@ -76,6 +81,7 @@ static void __attribute__((unused)) SYMAX_read_controls()
|
||||
// Channel 9
|
||||
if (Servo_AUX5)
|
||||
flags |= SYMAX_FLAG_HEADLESS;
|
||||
flags &= ~SYMAX_XTRM_RATES; // Extended rates & headless incompatible
|
||||
}
|
||||
|
||||
#define X5C_CHAN2TRIM(X) ((((X) & 0x80 ? 0xff - (X) : 0x80 + (X)) >> 2) + 0x20)
|
||||
@ -98,9 +104,15 @@ static void __attribute__((unused)) SYMAX_build_packet_x5c(uint8_t bind)
|
||||
packet[1] = rudder;
|
||||
packet[2] = elevator ^ 0x80; // reversed from default
|
||||
packet[3] = aileron;
|
||||
packet[4] = X5C_CHAN2TRIM(rudder ^ 0x80);// drive trims for extra control range
|
||||
packet[5] = X5C_CHAN2TRIM(elevator);
|
||||
packet[6] = X5C_CHAN2TRIM(aileron ^ 0x80);
|
||||
if (flags & SYMAX_XTRM_RATES) { // drive trims for extra control range
|
||||
packet[4] = X5C_CHAN2TRIM(rudder ^ 0x80);
|
||||
packet[5] = X5C_CHAN2TRIM(elevator);
|
||||
packet[6] = X5C_CHAN2TRIM(aileron ^ 0x80);
|
||||
} else {
|
||||
packet[4] = 0x00;
|
||||
packet[5] = 0x00;
|
||||
packet[6] = 0x00;
|
||||
}
|
||||
packet[7] = 0xae;
|
||||
packet[8] = 0xa9;
|
||||
packet[9] = 0x00;
|
||||
@ -138,9 +150,14 @@ static void __attribute__((unused)) SYMAX_build_packet(uint8_t bind)
|
||||
packet[2] = rudder;
|
||||
packet[3] = aileron;
|
||||
packet[4] = (flags & SYMAX_FLAG_VIDEO ? 0x80 : 0x00) | (flags & SYMAX_FLAG_PICTURE ? 0x40 : 0x00);
|
||||
packet[5] = (elevator >> 2) | 0xc0; //always high rates (bit 7 is rate control)
|
||||
packet[6] = (rudder >> 2) | (flags & SYMAX_FLAG_FLIP ? 0x40 : 0x00);
|
||||
packet[7] = (aileron >> 2) | (flags & SYMAX_FLAG_HEADLESS ? 0x80 : 0x00);
|
||||
packet[5] = 0xc0; //always high rates (bit 7 is rate control)
|
||||
packet[6] = flags & SYMAX_FLAG_FLIP ? 0x40 : 0x00;
|
||||
packet[7] = flags & SYMAX_FLAG_HEADLESS ? 0x80 : 0x00;
|
||||
if (flags & SYMAX_XTRM_RATES) { // use trims to extend controls
|
||||
packet[5] |= elevator >> 2;
|
||||
packet[6] |= rudder >> 2;
|
||||
packet[7] |= aileron >> 2;
|
||||
}
|
||||
packet[8] = 0x00;
|
||||
}
|
||||
packet[9] = SYMAX_checksum(packet);
|
||||
|
@ -31,6 +31,34 @@ uint8_t RetrySequence ;
|
||||
uint8_t sport_counter=0;
|
||||
uint8_t RxBt = 0;
|
||||
uint8_t sport = 0;
|
||||
#define MAX_PKTX 10
|
||||
#define FX_BUFFERS 4
|
||||
uint8_t pktx[MAX_PKTX];
|
||||
uint8_t pktx1[FRSKY_SPORT_PACKET_SIZE*FX_BUFFERS];
|
||||
uint8_t indx;
|
||||
//struct t_fx_rx_packet
|
||||
//{
|
||||
// uint8_t validSequence ;
|
||||
// uint8_t count ;
|
||||
// uint8_t payload[6] ;
|
||||
//} ;
|
||||
|
||||
// Store for out of sequence packet
|
||||
//struct t_fx_rx_packet FrskyxRxTelemetry ;
|
||||
|
||||
uint8_t FrskyxRxTelemetryValidSequence ;
|
||||
|
||||
struct t_fx_rx_frame
|
||||
{
|
||||
uint8_t valid ;
|
||||
uint8_t count ;
|
||||
uint8_t payload[6] ;
|
||||
} ;
|
||||
|
||||
// Store for FrskyX telemetry
|
||||
struct t_fx_rx_frame FrskyxRxFrames[4] ;
|
||||
uint8_t NextFxFrameToForward ;
|
||||
|
||||
#endif
|
||||
#if defined HUB_TELEMETRY
|
||||
#define USER_MAX_BYTES 6
|
||||
@ -40,10 +68,6 @@ uint8_t RetrySequence ;
|
||||
#define START_STOP 0x7e
|
||||
#define BYTESTUFF 0x7d
|
||||
#define STUFF_MASK 0x20
|
||||
#define MAX_PKTX 10
|
||||
uint8_t pktx[MAX_PKTX];
|
||||
uint8_t pktx1[MAX_PKTX];
|
||||
uint8_t indx;
|
||||
uint8_t frame[18];
|
||||
|
||||
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
|
||||
@ -155,7 +179,8 @@ void frskySendStuffed()
|
||||
|
||||
void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
{
|
||||
if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len ==(pkt[0] + 3))
|
||||
uint8_t clen = pkt[0] + 3 ;
|
||||
if(pkt[1] == rx_tx_addr[3] && pkt[2] == rx_tx_addr[2] && len == clen )
|
||||
{
|
||||
telemetry_link|=1; // Telemetry data is available
|
||||
/*previous version
|
||||
@ -205,19 +230,144 @@ void frsky_check_telemetry(uint8_t *pkt,uint8_t len)
|
||||
telemetry_lost=0;
|
||||
if (protocol==MODE_FRSKYX)
|
||||
{
|
||||
if ((pktt[5] >> 4 & 0x0f) == 0x08)
|
||||
uint16_t lcrc = crc_x(&pkt[3], len-7 ) ;
|
||||
// if ( ( sub_protocol & 2 ) == 0 )
|
||||
// {
|
||||
// if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) )
|
||||
// {
|
||||
// lcrc = 0 ;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// lcrc = 1 ;
|
||||
// }
|
||||
// }
|
||||
// if ( lcrc == 0 )
|
||||
|
||||
if ( ( (lcrc >> 8) == pkt[len-4]) && ( (lcrc & 0x00FF ) == pkt[len-3]) )
|
||||
{
|
||||
seq_last_sent = 8;
|
||||
seq_last_rcvd = 0;
|
||||
pass=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4)
|
||||
seq_last_rcvd = (seq_last_rcvd + 1) % 4;
|
||||
// Check if in sequence
|
||||
if ( (pkt[5] & 0x0F) == 0x08 )
|
||||
{
|
||||
FrX_receive_seq = 0x08 ;
|
||||
NextFxFrameToForward = 0 ;
|
||||
FrskyxRxFrames[0].valid = 0 ;
|
||||
FrskyxRxFrames[1].valid = 0 ;
|
||||
FrskyxRxFrames[2].valid = 0 ;
|
||||
FrskyxRxFrames[3].valid = 0 ;
|
||||
}
|
||||
else if ( (pkt[5] & 0x03) == (FrX_receive_seq & 0x03 ) )
|
||||
{
|
||||
// OK to process
|
||||
struct t_fx_rx_frame *p ;
|
||||
uint8_t count ;
|
||||
p = &FrskyxRxFrames[FrX_receive_seq & 3] ;
|
||||
count = pkt[6] ;
|
||||
if ( count <= 6 )
|
||||
{
|
||||
p->count = count ;
|
||||
for ( uint8_t i = 0 ; i < count ; i += 1 )
|
||||
{
|
||||
p->payload[i] = pkt[i+7] ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->count = 0 ;
|
||||
}
|
||||
p->valid = 1 ;
|
||||
|
||||
|
||||
|
||||
FrX_receive_seq = ( FrX_receive_seq + 1 ) & 0x03 ;
|
||||
|
||||
if ( FrskyxRxTelemetryValidSequence & 0x80 )
|
||||
{
|
||||
FrX_receive_seq = ( FrskyxRxTelemetryValidSequence + 1 ) & 3 ;
|
||||
FrskyxRxTelemetryValidSequence &= 0x7F ;
|
||||
}
|
||||
|
||||
// if ( FrskyxRxTelemetry.validSequence & 0x80 )
|
||||
// {
|
||||
// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ;
|
||||
|
||||
// FrskyxRxTelemetry.validSequence &= 0x7F ;
|
||||
|
||||
// }
|
||||
}
|
||||
else
|
||||
pass=0;//reset if sequence wrong
|
||||
{
|
||||
// Save and request correct packet
|
||||
// struct t_fx_rx_packet *p ;
|
||||
struct t_fx_rx_frame *q ;
|
||||
uint8_t count ;
|
||||
// pkt[4] RSSI
|
||||
// pkt[5] sequence control
|
||||
// pkt[6] payload count
|
||||
// pkt[7-12] payload
|
||||
pktt[6] = 0 ; // Don't process
|
||||
if ( (pkt[5] & 0x03) == ( ( FrX_receive_seq +1 ) & 3 ) )
|
||||
{
|
||||
q = &FrskyxRxFrames[(pkt[5] & 0x03)] ;
|
||||
count = pkt[6] ;
|
||||
if ( count <= 6 )
|
||||
{
|
||||
q->count = count ;
|
||||
for ( uint8_t i = 0 ; i < count ; i += 1 )
|
||||
{
|
||||
q->payload[i] = pkt[i+7] ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
q->count = 0 ;
|
||||
}
|
||||
q->valid = 1 ;
|
||||
|
||||
FrskyxRxTelemetryValidSequence = 0x80 | ( pkt[5] & 0x03 ) ;
|
||||
}
|
||||
|
||||
|
||||
// p = &FrskyxRxTelemetry ;
|
||||
// count = pkt[6] ;
|
||||
// if ( count <= 6 )
|
||||
// {
|
||||
// p->count = count ;
|
||||
// for ( uint8_t i = 0 ; i < count ; i += 1 )
|
||||
// {
|
||||
// p->payload[i] = pkt[i+7] ;
|
||||
// }
|
||||
// p->validSequence = 0x80 | ( pkt[5] & 0x03 ) ;
|
||||
// }
|
||||
FrX_receive_seq = ( FrX_receive_seq & 0x03 ) | 0x04 ; // Request re-transmission
|
||||
}
|
||||
|
||||
if (((pktt[5] >> 4) & 0x0f) == 0x08)
|
||||
{
|
||||
FrX_send_seq = 0 ;
|
||||
// FrX_receive_seq = 0x08 ;
|
||||
}
|
||||
}
|
||||
|
||||
// packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
|
||||
// if ( FrX_send_seq != 0x08 )
|
||||
// {
|
||||
// FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
|
||||
// }
|
||||
|
||||
// if ((pktt[5] >> 4 & 0x0f) == 0x08)
|
||||
// {
|
||||
// seq_last_sent = 8;
|
||||
// seq_last_rcvd = 0;
|
||||
// pass=0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if ((pktt[5] >> 4 & 0x03) == (seq_last_rcvd + 1) % 4)
|
||||
// seq_last_rcvd = (seq_last_rcvd + 1) % 4;
|
||||
// else
|
||||
// pass=0;//reset if sequence wrong
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -363,12 +513,25 @@ pkt[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
|
||||
0x34 0x0A 0xC3 0x56 0xF3
|
||||
|
||||
*/
|
||||
|
||||
const uint8_t PROGMEM Indices[] = { 0x00, 0xA1, 0x22, 0x83, 0xE4, 0x45,
|
||||
0xC6, 0x67, 0x48, 0xE9, 0x6A, 0xCB,
|
||||
0xAC, 0x0D, 0x8E, 0x2F, 0xD0, 0x71,
|
||||
0xF2, 0x53, 0x34, 0x95, 0x16, 0xB7,
|
||||
0x98, 0x39, 0xBA, 0x1B } ;
|
||||
|
||||
|
||||
#ifdef MULTI_TELEMETRY
|
||||
void sportSend(uint8_t *p)
|
||||
{
|
||||
multi_send_header(MULTI_TELEMETRY_SPORT, 9);
|
||||
uint16_t crc_s = 0;
|
||||
Serial_write(p[0]) ;
|
||||
uint8_t x = p[0] ;
|
||||
if ( x <= 0x1B )
|
||||
{
|
||||
x = pgm_read_byte_near( &Indices[x] ) ;
|
||||
}
|
||||
Serial_write(x) ;
|
||||
for (uint8_t i = 1; i < 9; i++)
|
||||
{
|
||||
if (i == 8)
|
||||
@ -462,7 +625,13 @@ void sportSendFrame()
|
||||
{
|
||||
for (i=0;i<FRSKY_SPORT_PACKET_SIZE;i++)
|
||||
frame[i]=pktx1[i];
|
||||
sport=0;
|
||||
sport -= 1 ;
|
||||
if ( sport )
|
||||
{
|
||||
uint8_t j = sport * FRSKY_SPORT_PACKET_SIZE ;
|
||||
for (i=0;i<j;i++)
|
||||
pktx1[i] = pktx1[i+FRSKY_SPORT_PACKET_SIZE] ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -506,19 +675,20 @@ void proces_sport_data(uint8_t data)
|
||||
} // end switch
|
||||
if (indx >= FRSKY_SPORT_PACKET_SIZE)
|
||||
{//8 bytes no crc
|
||||
if ( sport )
|
||||
{
|
||||
// overrun!
|
||||
}
|
||||
else
|
||||
if ( sport < FX_BUFFERS )
|
||||
{
|
||||
uint8_t dest = sport * FRSKY_SPORT_PACKET_SIZE ;
|
||||
uint8_t i ;
|
||||
for ( i = 0 ; i < FRSKY_SPORT_PACKET_SIZE ; i += 1 )
|
||||
{
|
||||
pktx1[i] = pktx[i] ; // Double buffer
|
||||
pktx1[dest++] = pktx[i] ; // Triple buffer
|
||||
}
|
||||
sport = 1;//ok to send
|
||||
sport += 1 ;//ok to send
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// // Overrun
|
||||
// }
|
||||
pass = 0;//reset
|
||||
}
|
||||
}
|
||||
@ -534,11 +704,14 @@ void TelemetryUpdate()
|
||||
h = SerialControl.head ;
|
||||
t = SerialControl.tail ;
|
||||
if ( h >= t )
|
||||
t += 128 - h ;
|
||||
t += 192 - h ;
|
||||
else
|
||||
t -= h ;
|
||||
// if ( t < 32 )
|
||||
if ( t < 64 )
|
||||
{
|
||||
return ;
|
||||
}
|
||||
#else
|
||||
uint8_t h ;
|
||||
uint8_t t ;
|
||||
@ -549,7 +722,9 @@ void TelemetryUpdate()
|
||||
else
|
||||
t -= h ;
|
||||
if ( t < 32 )
|
||||
{
|
||||
return ;
|
||||
}
|
||||
#endif
|
||||
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
|
||||
{
|
||||
@ -566,15 +741,62 @@ void TelemetryUpdate()
|
||||
#if defined SPORT_TELEMETRY
|
||||
if (protocol==MODE_FRSKYX)
|
||||
{ // FrSkyX
|
||||
// struct t_fx_rx_frame *p ;
|
||||
// uint8_t count ;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
struct t_fx_rx_frame *p ;
|
||||
uint8_t count ;
|
||||
p = &FrskyxRxFrames[NextFxFrameToForward] ;
|
||||
if ( p->valid )
|
||||
{
|
||||
count = p->count ;
|
||||
for (uint8_t i=0; i < count ; i++)
|
||||
proces_sport_data(p->payload[i]) ;
|
||||
p->valid = 0 ; // Sent on
|
||||
NextFxFrameToForward = ( NextFxFrameToForward + 1 ) & 3 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
// p = &FrskyxRxFrames[NextFxFrameToForward] ;
|
||||
// if ( p->valid )
|
||||
// {
|
||||
// count = p->count ;
|
||||
// for (uint8_t i=0; i < count ; i++)
|
||||
// proces_sport_data(p->payload[i]) ;
|
||||
// p->valid = 0 ; // Sent on
|
||||
// NextFxFrameToForward = ( NextFxFrameToForward + 1 ) & 3 ;
|
||||
// }
|
||||
|
||||
if(telemetry_link)
|
||||
{
|
||||
if(pktt[4] & 0x80)
|
||||
RX_RSSI=pktt[4] & 0x7F ;
|
||||
else
|
||||
RxBt = (pktt[4]<<1) + 1 ;
|
||||
if(pktt[6] && pktt[6]<=6)
|
||||
for (uint8_t i=0; i < pktt[6]; i++)
|
||||
proces_sport_data(pktt[7+i]);
|
||||
|
||||
// if(pktt[6] && pktt[6]<=6)
|
||||
// {
|
||||
// for (uint8_t i=0; i < pktt[6]; i++)
|
||||
// proces_sport_data(pktt[7+i]);
|
||||
// if ( FrskyxRxTelemetry.validSequence & 0x80 )
|
||||
// {
|
||||
// // Process out of sequence packet
|
||||
// for (uint8_t i=0; i < FrskyxRxTelemetry.count ; i++)
|
||||
// {
|
||||
// proces_sport_data( FrskyxRxTelemetry.payload[i] ) ;
|
||||
// }
|
||||
//// FrX_receive_seq = ( FrskyxRxTelemetry.validSequence + 1 ) & 3 ;
|
||||
// FrskyxRxTelemetry.validSequence = 0 ;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
telemetry_link=0;
|
||||
}
|
||||
uint32_t now = micros();
|
||||
@ -928,7 +1150,13 @@ ISR(TIMER0_COMPB_vect)
|
||||
{
|
||||
GPIOR0 = ptr->data[ptr->tail] ;
|
||||
GPIOR2 = ptr->data[ptr->tail+1] ;
|
||||
ptr->tail = ( ptr->tail + 2 ) & 0x7F ;
|
||||
uint8_t nextTail ;
|
||||
nextTail = ptr->tail + 2 ;
|
||||
if ( nextTail > 192 )
|
||||
{
|
||||
nextTail = 0 ;
|
||||
}
|
||||
ptr->tail = nextTail ;
|
||||
GPIOR1 = 8 ;
|
||||
OCR0A = OCR0B + 40 ;
|
||||
OCR0B = OCR0A + 8 * 20 ;
|
||||
|
@ -49,6 +49,15 @@
|
||||
//The goal is to prevent binding other people's model when powering up the TX, changing model or scanning through protocols.
|
||||
#define WAIT_FOR_BIND
|
||||
|
||||
/*************************/
|
||||
/*** BOOTLOADER USE ***/
|
||||
/*************************/
|
||||
#define CHECK_FOR_BOOTLOADER
|
||||
//Allow flashing multimodule directly with TX(erky9x or opentx modified firmwares)
|
||||
//1. Start ersky9x in bootloader mode and copy the multi.hex file into the firmware directory on the SD card.
|
||||
//2. Disconnect the USB, then press EXIT LONG while holding the horizontal trims APART to enter "maintenance mode".
|
||||
//3. Select "Update Multi", then HEX mode, then select the file and start the flash.
|
||||
//4. When finished, EXIT back to reboot in normal mode.
|
||||
|
||||
/****************/
|
||||
/*** RF CHIPS ***/
|
||||
@ -87,6 +96,41 @@
|
||||
//Default is commented, you should uncoment only for test purpose or if you know exactly what you are doing!!!
|
||||
//#define FORCE_CYRF_ID "\x12\x34\x56\x78\x9A\xBC"
|
||||
|
||||
/**************************/
|
||||
/*** FAILSAFE SETTINGS ***/
|
||||
/**************************/
|
||||
#define AFHDS2A_FAILSAFE
|
||||
#ifdef AFHDS2A_FAILSAFE
|
||||
/*
|
||||
Failsafe Min/Max values 962 <-> 2038
|
||||
*/
|
||||
const int8_t AFHDS2AFailsafeMIN = -105;
|
||||
const int8_t AFHDS2AFailsafeMAX = 105;
|
||||
//
|
||||
const int8_t AFHDS2AFailsafe[14]= {
|
||||
/*
|
||||
Failsafe examples
|
||||
988 <-> 2012µs -100% = 988 = 1500 + (2012-988)/2 * (-100/100) = 1500 - 512 = 988
|
||||
988 <-> 2012µs 0% = 1500 = 1500 + (2012-988)/2 * ( 0/100) = 1500 + 0 = 1500
|
||||
988 <-> 2012µs 100% = 2012 = 1500 + (2012-988)/2 * ( 100/100) = 1500 + 512 = 2012
|
||||
988 <-> 2012µs -105% = 962 = 1500 + (2012-988)/2 * (-105/100) = 1500 - 538 = 962
|
||||
*/
|
||||
/* ch 1 */ -1,
|
||||
/* ch 2 */ -1,
|
||||
/* ch 3 */ -105,
|
||||
/* ch 4 */ -1,
|
||||
/* ch 5 */ -1,
|
||||
/* ch 6 */ -1,
|
||||
/* ch 7 */ -1,
|
||||
/* ch 8 */ -1,
|
||||
/* ch 9 */ -1,
|
||||
/* ch 10 */ -1,
|
||||
/* ch 11 */ -1,
|
||||
/* ch 12 */ -1,
|
||||
/* ch 13 */ -1,
|
||||
/* ch 14 */ -1
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************/
|
||||
/*** PROTOCOLS TO INCLUDE ***/
|
||||
|
28
StmBoot/README.md
Normal file
28
StmBoot/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# StmMultiBoot
|
||||
Source files for Serial bootloader for use on the STM based Multi Module
|
||||
|
||||
To use this bootloader, you will need first to flash it to the module. Download the source files from the Github repository. Double click on the StmBoot.ino file to open the Arduino IDE. I'm assuming you already have this configured for building for the STM processor as it is needed for the Multi code.
|
||||
In "Tools", set the board to Generic STM32F013C series, the variant to 128K flash, and the Upload method to "Serial".
|
||||
You will need to connect to the serial port of the board, using a FTDI, or similar, interface, and fit the link to make it boot in the inbuilt bootloader. Again, this is the same as used for flashing the Multi code.
|
||||
Apply power to the Multi board, and click "Upload" in the Arduino IDE. The code should be compiled and flashed to the board.
|
||||
|
||||
Next, build the Multi code for flashing using a bootloader, in "Tools", set the Upload method to STM32duino bootloader, then use the "Export compiled binary" option to build the Multi firmware. This will put a .bin file in the sketch directory, you may wish to rename the file to have a shorter filename. Copy this file to "FIRMWARE" directory of the SD card in your radio.
|
||||
|
||||
You will also need to update the ersky9x firmware on your radio with the P221 "e2" test version (which I'll post soon). Start the radio in "maintenance mode", select "Update Multi", select the flashing options that depend on how your module is installed, and choose "Update". Select the file you put on the SD card and confirm to start flashing.
|
||||
|
||||
If you build using the "multiprotocol.ino" file I posted above, with "CHECK_FOR_BOOTLOADER" uncommented in _config.h, then flashing again later should work in the same way. If the Multi code doesn't have this bootlaoder check in, then you need the dial set to 0 and have the bind button pressed at power on to force the bootloader to run.
|
||||
|
||||
This bootloader will also work if you use the serial port, however you need to do some fiddling. First you need a .hex file of the Multi code, which you need to edit so it loads at address 2000 instead of 08002000. Then you use AvrDude set to use an ATMEGA128 and an Arduino programmer at 57600 baud to do the flashing.
|
||||
|
||||
When you do the build, a .bin file is exported, but you should find a .elf file in the "build" directory. I obtain a .hex file with:
|
||||
arm-none-eabi-objcopy -O ihex ..\..\Build\Multiprotocol.ino.elf multi.hex
|
||||
This hex file will start with a line:
|
||||
:020000040800F2
|
||||
change this to:
|
||||
:020000040000FA
|
||||
Further down the file, if the firmware is large enough, you will find a line:
|
||||
:020000040801F1
|
||||
change this to:
|
||||
:020000040001F9
|
||||
Then just use AvrDude to flash this .hex file to the STM board, but choose a processor of ATMEGA128, programmer Arduino, baudrate 57600 and the COM port of your FTDI adapter.
|
||||
|
558
StmBoot/StmBoot.ino
Normal file
558
StmBoot/StmBoot.ino
Normal file
@ -0,0 +1,558 @@
|
||||
|
||||
|
||||
#define _FLASH_PROG 1
|
||||
|
||||
|
||||
// Temp
|
||||
#define SIGNATURE_0 0x1E
|
||||
#define SIGNATURE_1 0x55 //0x97
|
||||
#define SIGNATURE_2 0xAA //0x02
|
||||
|
||||
#define SIGNATURE_3 0x97
|
||||
#define SIGNATURE_4 0x02
|
||||
|
||||
|
||||
#define STM32F10X_CL
|
||||
|
||||
#include "stm32f10x.h"
|
||||
|
||||
#include "stk500.h"
|
||||
#include "stm32f10x_flash.h"
|
||||
|
||||
#define OPTIBOOT_MAJVER 4
|
||||
#define OPTIBOOT_MINVER 5
|
||||
|
||||
uint32_t ResetReason ;
|
||||
uint32_t LongCount ;
|
||||
uint8_t Buff[512] ;
|
||||
|
||||
uint8_t NotSynced ;
|
||||
uint8_t Port ;
|
||||
|
||||
static void start_timer2()
|
||||
{
|
||||
TIM2->CNT = 0 ;
|
||||
TIM2->PSC = 71 ; // 72-1;for 72 MHZ /1.0usec/(71+1)
|
||||
TIM2->ARR = 0xFFFF; //count till max
|
||||
}
|
||||
|
||||
void RCC_DeInit(void)
|
||||
{
|
||||
/* Disable APB2 Peripheral Reset */
|
||||
RCC->APB2RSTR = 0x00000000;
|
||||
|
||||
/* Disable APB1 Peripheral Reset */
|
||||
RCC->APB1RSTR = 0x00000000;
|
||||
|
||||
/* FLITF and SRAM Clock ON */
|
||||
RCC->AHBENR = 0x00000014;
|
||||
|
||||
/* Disable APB2 Peripheral Clock */
|
||||
RCC->APB2ENR = 0x00000000;
|
||||
|
||||
/* Disable APB1 Peripheral Clock */
|
||||
RCC->APB1ENR = 0x00000000;
|
||||
|
||||
/* Set HSION bit */
|
||||
RCC->CR |= (u32)0x00000001;
|
||||
|
||||
/* Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0] and MCO[2:0] bits*/
|
||||
RCC->CFGR &= 0xF8FF0000;
|
||||
|
||||
/* Reset HSEON, CSSON and PLLON bits */
|
||||
RCC->CR &= 0xFEF6FFFF;
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
RCC->CR &= 0xFFFBFFFF;
|
||||
|
||||
/* Reset PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE bits */
|
||||
RCC->CFGR &= 0xFF80FFFF;
|
||||
|
||||
/* Disable all interrupts */
|
||||
RCC->CIR = 0x009F0000;
|
||||
}
|
||||
|
||||
void disableInterrupts()
|
||||
{
|
||||
__disable_irq() ;
|
||||
NVIC_DisableIRQ(USART1_IRQn) ;
|
||||
NVIC_DisableIRQ(USART2_IRQn) ;
|
||||
NVIC_DisableIRQ(USART3_IRQn) ;
|
||||
NVIC_DisableIRQ(TIM1_BRK_IRQn) ;
|
||||
NVIC_DisableIRQ(TIM1_UP_IRQn) ;
|
||||
NVIC_DisableIRQ(TIM1_TRG_COM_IRQn) ;
|
||||
NVIC_DisableIRQ(TIM1_CC_IRQn) ;
|
||||
NVIC_DisableIRQ(TIM3_IRQn) ;
|
||||
NVIC_DisableIRQ(TIM4_IRQn) ;
|
||||
NVIC_DisableIRQ(ADC1_2_IRQn) ;
|
||||
SysTick->CTRL = 0 ;
|
||||
}
|
||||
|
||||
|
||||
static void executeApp()
|
||||
{
|
||||
// Expected at 0x08002000
|
||||
uint32_t *p ;
|
||||
|
||||
// Disable all peripheral clocks
|
||||
// Disable used PLL
|
||||
// Disable interrupts
|
||||
// Clear pending interrupts
|
||||
|
||||
p = (uint32_t *) 0x08002000 ;
|
||||
|
||||
if ( *p == 0x20005000 )
|
||||
{
|
||||
|
||||
USART1->CR1 = 0 ;
|
||||
USART1->BRR = 0 ;
|
||||
USART2->CR1 = 0 ;
|
||||
USART2->BRR = 0 ;
|
||||
USART3->CR1 = 0 ;
|
||||
USART3->BRR = 0 ;
|
||||
(void) USART2->SR ;
|
||||
(void) USART2->DR ;
|
||||
(void) USART1->SR ;
|
||||
(void) USART1->DR ;
|
||||
USART1->SR = 0 ;
|
||||
USART2->SR = 0 ;
|
||||
USART3->SR = 0 ;
|
||||
|
||||
RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN ; // Disable clock
|
||||
RCC->APB1ENR &= ~RCC_APB1ENR_USART3EN ; // Disable clock
|
||||
|
||||
TIM2->CR1 = 0 ;
|
||||
|
||||
disableInterrupts() ;
|
||||
|
||||
NVIC->ICER[0] = 0xFFFFFFFF ;
|
||||
NVIC->ICER[1] = 0xFFFFFFFF ;
|
||||
NVIC->ICER[2] = 0xFFFFFFFF ;
|
||||
NVIC->ICPR[0] = 0xFFFFFFFF ;
|
||||
NVIC->ICPR[1] = 0xFFFFFFFF ;
|
||||
NVIC->ICPR[2] = 0xFFFFFFFF ;
|
||||
|
||||
RCC_DeInit() ;
|
||||
SysTick->CTRL = 0 ;
|
||||
SysTick->LOAD = 0 ;
|
||||
SysTick->VAL = 0 ;
|
||||
|
||||
asm(" mov.w r1, #134217728"); // 0x8000000
|
||||
asm(" add.w r1, #8192"); // 0x2000
|
||||
|
||||
asm(" movw r0, #60680"); // 0xED08
|
||||
asm(" movt r0, #57344"); // 0xE000
|
||||
asm(" str r1, [r0, #0]"); // Set the VTOR
|
||||
|
||||
asm("ldr r0, [r1, #0]"); // Stack pointer value
|
||||
asm("msr msp, r0"); // Set it
|
||||
asm("ldr r0, [r1, #4]"); // Reset address
|
||||
asm("mov.w r1, #1");
|
||||
asm("orr r0, r1"); // Set lsbit
|
||||
asm("bx r0"); // Execute application
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint16_t test0()
|
||||
{
|
||||
if ( USART2->SR & USART_SR_RXNE )
|
||||
{
|
||||
return USART2->DR ;
|
||||
}
|
||||
return 0xFFFF ;
|
||||
}
|
||||
|
||||
static uint16_t test1()
|
||||
{
|
||||
if ( USART1->SR & USART_SR_RXNE )
|
||||
{
|
||||
return USART1->DR ;
|
||||
}
|
||||
return 0xFFFF ;
|
||||
}
|
||||
|
||||
uint8_t getch1()
|
||||
{
|
||||
while ( ( USART1->SR & USART_SR_RXNE ) == 0 )
|
||||
{
|
||||
IWDG->KR = 0xAAAA ; // reload
|
||||
if ( TIM2->SR & TIM_SR_UIF )
|
||||
{
|
||||
TIM2->SR &= ~TIM_SR_UIF ;
|
||||
GPIOA->ODR ^= 0x0002 ;
|
||||
}
|
||||
// wait
|
||||
}
|
||||
return USART1->DR ;
|
||||
}
|
||||
|
||||
uint8_t getch()
|
||||
{
|
||||
if ( Port )
|
||||
{
|
||||
return getch1() ;
|
||||
}
|
||||
while ( ( USART2->SR & USART_SR_RXNE ) == 0 )
|
||||
{
|
||||
IWDG->KR = 0xAAAA ; // reload
|
||||
if ( TIM2->SR & TIM_SR_UIF )
|
||||
{
|
||||
TIM2->SR &= ~TIM_SR_UIF ;
|
||||
GPIOA->ODR ^= 0x0002 ;
|
||||
}
|
||||
// wait
|
||||
}
|
||||
return USART2->DR ;
|
||||
}
|
||||
|
||||
void putch( uint8_t byte )
|
||||
{
|
||||
if ( Port )
|
||||
{
|
||||
while ( ( USART1->SR & USART_SR_TXE ) == 0 )
|
||||
{
|
||||
// wait
|
||||
}
|
||||
USART1->DR = byte ;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( ( USART3->SR & USART_SR_TXE ) == 0 )
|
||||
{
|
||||
// wait
|
||||
}
|
||||
USART3->DR = byte ;
|
||||
}
|
||||
}
|
||||
|
||||
static void serialInit()
|
||||
{
|
||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN ; // Enable clock
|
||||
RCC->APB1ENR |= RCC_APB1ENR_USART2EN ; // Enable clock
|
||||
RCC->APB1ENR |= RCC_APB1ENR_USART3EN ; // Enable clock
|
||||
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN ;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN ;
|
||||
|
||||
GPIOA->CRH = GPIOA->CRH & 0xFFFFFF0F | 0x00000090 ; // PA9
|
||||
// USART2 TX is PA2, only Rx used
|
||||
// USART3 TX is PB10, only Tx used
|
||||
GPIOB->CRH = GPIOB->CRH & 0xFFFFF0FF | 0x00000900 ; // PB10
|
||||
|
||||
USART1->BRR = 72000000 / 57600 ;
|
||||
USART1->CR1 = 0x200C ;
|
||||
USART2->BRR = 36000000 / 57600 ;
|
||||
USART2->CR1 = 0x200C ;
|
||||
USART2->CR2 = 0 ;
|
||||
USART2->CR3 = 0 ;
|
||||
USART3->BRR = 36000000 / 57600 ;
|
||||
USART3->CR1 = 0x200C ;
|
||||
USART3->CR2 = 0 ;
|
||||
USART3->CR3 = 0 ;
|
||||
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
serialInit() ;
|
||||
start_timer2() ;//0.5us
|
||||
FLASH_Unlock() ;
|
||||
GPIOA->BSRR = 0x000000F1 ;
|
||||
GPIOA->CRL = GPIOA->CRL & 0x0000FF00 | 0x88880028 ; // LED and inputs
|
||||
|
||||
// Input with pullup, 1000B, and set the ODR bit
|
||||
|
||||
GPIOB->CRL = GPIOB->CRL & 0xFFFF0F0F | 0x00002020 ; // PB1 and PB3, invert controls
|
||||
GPIOB->BRR = 0x00000008 ;
|
||||
GPIOB->BSRR = 0x00000002 ;
|
||||
|
||||
}
|
||||
|
||||
void verifySpace()
|
||||
{
|
||||
if ( getch() != CRC_EOP)
|
||||
{
|
||||
NotSynced = 1 ;
|
||||
return ;
|
||||
|
||||
}
|
||||
putch(STK_INSYNC);
|
||||
}
|
||||
|
||||
void bgetNch(uint8_t count)
|
||||
{
|
||||
do
|
||||
{
|
||||
getch() ;
|
||||
} while (--count) ;
|
||||
verifySpace() ;
|
||||
}
|
||||
|
||||
void loader( uint32_t check )
|
||||
{
|
||||
uint8_t ch ;
|
||||
uint8_t GPIOR0 ;
|
||||
uint32_t address = 0 ;
|
||||
uint8_t lastCh ;
|
||||
|
||||
ResetReason = RCC->CSR ;
|
||||
RCC->CSR |= RCC_CSR_RMVF ;
|
||||
if ( ResetReason & RCC_CSR_SFTRSTF )
|
||||
{
|
||||
check = 0 ; // Stay in bootloader
|
||||
}
|
||||
|
||||
NVIC_DisableIRQ(TIM2_IRQn) ;
|
||||
if ( check )
|
||||
{
|
||||
TIM2->CNT = 0 ;
|
||||
TIM2->SR &= ~TIM_SR_UIF ;
|
||||
while ( ( TIM2->SR & TIM_SR_UIF ) == 0 )
|
||||
{
|
||||
// wait
|
||||
}
|
||||
TIM2->SR &= ~TIM_SR_UIF ;
|
||||
|
||||
while ( ( TIM2->SR & TIM_SR_UIF ) == 0 )
|
||||
{
|
||||
// wait
|
||||
}
|
||||
TIM2->SR &= ~TIM_SR_UIF ;
|
||||
|
||||
ch = GPIOA->IDR & 0xF1 ;
|
||||
if ( ch != 0xF0 )
|
||||
{
|
||||
return ;
|
||||
}
|
||||
}
|
||||
disableInterrupts() ;
|
||||
|
||||
NotSynced = 1 ;
|
||||
lastCh = 0 ;
|
||||
for (;;)
|
||||
{
|
||||
while ( NotSynced )
|
||||
{
|
||||
uint16_t data ;
|
||||
|
||||
data = test0() ;
|
||||
if ( data != 0xFFFF )
|
||||
{
|
||||
ch = data ;
|
||||
if ( ( lastCh == STK_GET_SYNC ) && ( ch == CRC_EOP ) )
|
||||
{
|
||||
NotSynced = 0 ;
|
||||
Port = 0 ;
|
||||
break ;
|
||||
}
|
||||
lastCh = ch ;
|
||||
}
|
||||
data = test1() ;
|
||||
if ( data != 0xFFFF )
|
||||
{
|
||||
ch = data ;
|
||||
if ( ( lastCh == STK_GET_SYNC ) && ( ch == CRC_EOP ) )
|
||||
{
|
||||
NotSynced = 0 ;
|
||||
Port = 1 ;
|
||||
break ;
|
||||
}
|
||||
lastCh = ch ;
|
||||
}
|
||||
IWDG->KR = 0xAAAA ; // reload
|
||||
if ( TIM2->SR & TIM_SR_UIF )
|
||||
{
|
||||
TIM2->SR &= ~TIM_SR_UIF ;
|
||||
GPIOA->ODR ^= 0x0002 ;
|
||||
}
|
||||
}
|
||||
|
||||
/* get character from UART */
|
||||
ch = getch() ;
|
||||
if(ch == STK_GET_PARAMETER)
|
||||
{
|
||||
GPIOR0 = getch() ;
|
||||
verifySpace() ;
|
||||
if (GPIOR0 == 0x82)
|
||||
{
|
||||
putch(OPTIBOOT_MINVER) ;
|
||||
}
|
||||
else if (GPIOR0 == 0x81)
|
||||
{
|
||||
putch(OPTIBOOT_MAJVER) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* GET PARAMETER returns a generic 0x03 reply for
|
||||
* other parameters - enough to keep Avrdude happy
|
||||
*/
|
||||
putch(0x03) ;
|
||||
}
|
||||
}
|
||||
else if(ch == STK_SET_DEVICE)
|
||||
{
|
||||
// SET DEVICE is ignored
|
||||
bgetNch(20) ;
|
||||
}
|
||||
else if(ch == STK_SET_DEVICE_EXT)
|
||||
{
|
||||
// SET DEVICE EXT is ignored
|
||||
bgetNch(5);
|
||||
}
|
||||
else if(ch == STK_LOAD_ADDRESS)
|
||||
{
|
||||
// LOAD ADDRESS
|
||||
uint16_t newAddress ;
|
||||
newAddress = getch() ;
|
||||
newAddress = (newAddress & 0xff) | (getch() << 8);
|
||||
address = newAddress ; // Convert from word address to byte address
|
||||
address <<= 1 ;
|
||||
verifySpace() ;
|
||||
}
|
||||
else if(ch == STK_UNIVERSAL)
|
||||
{
|
||||
// UNIVERSAL command is ignored
|
||||
bgetNch(4) ;
|
||||
putch(0x00) ;
|
||||
}
|
||||
else if(ch == STK_PROG_PAGE)
|
||||
{
|
||||
// PROGRAM PAGE - we support flash programming only, not EEPROM
|
||||
uint8_t *bufPtr;
|
||||
uint16_t addrPtr;
|
||||
uint16_t length ;
|
||||
uint16_t count ;
|
||||
uint16_t data ;
|
||||
uint8_t *memAddress ;
|
||||
length = getch() << 8 ; /* getlen() */
|
||||
length |= getch() ;
|
||||
getch() ; // discard flash/eeprom byte
|
||||
// While that is going on, read in page contents
|
||||
count = length ;
|
||||
bufPtr = Buff;
|
||||
do
|
||||
{
|
||||
*bufPtr++ = getch() ;
|
||||
}
|
||||
while (--count) ;
|
||||
if ( length & 1 )
|
||||
{
|
||||
*bufPtr = 0xFF ;
|
||||
}
|
||||
count = length ;
|
||||
count += 1 ;
|
||||
count /= 2 ;
|
||||
memAddress = (uint8_t *)(address + 0x08000000) ;
|
||||
|
||||
if ( (uint32_t)memAddress < 0x08020000 )
|
||||
{
|
||||
// Read command terminator, start reply
|
||||
verifySpace();
|
||||
|
||||
if ( (uint32_t)memAddress >= 0x08002000 )
|
||||
{
|
||||
if ( ((uint32_t)memAddress & 0x000003FF) == 0 )
|
||||
{
|
||||
// At page start so erase it
|
||||
FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
|
||||
FLASH_ErasePage( (uint32_t)memAddress ) ;
|
||||
}
|
||||
bufPtr = Buff;
|
||||
while ( count )
|
||||
{
|
||||
data = *bufPtr++ ;
|
||||
data |= *bufPtr++ << 8 ;
|
||||
FLASH_ProgramHalfWord( (uint32_t)memAddress, data ) ;
|
||||
memAddress += 2 ;
|
||||
count -= 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
verifySpace();
|
||||
}
|
||||
}
|
||||
else if(ch == STK_READ_PAGE)
|
||||
{
|
||||
uint16_t length ;
|
||||
uint8_t xlen ;
|
||||
uint8_t *memAddress ;
|
||||
memAddress = (uint8_t *)(address + 0x08000000) ;
|
||||
// READ PAGE - we only read flash
|
||||
xlen = getch() ; /* getlen() */
|
||||
length = getch() | (xlen << 8 ) ;
|
||||
getch() ;
|
||||
verifySpace() ;
|
||||
do
|
||||
{
|
||||
putch( *memAddress++) ;
|
||||
}
|
||||
while (--length) ;
|
||||
|
||||
|
||||
}
|
||||
else if(ch == STK_READ_SIGN)
|
||||
{
|
||||
// READ SIGN - return what Avrdude wants to hear
|
||||
verifySpace() ;
|
||||
putch(SIGNATURE_0) ;
|
||||
if ( Port )
|
||||
{
|
||||
putch(SIGNATURE_3) ;
|
||||
putch(SIGNATURE_4) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
putch(SIGNATURE_1) ;
|
||||
putch(SIGNATURE_2) ;
|
||||
}
|
||||
}
|
||||
else if (ch == STK_LEAVE_PROGMODE)
|
||||
{ /* 'Q' */
|
||||
// Adaboot no-wait mod
|
||||
|
||||
// watchdogConfig(WATCHDOG_16MS);
|
||||
|
||||
verifySpace() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This covers the response to commands like STK_ENTER_PROGMODE
|
||||
verifySpace() ;
|
||||
}
|
||||
if ( NotSynced )
|
||||
{
|
||||
continue ;
|
||||
}
|
||||
putch(STK_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
loader(1) ;
|
||||
|
||||
// Execute loaded application
|
||||
executeApp() ;
|
||||
|
||||
loader(0) ;
|
||||
|
||||
// The next bit not really needed as loader(0) doesn't return
|
||||
for(;;)
|
||||
{
|
||||
if ( TIM2->SR & TIM_SR_UIF )
|
||||
{
|
||||
TIM2->SR &= ~TIM_SR_UIF ;
|
||||
if ( ++LongCount > 4 )
|
||||
{
|
||||
GPIOA->ODR ^= 0x0002 ;
|
||||
LongCount = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1818
StmBoot/core_cm3.h
Normal file
1818
StmBoot/core_cm3.h
Normal file
File diff suppressed because it is too large
Load Diff
24
StmBoot/how to use.txt
Normal file
24
StmBoot/how to use.txt
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
To use this bootloader, you will need first to flash it to the module.
|
||||
Download the source files from the Github repository. Double click on the StmBoot.ino file to open the Arduino IDE. I'm assuming you already have this configured for building for the STM processor as it is needed for the Multi code.
|
||||
In "Tools", set the board to Generic STM32F013C series, the variant to 128K flash, and the Upload method to "Serial".
|
||||
|
||||
You will need to connect to the serial port of the board, using a FTDI, or similar, interface, and fit the link to make it boot in the inbuilt bootloader. Again, this is the same as used for flashing the Multi code.
|
||||
Apply power to the Multi board, and click "Upload" in the Arduino IDE. The code should be compiled and flashed to the board.
|
||||
|
||||
Next, build the Multi code for flashing using a bootloader, in "Tools", set the Upload method to STM32duino bootloader,
|
||||
then use the "Export compiled binary" option to build the Multi firmware. This will put a .bin file in the sketch directory, you may wish to rename the file to have a shorter filename.
|
||||
Copy this file to "FIRMWARE" directory of the SD card in your radio.
|
||||
|
||||
You will also need to update the ersky9x firmware on your radio with the P221 "e2" test version or higher.
|
||||
Start the radio in "maintenance mode", select "Update Multi", select the flashing options that depend on how your module is installed, and choose "Update".
|
||||
Select the file you put on the SD card and confirm to start flashing.
|
||||
|
||||
If you build using the "multiprotocol.ino" file I posted above, with "CHECK_FOR_BOOTLOADER" uncommented in _config.h, then flashing again later should work in the same way.
|
||||
If the Multi code doesn't have this bootlaoder check in, then you need the dial set to 0 and have the bind button pressed at power on to force the bootloader to run.
|
||||
|
||||
This bootloader will also work if you use the serial port, however you need to do some fiddling.
|
||||
First you need a .hex file of the Multi code, which you need to edit so it loads at address 2000 instead of 08002000.
|
||||
Then you use AvrDude set to use an ATMEGA128 and an Arduino programmer at 57600 baud to do the flashing.
|
||||
|
||||
Mike
|
39
StmBoot/stk500.h
Normal file
39
StmBoot/stk500.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* STK500 constants list, from AVRDUDE */
|
||||
#define STK_OK 0x10
|
||||
#define STK_FAILED 0x11 // Not used
|
||||
#define STK_UNKNOWN 0x12 // Not used
|
||||
#define STK_NODEVICE 0x13 // Not used
|
||||
#define STK_INSYNC 0x14 // ' '
|
||||
#define STK_NOSYNC 0x15 // Not used
|
||||
#define ADC_CHANNEL_ERROR 0x16 // Not used
|
||||
#define ADC_MEASURE_OK 0x17 // Not used
|
||||
#define PWM_CHANNEL_ERROR 0x18 // Not used
|
||||
#define PWM_ADJUST_OK 0x19 // Not used
|
||||
#define CRC_EOP 0x20 // 'SPACE'
|
||||
#define STK_GET_SYNC 0x30 // '0'
|
||||
#define STK_GET_SIGN_ON 0x31 // '1'
|
||||
#define STK_SET_PARAMETER 0x40 // '@'
|
||||
#define STK_GET_PARAMETER 0x41 // 'A'
|
||||
#define STK_SET_DEVICE 0x42 // 'B'
|
||||
#define STK_SET_DEVICE_EXT 0x45 // 'E'
|
||||
#define STK_ENTER_PROGMODE 0x50 // 'P'
|
||||
#define STK_LEAVE_PROGMODE 0x51 // 'Q'
|
||||
#define STK_CHIP_ERASE 0x52 // 'R'
|
||||
#define STK_CHECK_AUTOINC 0x53 // 'S'
|
||||
#define STK_LOAD_ADDRESS 0x55 // 'U'
|
||||
#define STK_UNIVERSAL 0x56 // 'V'
|
||||
#define STK_PROG_FLASH 0x60 // '`'
|
||||
#define STK_PROG_DATA 0x61 // 'a'
|
||||
#define STK_PROG_FUSE 0x62 // 'b'
|
||||
#define STK_PROG_LOCK 0x63 // 'c'
|
||||
#define STK_PROG_PAGE 0x64 // 'd'
|
||||
#define STK_PROG_FUSE_EXT 0x65 // 'e'
|
||||
#define STK_READ_FLASH 0x70 // 'p'
|
||||
#define STK_READ_DATA 0x71 // 'q'
|
||||
#define STK_READ_FUSE 0x72 // 'r'
|
||||
#define STK_READ_LOCK 0x73 // 's'
|
||||
#define STK_READ_PAGE 0x74 // 't'
|
||||
#define STK_READ_SIGN 0x75 // 'u'
|
||||
#define STK_READ_OSCCAL 0x76 // 'v'
|
||||
#define STK_READ_FUSE_EXT 0x77 // 'w'
|
||||
#define STK_READ_OSCCAL_EXT 0x78 // 'x'
|
8359
StmBoot/stm32f10x.h
Normal file
8359
StmBoot/stm32f10x.h
Normal file
File diff suppressed because it is too large
Load Diff
911
StmBoot/stm32f10x_flash.cpp
Normal file
911
StmBoot/stm32f10x_flash.cpp
Normal file
@ -0,0 +1,911 @@
|
||||
/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
|
||||
* File Name : stm32f10x_flash.c
|
||||
* Author : MCD Application Team
|
||||
* Version : V1.0
|
||||
* Date : 10/08/2007
|
||||
* Description : This file provides all the FLASH firmware functions.
|
||||
********************************************************************************
|
||||
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
|
||||
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
|
||||
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
|
||||
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*******************************************************************************/
|
||||
|
||||
#define STM32F10X_CL
|
||||
#define _FLASH_PROG 1
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f10x_flash.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Flash Access Control Register bits */
|
||||
#define ACR_LATENCY_Mask ((u32)0x00000038)
|
||||
#define ACR_HLFCYA_Mask ((u32)0xFFFFFFF7)
|
||||
#define ACR_PRFTBE_Mask ((u32)0xFFFFFFEF)
|
||||
|
||||
#ifdef _FLASH_PROG
|
||||
/* Flash Access Control Register bits */
|
||||
#define ACR_PRFTBS_Mask ((u32)0x00000020)
|
||||
|
||||
/* Flash Control Register bits */
|
||||
#define CR_PG_Set ((u32)0x00000001)
|
||||
#define CR_PG_Reset ((u32)0x00001FFE)
|
||||
|
||||
#define CR_PER_Set ((u32)0x00000002)
|
||||
#define CR_PER_Reset ((u32)0x00001FFD)
|
||||
|
||||
#define CR_MER_Set ((u32)0x00000004)
|
||||
#define CR_MER_Reset ((u32)0x00001FFB)
|
||||
|
||||
#define CR_OPTPG_Set ((u32)0x00000010)
|
||||
#define CR_OPTPG_Reset ((u32)0x00001FEF)
|
||||
|
||||
#define CR_OPTER_Set ((u32)0x00000020)
|
||||
#define CR_OPTER_Reset ((u32)0x00001FDF)
|
||||
|
||||
#define CR_STRT_Set ((u32)0x00000040)
|
||||
|
||||
#define CR_LOCK_Set ((u32)0x00000080)
|
||||
|
||||
/* FLASH Mask */
|
||||
#define RDPRT_Mask ((u32)0x00000002)
|
||||
#define WRP0_Mask ((u32)0x000000FF)
|
||||
#define WRP1_Mask ((u32)0x0000FF00)
|
||||
#define WRP2_Mask ((u32)0x00FF0000)
|
||||
#define WRP3_Mask ((u32)0xFF000000)
|
||||
|
||||
/* FLASH Keys */
|
||||
#define RDP_Key ((u16)0x00A5)
|
||||
#define FLASH_KEY1 ((u32)0x45670123)
|
||||
#define FLASH_KEY2 ((u32)0xCDEF89AB)
|
||||
|
||||
/* Delay definition */
|
||||
#define EraseTimeout ((u32)0x00000FFF)
|
||||
#define ProgramTimeout ((u32)0x0000000F)
|
||||
#endif
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
#ifdef _FLASH_PROG
|
||||
static void delay(void);
|
||||
#endif
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_SetLatency
|
||||
* Description : Sets the code latency value.
|
||||
* Input : - FLASH_Latency: specifies the FLASH Latency value.
|
||||
* This parameter can be one of the following values:
|
||||
* - FLASH_Latency_0: FLASH Zero Latency cycle
|
||||
* - FLASH_Latency_1: FLASH One Latency cycle
|
||||
* - FLASH_Latency_2: FLASH Two Latency cycles
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_SetLatency(u32 FLASH_Latency)
|
||||
{
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_LATENCY(FLASH_Latency));
|
||||
|
||||
/* Sets the Latency value */
|
||||
FLASH->ACR &= ACR_LATENCY_Mask;
|
||||
FLASH->ACR |= FLASH_Latency;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_HalfCycleAccessCmd
|
||||
* Description : Enables or disables the Half cycle flash access.
|
||||
* Input : - FLASH_HalfCycle: specifies the FLASH Half cycle Access mode.
|
||||
* This parameter can be one of the following values:
|
||||
* - FLASH_HalfCycleAccess_Enable: FLASH Half Cycle Enable
|
||||
* - FLASH_HalfCycleAccess_Disable: FLASH Half Cycle Disable
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_HalfCycleAccessCmd(u32 FLASH_HalfCycleAccess)
|
||||
{
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_HALFCYCLEACCESS_STATE(FLASH_HalfCycleAccess));
|
||||
|
||||
/* Enable or disable the Half cycle access */
|
||||
FLASH->ACR &= ACR_HLFCYA_Mask;
|
||||
FLASH->ACR |= FLASH_HalfCycleAccess;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_PrefetchBufferCmd
|
||||
* Description : Enables or disables the Prefetch Buffer.
|
||||
* Input : - FLASH_PrefetchBuffer: specifies the Prefetch buffer status.
|
||||
* This parameter can be one of the following values:
|
||||
* - FLASH_PrefetchBuffer_Enable: FLASH Prefetch Buffer Enable
|
||||
* - FLASH_PrefetchBuffer_Disable: FLASH Prefetch Buffer Disable
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_PrefetchBufferCmd(u32 FLASH_PrefetchBuffer)
|
||||
{
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_PREFETCHBUFFER_STATE(FLASH_PrefetchBuffer));
|
||||
|
||||
/* Enable or disable the Prefetch Buffer */
|
||||
FLASH->ACR &= ACR_PRFTBE_Mask;
|
||||
FLASH->ACR |= FLASH_PrefetchBuffer;
|
||||
}
|
||||
|
||||
#ifdef _FLASH_PROG
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_Unlock
|
||||
* Description : Unlocks the FLASH Program Erase Controller.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_Unlock(void)
|
||||
{
|
||||
/* Authorize the FPEC Access */
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_Lock
|
||||
* Description : Locks the FLASH Program Erase Controller.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_Lock(void)
|
||||
{
|
||||
/* Set the Lock Bit to lock the FPEC and the FCR */
|
||||
FLASH->CR |= CR_LOCK_Set;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ErasePage
|
||||
* Description : Erases a specified FLASH page.
|
||||
* Input : - Page_Address: The page address to be erased.
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_ErasePage(u32 Page_Address)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_ADDRESS(Page_Address));
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the previous operation is completed, proceed to erase the page */
|
||||
FLASH->CR|= CR_PER_Set;
|
||||
FLASH->AR = Page_Address;
|
||||
FLASH->CR|= CR_STRT_Set;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the erase operation is completed, disable the PER Bit */
|
||||
FLASH->CR &= CR_PER_Reset;
|
||||
}
|
||||
}
|
||||
/* Return the Erase Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_EraseAllPages
|
||||
* Description : Erases all FLASH pages.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_EraseAllPages(void)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the previous operation is completed, proceed to erase all pages */
|
||||
FLASH->CR |= CR_MER_Set;
|
||||
FLASH->CR |= CR_STRT_Set;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the erase operation is completed, disable the MER Bit */
|
||||
FLASH->CR &= CR_MER_Reset;
|
||||
}
|
||||
}
|
||||
/* Return the Erase Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_EraseOptionBytes
|
||||
* Description : Erases the FLASH option bytes.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_EraseOptionBytes(void)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* Authorize the small information block programming */
|
||||
FLASH->OPTKEYR = FLASH_KEY1;
|
||||
FLASH->OPTKEYR = FLASH_KEY2;
|
||||
|
||||
/* if the previous operation is completed, proceed to erase the option bytes */
|
||||
FLASH->CR |= CR_OPTER_Set;
|
||||
FLASH->CR |= CR_STRT_Set;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the erase operation is completed, disable the OPTER Bit */
|
||||
FLASH->CR &= CR_OPTER_Reset;
|
||||
|
||||
/* Enable the Option Bytes Programming operation */
|
||||
FLASH->CR |= CR_OPTPG_Set;
|
||||
|
||||
/* Enable the readout access */
|
||||
OB->RDP= RDP_Key;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
FLASH->CR &= CR_OPTPG_Reset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status != FLASH_BUSY)
|
||||
{
|
||||
/* Disable the OPTPG Bit */
|
||||
FLASH->CR &= CR_OPTPG_Reset;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the erase status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ProgramWord
|
||||
* Description : Programs a word at a specified address.
|
||||
* Input : - Address: specifies the address to be programmed.
|
||||
* - Data: specifies the data to be programmed.
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_ProgramWord(u32 Address, u32 Data)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_ADDRESS(Address));
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the previous operation is completed, proceed to program the new first
|
||||
half word */
|
||||
FLASH->CR |= CR_PG_Set;
|
||||
|
||||
*(vu16*)Address = (u16)Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the previous operation is completed, proceed to program the new second
|
||||
half word */
|
||||
*(vu16*)(Address + 2) = Data >> 16;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* Disable the PG Bit */
|
||||
FLASH->CR &= CR_PG_Reset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status != FLASH_BUSY)
|
||||
{
|
||||
/* Disable the PG Bit */
|
||||
FLASH->CR &= CR_PG_Reset;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the Program Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ProgramHalfWord
|
||||
* Description : Programs a half word at a specified address.
|
||||
* Input : - Address: specifies the address to be programmed.
|
||||
* - Data: specifies the data to be programmed.
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_ProgramHalfWord(u32 Address, u16 Data)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_ADDRESS(Address));
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the previous operation is completed, proceed to program the new data */
|
||||
FLASH->CR |= CR_PG_Set;
|
||||
|
||||
*(vu16*)Address = Data;
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the program operation is completed, disable the PG Bit */
|
||||
FLASH->CR &= CR_PG_Reset;
|
||||
}
|
||||
}
|
||||
/* Return the Program Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ProgramOptionByteData
|
||||
* Description : Programs a half word at a specified Option Byte Data address.
|
||||
* Input : - Address: specifies the address to be programmed.
|
||||
* This parameter can be 0x1FFFF804 or 0x1FFFF806.
|
||||
* - Data: specifies the data to be programmed.
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_ProgramOptionByteData(u32 Address, u8 Data)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_OB_DATA_ADDRESS(Address));
|
||||
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* Authorize the small information block programming */
|
||||
FLASH->OPTKEYR = FLASH_KEY1;
|
||||
FLASH->OPTKEYR = FLASH_KEY2;
|
||||
|
||||
/* Enables the Option Bytes Programming operation */
|
||||
FLASH->CR |= CR_OPTPG_Set;
|
||||
*(vu16*)Address = Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
FLASH->CR &= CR_OPTPG_Reset;
|
||||
}
|
||||
}
|
||||
/* Return the Option Byte Data Program Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_EnableWriteProtection
|
||||
* Description : Write protects the desired pages
|
||||
* Input : - FLASH_Pages: specifies the address of the pages to be
|
||||
* write protected. This parameter can be:
|
||||
* - A value between FLASH_WRProt_Pages0to3 and
|
||||
* FLASH_WRProt_Pages124to127
|
||||
* - FLASH_WRProt_AllPages
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_EnableWriteProtection(u32 FLASH_Pages)
|
||||
{
|
||||
u16 WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF, WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF;
|
||||
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_WRPROT_PAGE(FLASH_Pages));
|
||||
|
||||
FLASH_Pages = (u32)(~FLASH_Pages);
|
||||
WRP0_Data = (vu16)(FLASH_Pages & WRP0_Mask);
|
||||
WRP1_Data = (vu16)((FLASH_Pages & WRP1_Mask) >> 8);
|
||||
WRP2_Data = (vu16)((FLASH_Pages & WRP2_Mask) >> 16);
|
||||
WRP3_Data = (vu16)((FLASH_Pages & WRP3_Mask) >> 24);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* Authorizes the small information block programming */
|
||||
FLASH->OPTKEYR = FLASH_KEY1;
|
||||
FLASH->OPTKEYR = FLASH_KEY2;
|
||||
FLASH->CR |= CR_OPTPG_Set;
|
||||
|
||||
if(WRP0_Data != 0xFF)
|
||||
{
|
||||
OB->WRP0 = WRP0_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
}
|
||||
if((status == FLASH_COMPLETE) && (WRP1_Data != 0xFF))
|
||||
{
|
||||
OB->WRP1 = WRP1_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
}
|
||||
|
||||
if((status == FLASH_COMPLETE) && (WRP2_Data != 0xFF))
|
||||
{
|
||||
OB->WRP2 = WRP2_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
}
|
||||
|
||||
if((status == FLASH_COMPLETE)&& (WRP3_Data != 0xFF))
|
||||
{
|
||||
OB->WRP3 = WRP3_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
}
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
FLASH->CR &= CR_OPTPG_Reset;
|
||||
}
|
||||
}
|
||||
/* Return the write protection operation Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ReadOutProtection
|
||||
* Description : Enables or disables the read out protection.
|
||||
* If the user has already programmed the other option bytes before
|
||||
* calling this function, he must re-program them since this
|
||||
* function erases all option bytes.
|
||||
* Input : - Newstate: new state of the ReadOut Protection.
|
||||
* This parameter can be: ENABLE or DISABLE.
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FUNCTIONAL_STATE(NewState));
|
||||
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* Authorizes the small information block programming */
|
||||
FLASH->OPTKEYR = FLASH_KEY1;
|
||||
FLASH->OPTKEYR = FLASH_KEY2;
|
||||
|
||||
FLASH->CR |= CR_OPTER_Set;
|
||||
FLASH->CR |= CR_STRT_Set;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* if the erase operation is completed, disable the OPTER Bit */
|
||||
FLASH->CR &= CR_OPTER_Reset;
|
||||
|
||||
/* Enable the Option Bytes Programming operation */
|
||||
FLASH->CR |= CR_OPTPG_Set;
|
||||
|
||||
if(NewState != DISABLE)
|
||||
{
|
||||
OB->RDP = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
OB->RDP = RDP_Key;
|
||||
}
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(EraseTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
FLASH->CR &= CR_OPTPG_Reset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* Disable the OPTER Bit */
|
||||
FLASH->CR &= CR_OPTER_Reset;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the protection operation Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_UserOptionByteConfig
|
||||
* Description : Programs the FLASH User Option Byte: IWDG_SW / RST_STOP /
|
||||
* RST_STDBY.
|
||||
* Input : - OB_IWDG: Selects the IWDG mode
|
||||
* This parameter can be one of the following values:
|
||||
* - OB_IWDG_SW: Software IWDG selected
|
||||
* - OB_IWDG_HW: Hardware IWDG selected
|
||||
* - OB_STOP: Reset event when entering STOP mode.
|
||||
* This parameter can be one of the following values:
|
||||
* - OB_STOP_NoRST: No reset generated when entering in STOP
|
||||
* - OB_STOP_RST: Reset generated when entering in STOP
|
||||
* - OB_STDBY: Reset event when entering Standby mode.
|
||||
* This parameter can be one of the following values:
|
||||
* - OB_STDBY_NoRST: No reset generated when entering in STANDBY
|
||||
* - OB_STDBY_RST: Reset generated when entering in STANDBY
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_UserOptionByteConfig(u16 OB_IWDG, u16 OB_STOP, u16 OB_STDBY)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_OB_IWDG_SOURCE(OB_IWDG));
|
||||
// assert_param(IS_OB_STOP_SOURCE(OB_STOP));
|
||||
// assert_param(IS_OB_STDBY_SOURCE(OB_STDBY));
|
||||
|
||||
/* Authorize the small information block programming */
|
||||
FLASH->OPTKEYR = FLASH_KEY1;
|
||||
FLASH->OPTKEYR = FLASH_KEY2;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status == FLASH_COMPLETE)
|
||||
{
|
||||
/* Enable the Option Bytes Programming operation */
|
||||
FLASH->CR |= CR_OPTPG_Set;
|
||||
|
||||
OB->USER = ( OB_IWDG | OB_STOP |OB_STDBY) | (u16)0xF8;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
|
||||
if(status != FLASH_BUSY)
|
||||
{
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
FLASH->CR &= CR_OPTPG_Reset;
|
||||
}
|
||||
}
|
||||
/* Return the Option Byte program Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_GetUserOptionByte
|
||||
* Description : Returns the FLASH User Option Bytes values.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : The FLASH User Option Bytes values:IWDG_SW(Bit0), RST_STOP(Bit1)
|
||||
* and RST_STDBY(Bit2).
|
||||
*******************************************************************************/
|
||||
u32 FLASH_GetUserOptionByte(void)
|
||||
{
|
||||
/* Return the User Option Byte */
|
||||
return (u32)(FLASH->OBR >> 2);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_GetWriteProtectionOptionByte
|
||||
* Description : Returns the FLASH Write Protection Option Bytes Register value.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : The FLASH Write Protection Option Bytes Register value
|
||||
*******************************************************************************/
|
||||
u32 FLASH_GetWriteProtectionOptionByte(void)
|
||||
{
|
||||
/* Return the Falsh write protection Register value */
|
||||
return (u32)(FLASH->WRPR);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_GetReadOutProtectionStatus
|
||||
* Description : Checks whether the FLASH Read Out Protection Status is set
|
||||
* or not.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : FLASH ReadOut Protection Status(SET or RESET)
|
||||
*******************************************************************************/
|
||||
FlagStatus FLASH_GetReadOutProtectionStatus(void)
|
||||
{
|
||||
FlagStatus readoutstatus = RESET;
|
||||
|
||||
if ((FLASH->OBR & RDPRT_Mask) != (u32)RESET)
|
||||
{
|
||||
readoutstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
readoutstatus = RESET;
|
||||
}
|
||||
return readoutstatus;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_GetPrefetchBufferStatus
|
||||
* Description : Checks whether the FLASH Prefetch Buffer status is set or not.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : FLASH Prefetch Buffer Status (SET or RESET).
|
||||
*******************************************************************************/
|
||||
FlagStatus FLASH_GetPrefetchBufferStatus(void)
|
||||
{
|
||||
FlagStatus bitstatus = RESET;
|
||||
|
||||
if ((FLASH->ACR & ACR_PRFTBS_Mask) != (u32)RESET)
|
||||
{
|
||||
bitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitstatus = RESET;
|
||||
}
|
||||
/* Return the new state of FLASH Prefetch Buffer Status (SET or RESET) */
|
||||
return bitstatus;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ITConfig
|
||||
* Description : Enables or disables the specified FLASH interrupts.
|
||||
* Input : - FLASH_IT: specifies the FLASH interrupt sources to be
|
||||
* enabled or disabled.
|
||||
* This parameter can be any combination of the following values:
|
||||
* - FLASH_IT_ERROR: FLASH Error Interrupt
|
||||
* - FLASH_IT_EOP: FLASH end of operation Interrupt
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_ITConfig(u16 FLASH_IT, FunctionalState NewState)
|
||||
{
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_IT(FLASH_IT));
|
||||
// assert_param(IS_FUNCTIONAL_STATE(NewState));
|
||||
|
||||
if(NewState != DISABLE)
|
||||
{
|
||||
/* Enable the interrupt sources */
|
||||
FLASH->CR |= FLASH_IT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the interrupt sources */
|
||||
FLASH->CR &= ~(u32)FLASH_IT;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_GetFlagStatus
|
||||
* Description : Checks whether the specified FLASH flag is set or not.
|
||||
* Input : - FLASH_FLAG: specifies the FLASH flag to check.
|
||||
* This parameter can be one of the following values:
|
||||
* - FLASH_FLAG_BSY: FLASH Busy flag
|
||||
* - FLASH_FLAG_PGERR: FLASH Program error flag
|
||||
* - FLASH_FLAG_WRPRTERR: FLASH Write protected error flag
|
||||
* - FLASH_FLAG_EOP: FLASH End of Operation flag
|
||||
* - FLASH_FLAG_OPTERR: FLASH Option Byte error flag
|
||||
* Output : None
|
||||
* Return : The new state of FLASH_FLAG (SET or RESET).
|
||||
*******************************************************************************/
|
||||
FlagStatus FLASH_GetFlagStatus(u16 FLASH_FLAG)
|
||||
{
|
||||
FlagStatus bitstatus = RESET;
|
||||
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)) ;
|
||||
|
||||
if(FLASH_FLAG == FLASH_FLAG_OPTERR)
|
||||
{
|
||||
if((FLASH->OBR & FLASH_FLAG_OPTERR) != (u32)RESET)
|
||||
{
|
||||
bitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitstatus = RESET;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((FLASH->SR & FLASH_FLAG) != (u32)RESET)
|
||||
{
|
||||
bitstatus = SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitstatus = RESET;
|
||||
}
|
||||
}
|
||||
/* Return the new state of FLASH_FLAG (SET or RESET) */
|
||||
return bitstatus;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_ClearFlag
|
||||
* Description : Clears the FLASH’s pending flags.
|
||||
* Input : - FLASH_FLAG: specifies the FLASH flags to clear.
|
||||
* This parameter can be any combination of the following values:
|
||||
* - FLASH_FLAG_BSY: FLASH Busy flag
|
||||
* - FLASH_FLAG_PGERR: FLASH Program error flag
|
||||
* - FLASH_FLAG_WRPRTERR: FLASH Write protected error flag
|
||||
* - FLASH_FLAG_EOP: FLASH End of Operation flag
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void FLASH_ClearFlag(u16 FLASH_FLAG)
|
||||
{
|
||||
/* Check the parameters */
|
||||
// assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)) ;
|
||||
|
||||
/* Clear the flags */
|
||||
FLASH->SR = FLASH_FLAG;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_GetStatus
|
||||
* Description : Returns the FLASH Status.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_GetStatus(void)
|
||||
{
|
||||
FLASH_Status flashstatus = FLASH_COMPLETE;
|
||||
|
||||
if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY)
|
||||
{
|
||||
flashstatus = FLASH_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FLASH->SR & FLASH_FLAG_PGERR)
|
||||
{
|
||||
flashstatus = FLASH_ERROR_PG;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FLASH->SR & FLASH_FLAG_WRPRTERR)
|
||||
{
|
||||
flashstatus = FLASH_ERROR_WRP;
|
||||
}
|
||||
else
|
||||
{
|
||||
flashstatus = FLASH_COMPLETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the Flash Status */
|
||||
return flashstatus;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : FLASH_WaitForLastOperation
|
||||
* Description : Waits for a Flash operation to complete or a TIMEOUT to occur.
|
||||
* Input : - Timeout: FLASH progamming Timeout
|
||||
* Output : None
|
||||
* Return : FLASH Status: The returned value can be: FLASH_BUSY,
|
||||
* FLASH_ERROR_PG or FLASH_ERROR_WRP or FLASH_COMPLETE or
|
||||
* FLASH_TIMEOUT.
|
||||
*******************************************************************************/
|
||||
FLASH_Status FLASH_WaitForLastOperation(u32 Timeout)
|
||||
{
|
||||
FLASH_Status status = FLASH_COMPLETE;
|
||||
|
||||
/* Check for the Flash Status */
|
||||
status = FLASH_GetStatus();
|
||||
|
||||
/* Wait for a Flash operation to complete or a TIMEOUT to occur */
|
||||
while((status == FLASH_BUSY) && (Timeout != 0x00))
|
||||
{
|
||||
delay();
|
||||
status = FLASH_GetStatus();
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if(Timeout == 0x00 )
|
||||
{
|
||||
status = FLASH_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Return the operation status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : delay
|
||||
* Description : Inserts a time delay.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
static void delay(void)
|
||||
{
|
||||
vu32 i = 0;
|
||||
|
||||
for(i = 0xFF; i != 0; i--)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/
|
173
StmBoot/stm32f10x_flash.h
Normal file
173
StmBoot/stm32f10x_flash.h
Normal file
@ -0,0 +1,173 @@
|
||||
/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
|
||||
* File Name : stm32f10x_flash.h
|
||||
* Author : MCD Application Team
|
||||
* Version : V1.0
|
||||
* Date : 10/08/2007
|
||||
* Description : This file contains all the functions prototypes for the
|
||||
* FLASH firmware library.
|
||||
********************************************************************************
|
||||
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
|
||||
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
|
||||
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
|
||||
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*******************************************************************************/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F10x_FLASH_H
|
||||
#define __STM32F10x_FLASH_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f10x.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
#ifdef _FLASH_PROG
|
||||
/* FLASH Status */
|
||||
typedef enum
|
||||
{
|
||||
FLASH_BUSY = 1,
|
||||
FLASH_ERROR_PG,
|
||||
FLASH_ERROR_WRP,
|
||||
FLASH_COMPLETE,
|
||||
FLASH_TIMEOUT
|
||||
}FLASH_Status;
|
||||
#endif
|
||||
|
||||
/* Flash Latency -------------------------------------------------------------*/
|
||||
#define FLASH_Latency_0 ((u32)0x00000000) /* FLASH Zero Latency cycle */
|
||||
#define FLASH_Latency_1 ((u32)0x00000001) /* FLASH One Latency cycle */
|
||||
#define FLASH_Latency_2 ((u32)0x00000002) /* FLASH Two Latency cycles */
|
||||
|
||||
#define IS_FLASH_LATENCY(LATENCY) ((LATENCY == FLASH_Latency_0) || \
|
||||
(LATENCY == FLASH_Latency_1) || \
|
||||
(LATENCY == FLASH_Latency_2))
|
||||
|
||||
/* Half Cycle Enable/Disable -------------------------------------------------*/
|
||||
#define FLASH_HalfCycleAccess_Enable ((u32)0x00000008) /* FLASH Half Cycle Enable */
|
||||
#define FLASH_HalfCycleAccess_Disable ((u32)0x00000000) /* FLASH Half Cycle Disable */
|
||||
|
||||
#define IS_FLASH_HALFCYCLEACCESS_STATE(STATE) ((STATE == FLASH_HalfCycleAccess_Enable) || \
|
||||
(STATE == FLASH_HalfCycleAccess_Disable))
|
||||
|
||||
|
||||
/* Prefetch Buffer Enable/Disable --------------------------------------------*/
|
||||
#define FLASH_PrefetchBuffer_Enable ((u32)0x00000010) /* FLASH Prefetch Buffer Enable */
|
||||
#define FLASH_PrefetchBuffer_Disable ((u32)0x00000000) /* FLASH Prefetch Buffer Disable */
|
||||
|
||||
#define IS_FLASH_PREFETCHBUFFER_STATE(STATE) ((STATE == FLASH_PrefetchBuffer_Enable) || \
|
||||
(STATE == FLASH_PrefetchBuffer_Disable))
|
||||
|
||||
#ifdef _FLASH_PROG
|
||||
/* Option Bytes Write Protection ---------------------------------------------*/
|
||||
#define FLASH_WRProt_Pages0to3 ((u32)0x00000001) /* Write protection of page 0 to 3 */
|
||||
#define FLASH_WRProt_Pages4to7 ((u32)0x00000002) /* Write protection of page 4 to 7 */
|
||||
#define FLASH_WRProt_Pages8to11 ((u32)0x00000004) /* Write protection of page 8 to 11 */
|
||||
#define FLASH_WRProt_Pages12to15 ((u32)0x00000008) /* Write protection of page 12 to 15 */
|
||||
#define FLASH_WRProt_Pages16to19 ((u32)0x00000010) /* Write protection of page 16 to 19 */
|
||||
#define FLASH_WRProt_Pages20to23 ((u32)0x00000020) /* Write protection of page 20 to 23 */
|
||||
#define FLASH_WRProt_Pages24to27 ((u32)0x00000040) /* Write protection of page 24 to 27 */
|
||||
#define FLASH_WRProt_Pages28to31 ((u32)0x00000080) /* Write protection of page 28 to 31 */
|
||||
#define FLASH_WRProt_Pages32to35 ((u32)0x00000100) /* Write protection of page 32 to 35 */
|
||||
#define FLASH_WRProt_Pages36to39 ((u32)0x00000200) /* Write protection of page 36 to 39 */
|
||||
#define FLASH_WRProt_Pages40to43 ((u32)0x00000400) /* Write protection of page 40 to 43 */
|
||||
#define FLASH_WRProt_Pages44to47 ((u32)0x00000800) /* Write protection of page 44 to 47 */
|
||||
#define FLASH_WRProt_Pages48to51 ((u32)0x00001000) /* Write protection of page 48 to 51 */
|
||||
#define FLASH_WRProt_Pages52to55 ((u32)0x00002000) /* Write protection of page 52 to 55 */
|
||||
#define FLASH_WRProt_Pages56to59 ((u32)0x00004000) /* Write protection of page 56 to 59 */
|
||||
#define FLASH_WRProt_Pages60to63 ((u32)0x00008000) /* Write protection of page 60 to 63 */
|
||||
#define FLASH_WRProt_Pages64to67 ((u32)0x00010000) /* Write protection of page 64 to 67 */
|
||||
#define FLASH_WRProt_Pages68to71 ((u32)0x00020000) /* Write protection of page 68 to 71 */
|
||||
#define FLASH_WRProt_Pages72to75 ((u32)0x00040000) /* Write protection of page 72 to 75 */
|
||||
#define FLASH_WRProt_Pages76to79 ((u32)0x00080000) /* Write protection of page 76 to 79 */
|
||||
#define FLASH_WRProt_Pages80to83 ((u32)0x00100000) /* Write protection of page 80 to 83 */
|
||||
#define FLASH_WRProt_Pages84to87 ((u32)0x00200000) /* Write protection of page 84 to 87 */
|
||||
#define FLASH_WRProt_Pages88to91 ((u32)0x00400000) /* Write protection of page 88 to 91 */
|
||||
#define FLASH_WRProt_Pages92to95 ((u32)0x00800000) /* Write protection of page 92 to 95 */
|
||||
#define FLASH_WRProt_Pages96to99 ((u32)0x01000000) /* Write protection of page 96 to 99 */
|
||||
#define FLASH_WRProt_Pages100to103 ((u32)0x02000000) /* Write protection of page 100 to 103 */
|
||||
#define FLASH_WRProt_Pages104to107 ((u32)0x04000000) /* Write protection of page 104 to 107 */
|
||||
#define FLASH_WRProt_Pages108to111 ((u32)0x08000000) /* Write protection of page 108 to 111 */
|
||||
#define FLASH_WRProt_Pages112to115 ((u32)0x10000000) /* Write protection of page 112 to 115 */
|
||||
#define FLASH_WRProt_Pages116to119 ((u32)0x20000000) /* Write protection of page 115 to 119 */
|
||||
#define FLASH_WRProt_Pages120to123 ((u32)0x40000000) /* Write protection of page 120 to 123 */
|
||||
#define FLASH_WRProt_Pages124to127 ((u32)0x80000000) /* Write protection of page 124 to 127 */
|
||||
#define FLASH_WRProt_AllPages ((u32)0xFFFFFFFF) /* Write protection All Pages */
|
||||
|
||||
#define IS_FLASH_WRPROT_PAGE(PAGE) ((PAGE != 0x00000000))
|
||||
|
||||
|
||||
#define IS_FLASH_ADDRESS(ADDRESS) ((ADDRESS >= 0x08000000) && (ADDRESS <= 0x0801FFFF))
|
||||
#define IS_OB_DATA_ADDRESS(ADDRESS) ((ADDRESS == 0x1FFFF804) || (ADDRESS == 0x1FFFF806))
|
||||
|
||||
/* Option Bytes IWatchdog ----------------------------------------------------*/
|
||||
#define OB_IWDG_SW ((u16)0x0001) /* Software IWDG selected */
|
||||
#define OB_IWDG_HW ((u16)0x0000) /* Hardware IWDG selected */
|
||||
|
||||
#define IS_OB_IWDG_SOURCE(SOURCE) ((SOURCE == OB_IWDG_SW) || (SOURCE == OB_IWDG_HW))
|
||||
|
||||
/* Option Bytes nRST_STOP ----------------------------------------------------*/
|
||||
#define OB_STOP_NoRST ((u16)0x0002) /* No reset generated when entering in STOP */
|
||||
#define OB_STOP_RST ((u16)0x0000) /* Reset generated when entering in STOP */
|
||||
|
||||
#define IS_OB_STOP_SOURCE(SOURCE) ((SOURCE == OB_STOP_NoRST) || (SOURCE == OB_STOP_RST))
|
||||
|
||||
/* Option Bytes nRST_STDBY ---------------------------------------------------*/
|
||||
#define OB_STDBY_NoRST ((u16)0x0004) /* No reset generated when entering in STANDBY */
|
||||
#define OB_STDBY_RST ((u16)0x0000) /* Reset generated when entering in STANDBY */
|
||||
|
||||
#define IS_OB_STDBY_SOURCE(SOURCE) ((SOURCE == OB_STDBY_NoRST) || (SOURCE == OB_STDBY_RST))
|
||||
|
||||
/* FLASH Interrupts ----------------------------------------------------------*/
|
||||
#define FLASH_IT_ERROR ((u32)0x00000400) /* FPEC error interrupt source */
|
||||
#define FLASH_IT_EOP ((u32)0x00001000) /* End of FLASH Operation Interrupt source */
|
||||
|
||||
#define IS_FLASH_IT(IT) (((IT & (u32)0xFFFFEBFF) == 0x00000000) && (IT != 0x00000000))
|
||||
|
||||
/* FLASH Flags ---------------------------------------------------------------*/
|
||||
#define FLASH_FLAG_BSY ((u32)0x00000001) /* FLASH Busy flag */
|
||||
#define FLASH_FLAG_EOP ((u32)0x00000020) /* FLASH End of Operation flag */
|
||||
#define FLASH_FLAG_PGERR ((u32)0x00000004) /* FLASH Program error flag */
|
||||
#define FLASH_FLAG_WRPRTERR ((u32)0x00000010) /* FLASH Write protected error flag */
|
||||
#define FLASH_FLAG_OPTERR ((u32)0x00000001) /* FLASH Option Byte error flag */
|
||||
|
||||
|
||||
#define IS_FLASH_CLEAR_FLAG(FLAG) (((FLAG & (u32)0xFFFFFFCA) == 0x00000000) && (FLAG != 0x00000000))
|
||||
#define IS_FLASH_GET_FLAG(FLAG) ((FLAG == FLASH_FLAG_BSY) || (FLAG == FLASH_FLAG_EOP) || \
|
||||
(FLAG == FLASH_FLAG_PGERR) || (FLAG == FLASH_FLAG_WRPRTERR) || \
|
||||
(FLAG == FLASH_FLAG_OPTERR))
|
||||
#endif
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void FLASH_SetLatency(u32 FLASH_Latency);
|
||||
void FLASH_HalfCycleAccessCmd(u32 FLASH_HalfCycleAccess);
|
||||
void FLASH_PrefetchBufferCmd(u32 FLASH_PrefetchBuffer);
|
||||
|
||||
#ifdef _FLASH_PROG
|
||||
void FLASH_Unlock(void);
|
||||
void FLASH_Lock(void);
|
||||
FLASH_Status FLASH_ErasePage(u32 Page_Address);
|
||||
FLASH_Status FLASH_EraseAllPages(void);
|
||||
FLASH_Status FLASH_EraseOptionBytes(void);
|
||||
FLASH_Status FLASH_ProgramWord(u32 Address, u32 Data);
|
||||
FLASH_Status FLASH_ProgramHalfWord(u32 Address, u16 Data);
|
||||
FLASH_Status FLASH_ProgramOptionByteData(u32 Address, u8 Data);
|
||||
FLASH_Status FLASH_EnableWriteProtection(u32 FLASH_Pages);
|
||||
FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);
|
||||
FLASH_Status FLASH_UserOptionByteConfig(u16 OB_IWDG, u16 OB_STOP, u16 OB_STDBY);
|
||||
u32 FLASH_GetUserOptionByte(void);
|
||||
u32 FLASH_GetWriteProtectionOptionByte(void);
|
||||
FlagStatus FLASH_GetReadOutProtectionStatus(void);
|
||||
FlagStatus FLASH_GetPrefetchBufferStatus(void);
|
||||
void FLASH_ITConfig(u16 FLASH_IT, FunctionalState NewState);
|
||||
FlagStatus FLASH_GetFlagStatus(u16 FLASH_FLAG);
|
||||
void FLASH_ClearFlag(u16 FLASH_FLAG);
|
||||
FLASH_Status FLASH_GetStatus(void);
|
||||
FLASH_Status FLASH_WaitForLastOperation(u32 Timeout);
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F10x_FLASH_H */
|
||||
|
||||
/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/
|
94
StmBoot/system_stm32f10x.h
Normal file
94
StmBoot/system_stm32f10x.h
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
Released into the public domain.
|
||||
This work is free: you can redistribute it and/or modify it under the terms of
|
||||
Creative Commons Zero license v1.0
|
||||
|
||||
This work is licensed under the Creative Commons Zero 1.0 United States License.
|
||||
To view a copy of this license, visit http://creativecommons.org/publicdomain/zero/1.0/
|
||||
or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco,
|
||||
California, 94105, USA.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup CMSIS
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32f10x_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Define to prevent recursive inclusion
|
||||
*/
|
||||
#ifndef __SYSTEM_STM32F10X_H
|
||||
#define __SYSTEM_STM32F10X_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F10x_System_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_types
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32F10x_System_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void SystemInit(void);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__SYSTEM_STM32F10X_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
BIN
Stmboot binary/StmBoot.ino.generic_stm32f103c.bin
Normal file
BIN
Stmboot binary/StmBoot.ino.generic_stm32f103c.bin
Normal file
Binary file not shown.
@ -46,9 +46,10 @@ Flashing precompiled **binaries** is done very simple with the cable setup prese
|
||||
|
||||
### Flashing the multimodule
|
||||
|
||||
There are three options for flashing the firmware. But We will present here only 2 methods ,the third one is presented in advanced topics.
|
||||
There are three options for flashing the firmware. But We will present here only 3 methods ,the 4-th one is presented in advanced topics.
|
||||
The first (and strongly recommended) is flashing it while it is plugged into and powered by the transmitter.The second is preparing the board for flashing with a USB cable.
|
||||
The second method is definitely the easiest in the long-term, but it does require the USB bord and setting up the bootloader on the STM32 MCU.
|
||||
The third method is also highly recommended and involving flashing using TX (firmware).At this methid is available for 9X ,9X pro ,Taranis with ersky9X fimrware.
|
||||
|
||||
#### Option 1: Flashing with Tx power(highly recommended)
|
||||
|
||||
@ -86,6 +87,19 @@ Notes:
|
||||
- If the initial upload fails, make sure you are running the latest [Java version](https://www.java.com/en/download/)
|
||||
- If using Banggood multiSTM32_USB module, follow instructions from step1(USB drivers on your computer) and jump after, to step 3(most probably generic bootloader is installed on multi module and no need to be installed again).I don't have one for test so this is an educated guess.
|
||||
|
||||
#### Option 3: Flashing with TX radio(firmware)
|
||||
1. Flash new STM32 bootloader(StmBoot) on multimodule.You have 2 options here.You can use one or the other.
|
||||
|
||||
- Flash precompiled binary **StmBoot.ino.generic_stm32f103c** using **ST Flash loader demonstrator** and USB serial device(FTDI) , with same custom cable presented above.This process is the same as flashing with precompiled binaries.For BG(green) module you can folow the paper instructions for flashing coming with the module using bridge pins provided.
|
||||
- Or you can compile Stmboot files yourself ,**Stmboot.ino** file using arduino IDE ,select Tools ,Upload method : **"Serial"** and press upload button.All this setup is using the same custom cable and USB-serial device(FTDI) as before.
|
||||
- After this process is complete switch off TX,remove cables FTDI serila device and/or mutimodule jumper used for flashing.The multimodule should be back inthe same state as before.
|
||||
|
||||
1. Compile multiprotocol source in arduino IDE ,choose this time Upload method **STM32duino bootloader** ,select **"Export compiled Binary"** to show the binary file in the same folder as source.
|
||||
1. Take copy of the resulted binary file, to TX radio SD card ,the firmware folder.
|
||||
1. Now flash the TX radio with the last firmware(for ersky9x is version P221 "e2" test version or higher).
|
||||
1. Enter in TX radio maintenance mode(for ersky9X start TX radio with both bottom trims pushed outwards).Select **Update multi** press menu button select also the right com port,update ,then the multiprotocol.bin file (see the correct name) and press menu and again for flashing. You'll see a bar fill slowly .Wait for the procces to be complete.Press exit( or switch off TX) several times to come out of the maintenace mode.
|
||||
1. Any subsequent update of the multiprotocol will follow 2-3 and 5-6 steps.There is no need anymore USB serial device or cables for flashing.
|
||||
|
||||
## Flashing precompiled binaries:
|
||||
|
||||
If you want to flash a pre-compiled binary file (like the Release .bin files) you need specialized software and the same FTDI cable setup already posted [here](Compiling_STM32.md#option-1-flashing-with-tx-powerhighly-recommended).
|
||||
|
@ -7,9 +7,9 @@ The Deviation project (on which this project was based) have a useful list of mo
|
||||
<img src="http://img2.cheapdrone.co.uk/images/upload/2014/12/X5C%203/SKU115108-7.jpg" Width="200" Height="200" />
|
||||
|
||||
## Channel Map
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
||||
---|---|---|---|---|---|---|---
|
||||
A|E|T|R|FLIP|RATES|PICTURE|VIDEO
|
||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||
---|---|---|---|---|---|---|---|---
|
||||
A|E|T|R|FLIP|RATES|PICTURE|VIDEO|HEADLESS
|
||||
|
||||
## Binding
|
||||
There are no special binding instructions. The model powers up in Autobind mode and expects the bind sequence from the transmitter within the first 4-5 seconds.
|
||||
@ -45,6 +45,25 @@ One of the most annoying functions on the Syma X5C is that the motors stop when
|
||||
1. When you want to fly in "idle-up" mode flick the switch and your stabilization will always be active.
|
||||
1. Remeber to switch off idle-up as soon as the quad lands (or crashes - to avoid damage to the motors)
|
||||
|
||||
### Additional notes on rates:
|
||||
|
||||
The SymaX driver can add full trim to the control output. Doing so enables
|
||||
dramatic rates, steep angles, and high speeds. If CH6 is low, the usual Syma
|
||||
full rates will be in effect. If CH6 is high, the SymaX extreme trim rates will be
|
||||
in effect. Be cautious when first trying out the extreme rates.
|
||||
|
||||
The extreme rates do not work with with headless mode because in this
|
||||
mode the trim and the primary control directions may not be aligned - the
|
||||
primary control directions will be based on the headless mode, but the trims
|
||||
remain based upon the quadcopter's heading. So extreme rates are disabled
|
||||
when headless mode is selected.
|
||||
|
||||
Be aware that the use of extreme rates and the resulting steep angles will
|
||||
disorient the gyro responsible for maintaining headless mode, and that the
|
||||
direction the quadcopter thinks you selected for headless mode may not be
|
||||
correct after especially wild flights.
|
||||
|
||||
|
||||
# Inductrix (Horizon Hobby)
|
||||
|
||||
<img src="https://s7d5.scene7.com/is/image/horizonhobby/BLH8700_a0" Width="200" Height="200" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user