Skip to content

Commit

Permalink
Merge remote-tracking branch 'betaflight/master' into betaflight-master
Browse files Browse the repository at this point in the history
  • Loading branch information
hydra committed Oct 2, 2017
2 parents eef3936 + 36c91c7 commit 4d4b41c
Show file tree
Hide file tree
Showing 76 changed files with 806 additions and 442 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ addons:
- git
- libc6-i386
- time
- libblocksruntime-dev

# We use cpp for unit tests, and c for the main project.
language: cpp
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Big thanks to current and past contributors:
* Bardwell, Joshua (joshuabardwell)
* ctzsnooze
* Höglund, Anders (andershoglund)
* Ledvin, Peter (ledvinap) - **IO code awesomeness!**
* Ledvina, Petr (ledvinap) - **IO code awesomeness!**
* kc10kevin
* Keeble, Gary (MadmanK)
* Keller, Michael (mikeller) - **Configurator brilliance**
Expand Down
1 change: 1 addition & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Vagrant.configure(2) do |config|
apt-get update
apt-get install -y git gcc-arm-embedded=6-2017q2-1~xenial1
apt-get install -y make python gcc clang
apt-get install -y libblocksruntime-dev
SHELL
end

Expand Down
10 changes: 5 additions & 5 deletions src/main/blackbox/blackbox_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static struct {

#endif // USE_SDCARD

void blackboxOpen()
void blackboxOpen(void)
{
serialPort_t *sharedBlackboxAndMspPort = findSharedSerialPort(FUNCTION_BLACKBOX, FUNCTION_MSP);
if (sharedBlackboxAndMspPort) {
Expand Down Expand Up @@ -351,7 +351,7 @@ static void blackboxLogFileCreated(afatfsFilePtr_t file)
}
}

static void blackboxCreateLogFile()
static void blackboxCreateLogFile(void)
{
uint32_t remainder = blackboxSDCard.largestLogFileNumber + 1;

Expand All @@ -372,7 +372,7 @@ static void blackboxCreateLogFile()
*
* Keep calling until the function returns true (open is complete).
*/
static bool blackboxSDCardBeginLog()
static bool blackboxSDCardBeginLog(void)
{
fatDirectoryEntry_t *directoryEntry;

Expand Down Expand Up @@ -511,7 +511,7 @@ bool isBlackboxDeviceFull(void)
}
}

unsigned int blackboxGetLogNumber()
unsigned int blackboxGetLogNumber(void)
{
#ifdef USE_SDCARD
return blackboxSDCard.largestLogFileNumber;
Expand All @@ -523,7 +523,7 @@ unsigned int blackboxGetLogNumber()
* Call once every loop iteration in order to maintain the global blackboxHeaderBudget with the number of bytes we can
* transmit this iteration.
*/
void blackboxReplenishHeaderBudget()
void blackboxReplenishHeaderBudget(void)
{
int32_t freeSpace;

Expand Down
4 changes: 2 additions & 2 deletions src/main/blackbox/blackbox_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ bool blackboxDeviceBeginLog(void);
bool blackboxDeviceEndLog(bool retainLog);

bool isBlackboxDeviceFull(void);
unsigned int blackboxGetLogNumber();
unsigned int blackboxGetLogNumber(void);

void blackboxReplenishHeaderBudget();
void blackboxReplenishHeaderBudget(void);
blackboxBufferReserveStatus_e blackboxDeviceReserveBufferSpace(int32_t bytes);
7 changes: 7 additions & 0 deletions src/main/build/atomic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <stdint.h>

#include "atomic.h"

#if defined(UNIT_TEST)
uint8_t atomic_BASEPRI;
#endif
119 changes: 99 additions & 20 deletions src/main/build/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,76 +17,133 @@

#pragma once

// only set_BASEPRI is implemented in device library. It does always create memory barrirer
#include <stdint.h>

#if !defined(UNIT_TEST)
// BASEPRI manipulation functions
// only set_BASEPRI is implemented in device library. It does always create memory barrier
// missing versions are implemented here

// set BASEPRI and BASEPRI_MAX register, but do not create memory barrier
// set BASEPRI register, do not create memory barrier
__attribute__( ( always_inline ) ) static inline void __set_BASEPRI_nb(uint32_t basePri)
{
__ASM volatile ("\tMSR basepri, %0\n" : : "r" (basePri) );
}

// set BASEPRI_MAX register, do not create memory barrier
__attribute__( ( always_inline ) ) static inline void __set_BASEPRI_MAX_nb(uint32_t basePri)
{
__ASM volatile ("\tMSR basepri_max, %0\n" : : "r" (basePri) );
}

#if !defined(STM32F3) && !defined(STM32F4) && !defined(STM32F7) /* already defined in /lib/main/CMSIS/CM4/CoreSupport/core_cmFunc.h for F4 targets */
// set BASEPRI_MAX register, with memory barrier
# if !defined(STM32F3) && !defined(STM32F4) && !defined(STM32F7) /* already defined in /lib/main/CMSIS/CM4/CoreSupport/core_cmFunc.h for F4 targets */
__attribute__( ( always_inline ) ) static inline void __set_BASEPRI_MAX(uint32_t basePri)
{
__ASM volatile ("\tMSR basepri_max, %0\n" : : "r" (basePri) : "memory" );
}
# endif

#endif

// cleanup BASEPRI restore function, with global memory barrier
#if defined(UNIT_TEST)
// atomic related functions for unittest.

extern uint8_t atomic_BASEPRI;

static inline uint8_t __get_BASEPRI(void)
{
return atomic_BASEPRI;
}

// restore BASEPRI (called as cleanup function), with global memory barrier
static inline void __basepriRestoreMem(uint8_t *val)
{
atomic_BASEPRI = *val;
asm volatile ("": : :"memory"); // compiler memory barrier
}

// increase BASEPRI, with global memory barrier, returns true
static inline uint8_t __basepriSetMemRetVal(uint8_t prio)
{
if(prio && (atomic_BASEPRI == 0 || atomic_BASEPRI > prio)) {
atomic_BASEPRI = prio;
}
asm volatile ("": : :"memory"); // compiler memory barrier
return 1;
}

// restore BASEPRI (called as cleanup function), no memory barrier
static inline void __basepriRestore(uint8_t *val)
{
atomic_BASEPRI = *val;
}

// increase BASEPRI, no memory barrier, returns true
static inline uint8_t __basepriSetRetVal(uint8_t prio)
{
if(prio && (atomic_BASEPRI == 0 || atomic_BASEPRI > prio)) {
atomic_BASEPRI = prio;
}
return 1;
}

#else
// ARM BASEPRI manipulation

// restore BASEPRI (called as cleanup function), with global memory barrier
static inline void __basepriRestoreMem(uint8_t *val)
{
__set_BASEPRI(*val);
}

// set BASEPRI_MAX function, with global memory barrier, returns true
// set BASEPRI_MAX, with global memory barrier, returns true
static inline uint8_t __basepriSetMemRetVal(uint8_t prio)
{
__set_BASEPRI_MAX(prio);
return 1;
}

// cleanup BASEPRI restore function, no memory barrier
// restore BASEPRI (called as cleanup function), no memory barrier
static inline void __basepriRestore(uint8_t *val)
{
__set_BASEPRI_nb(*val);
}

// set BASEPRI_MAX function, no memory barrier, returns true
// set BASEPRI_MAX, no memory barrier, returns true
static inline uint8_t __basepriSetRetVal(uint8_t prio)
{
__set_BASEPRI_MAX_nb(prio);
return 1;
}

// Run block with elevated BASEPRI (using BASEPRI_MAX), restoring BASEPRI on exit. All exit paths are handled
// Full memory barrier is placed at start and exit of block
#define ATOMIC_BLOCK(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestoreMem))) = __get_BASEPRI(), \
#endif

// Run block with elevated BASEPRI (using BASEPRI_MAX), restoring BASEPRI on exit.
// All exit paths are handled. Implemented as for loop, does intercept break and continue
// Full memory barrier is placed at start and at exit of block
// __unused__ attribute is used to supress CLang warning
#define ATOMIC_BLOCK(prio) for ( uint8_t __basepri_save __attribute__ ((__cleanup__ (__basepriRestoreMem), __unused__)) = __get_BASEPRI(), \
__ToDo = __basepriSetMemRetVal(prio); __ToDo ; __ToDo = 0 )

// Run block with elevated BASEPRI (using BASEPRI_MAX), but do not create memory barrier.
// Be careful when using this, you must use some method to prevent optimizer form breaking things
// Be careful when using this, you must use some method to prevent optimizer from breaking things
// - lto is used for Cleanflight compilation, so function call is not memory barrier
// - use ATOMIC_BARRIER or volatile to protect used variables
// - gcc 4.8.4 does write all values in registers to memory before 'asm volatile', so this optimization does not help much
// - gcc 5 and later works as intended, generating quite optimal code
#define ATOMIC_BLOCK_NB(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestore))) = __get_BASEPRI(), \
#define ATOMIC_BLOCK_NB(prio) for ( uint8_t __basepri_save __attribute__ ((__cleanup__ (__basepriRestore), __unused__)) = __get_BASEPRI(), \
__ToDo = __basepriSetRetVal(prio); __ToDo ; __ToDo = 0 ) \

// ATOMIC_BARRIER
// Create memory barrier
// - at the beginning of containing block (value of parameter must be reread from memory)
// - at exit of block (all exit paths) (parameter value if written into memory, but may be cached in register for subsequent use)
// On gcc 5 and higher, this protects only memory passed as parameter (any type should work)
// On gcc 5 and higher, this protects only memory passed as parameter (any type can be used)
// this macro can be used only ONCE PER LINE, but multiple uses per block are fine

#if (__GNUC__ > 6)
#warning "Please verify that ATOMIC_BARRIER works as intended"
# warning "Please verify that ATOMIC_BARRIER works as intended"
// increment version number if BARRIER works
// TODO - use flag to disable ATOMIC_BARRIER and use full barrier instead
// you should check that local variable scope with cleanup spans entire block
Expand All @@ -98,15 +155,37 @@ static inline uint8_t __basepriSetRetVal(uint8_t prio)
# define __UNIQL(x) __UNIQL_CONCAT(x,__LINE__)
#endif

// this macro uses local function for cleanup. CLang block can be substituded
#define ATOMIC_BARRIER_ENTER(dataPtr, refStr) \
__asm__ volatile ("\t# barrier (" refStr ") enter\n" : "+m" (*(dataPtr)))

#define ATOMIC_BARRIER_LEAVE(dataPtr, refStr) \
__asm__ volatile ("\t# barrier (" refStr ") leave\n" : "m" (*(dataPtr)))

#if defined(__clang__)
// CLang version, using Objective C-style block
// based on https://stackoverflow.com/questions/24959440/rewrite-gcc-cleanup-macro-with-nested-function-for-clang
typedef void (^__cleanup_block)(void);
static inline void __do_cleanup(__cleanup_block * b) { (*b)(); }

#define ATOMIC_BARRIER(data) \
typeof(data) *__UNIQL(__barrier) = &data; \
ATOMIC_BARRIER_ENTER(__UNIQL(__barrier), #data); \
__cleanup_block __attribute__((cleanup(__do_cleanup) __unused__)) __UNIQL(__cleanup) = \
^{ ATOMIC_BARRIER_LEAVE(__UNIQL(__barrier), #data); }; \
do {} while(0) \
/**/
#else
// gcc version, uses local function for cleanup.
#define ATOMIC_BARRIER(data) \
__extension__ void __UNIQL(__barrierEnd)(typeof(data) **__d) { \
__asm__ volatile ("\t# barrier(" #data ") end\n" : : "m" (**__d)); \
ATOMIC_BARRIER_LEAVE(*__d, #data); \
} \
typeof(data) __attribute__((__cleanup__(__UNIQL(__barrierEnd)))) *__UNIQL(__barrier) = &data; \
__asm__ volatile ("\t# barrier (" #data ") start\n" : "+m" (*__UNIQL(__barrier)))

typeof(data) __attribute__((__cleanup__(__UNIQL(__barrierEnd)))) *__UNIQL(__barrier) = &data; \
ATOMIC_BARRIER_ENTER(__UNIQL(__barrier), #data); \
do {} while(0) \
/**/
#endif

// define these wrappers for atomic operations, use gcc buildins
// define these wrappers for atomic operations, using gcc builtins
#define ATOMIC_OR(ptr, val) __sync_fetch_and_or(ptr, val)
#define ATOMIC_AND(ptr, val) __sync_fetch_and_and(ptr, val)
2 changes: 1 addition & 1 deletion src/main/cms/cms_menu_blackbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ static char cmsx_BlackboxStatus[CMS_BLACKBOX_STRING_LENGTH];
static char cmsx_BlackboxDeviceStorageUsed[CMS_BLACKBOX_STRING_LENGTH];
static char cmsx_BlackboxDeviceStorageFree[CMS_BLACKBOX_STRING_LENGTH];

static void cmsx_Blackbox_GetDeviceStatus()
static void cmsx_Blackbox_GetDeviceStatus(void)
{
char * unit = "B";
#if defined(USE_SDCARD) || defined(USE_FLASHFS)
Expand Down
4 changes: 2 additions & 2 deletions src/main/cms/cms_menu_vtx_tramp.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static long trampCmsCommence(displayPort_t *pDisp, const void *self)
return MENU_CHAIN_BACK;
}

static void trampCmsInitSettings()
static void trampCmsInitSettings(void)
{
if (trampBand > 0) trampCmsBand = trampBand;
if (trampChannel > 0) trampCmsChan = trampChannel;
Expand All @@ -174,7 +174,7 @@ static void trampCmsInitSettings()
}
}

static long trampCmsOnEnter()
static long trampCmsOnEnter(void)
{
trampCmsInitSettings();
return 0;
Expand Down
4 changes: 2 additions & 2 deletions src/main/config/feature.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void intFeatureClearAll(uint32_t *features)
*features = 0;
}

void latchActiveFeatures()
void latchActiveFeatures(void)
{
activeFeaturesLatch = featureConfig()->enabledFeatures;
}
Expand All @@ -68,7 +68,7 @@ void featureClear(uint32_t mask)
intFeatureClear(mask, &featureConfigMutable()->enabledFeatures);
}

void featureClearAll()
void featureClearAll(void)
{
intFeatureClearAll(&featureConfigMutable()->enabledFeatures);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/config/parameter_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ int pgStore(const pgRegistry_t* reg, void *to, int size)
return take;
}

void pgResetAll()
void pgResetAll(void)
{
PG_FOREACH(reg) {
pgReset(reg);
Expand Down
2 changes: 1 addition & 1 deletion src/main/config/parameter_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ const pgRegistry_t* pgFind(pgn_t pgn);

void pgLoad(const pgRegistry_t* reg, const void *from, int size, int version);
int pgStore(const pgRegistry_t* reg, void *to, int size);
void pgResetAll();
void pgResetAll(void);
void pgResetInstance(const pgRegistry_t *reg, uint8_t *base);
bool pgResetCopy(void *copy, pgn_t pgn);
void pgReset(const pgRegistry_t* reg);
2 changes: 2 additions & 0 deletions src/main/drivers/bus_spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ typedef enum SPIDevice {
#define SPI_DEV_TO_CFG(x) ((x) + 1)

void spiPreInitCs(ioTag_t iotag);
void spiPreInitCsOutPU(ioTag_t iotag);

bool spiInit(SPIDevice device);
void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor);
uint8_t spiTransferByte(SPI_TypeDef *instance, uint8_t data);
Expand Down
19 changes: 18 additions & 1 deletion src/main/drivers/bus_spi_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@

// Bring a pin for possible CS line to pull-up state in preparation for
// sequential initialization by relevant drivers.
// Note that the pin is set to input for safety at this point.

// There are two versions:
// spiPreInitCs set the pin to input with pullup (IOCFG_IPU) for safety at this point.
// spiPreInitCsOutPU which actually drive the pin for digital hi.
//
// The later is required for SPI slave devices on some targets, interfaced through level shifters, such as Kakute F4.
// Note that with this handling, a pin declared as CS pin for MAX7456 needs special care when re-purposing the pin for other, especially, input uses.
// This will/should be fixed when we go fully reconfigurable.

void spiPreInitCs(ioTag_t iotag)
{
Expand All @@ -35,3 +42,13 @@ void spiPreInitCs(ioTag_t iotag)
IOConfigGPIO(io, IOCFG_IPU);
}
}

void spiPreInitCsOutPU(ioTag_t iotag)
{
IO_t io = IOGetByTag(iotag);
if (io) {
IOInit(io, OWNER_SPI_PREINIT, 0);
IOConfigGPIO(io, IOCFG_OUT_PP);
IOHi(io);
}
}
Loading

0 comments on commit 4d4b41c

Please sign in to comment.