1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-21 07:15:18 +03:00

Merge remote-tracking branch 'refs/remotes/betaflight/master' into betaflight

This commit is contained in:
tianbin4279 2016-07-14 22:45:12 +08:00
commit b15e2ed62c
250 changed files with 5240 additions and 4128 deletions

View file

@ -600,6 +600,7 @@ LDFLAGS = -lm \
-Wl,-gc-sections,-Map,$(TARGET_MAP) \ -Wl,-gc-sections,-Map,$(TARGET_MAP) \
-Wl,-L$(LINKER_DIR) \ -Wl,-L$(LINKER_DIR) \
-Wl,--cref \ -Wl,--cref \
-Wl,--no-wchar-size-warning \
-T$(LD_SCRIPT) -T$(LD_SCRIPT)
############################################################################### ###############################################################################
@ -664,27 +665,39 @@ all: $(VALID_TARGETS)
$(VALID_TARGETS): $(VALID_TARGETS):
echo "" && \ echo "" && \
echo "Building $@" && \ echo "Building $@" && \
$(MAKE) -j binary hex TARGET=$@ && \ $(MAKE) binary hex TARGET=$@ && \
echo "Building $@ succeeded." echo "Building $@ succeeded."
## clean : clean up all temporary / machine-generated files
CLEAN_TARGETS = $(addprefix clean_,$(VALID_TARGETS) )
TARGETS_CLEAN = $(addsuffix _clean,$(VALID_TARGETS) )
## clean : clean up temporary / machine-generated files
clean: clean:
echo "Cleaning $(TARGET)"
rm -f $(CLEAN_ARTIFACTS) rm -f $(CLEAN_ARTIFACTS)
rm -rf $(OBJECT_DIR)/$(TARGET) rm -rf $(OBJECT_DIR)/$(TARGET)
echo "Cleaning $(TARGET) succeeded."
## clean_test : clean up all temporary / machine-generated files (tests) ## clean_test : clean up temporary / machine-generated files (tests)
clean_test: clean_test:
cd src/test && $(MAKE) clean || true cd src/test && $(MAKE) clean || true
## clean_all_targets : clean all valid target platforms ## clean_<TARGET> : clean up one specific target
clean_all: $(CLEAN_TARGETS) :
for clean_target in $(VALID_TARGETS); do \ $(MAKE) -j TARGET=$(subst clean_,,$@) clean
echo "" && \
echo "Cleaning $$clean_target" && \ ## <TARGET>_clean : clean up one specific target (alias for above)
$(MAKE) -j TARGET=$$clean_target clean || \ $(TARGETS_CLEAN) :
break; \ $(MAKE) -j TARGET=$(subst _clean,,$@) clean
echo "Cleaning $$clean_target succeeded."; \
done ## clean_all : clean all valid targets
clean_all:$(CLEAN_TARGETS)
## all_clean : clean all valid targets (alias for above)
all_clean:$(TARGETS_CLEAN)
flash_$(TARGET): $(TARGET_HEX) flash_$(TARGET): $(TARGET_HEX)
stty -F $(SERIAL_DEVICE) raw speed 115200 -crtscts cs8 -parenb -cstopb -ixon stty -F $(SERIAL_DEVICE) raw speed 115200 -crtscts cs8 -parenb -cstopb -ixon
@ -700,8 +713,11 @@ st-flash_$(TARGET): $(TARGET_BIN)
## st-flash : flash firmware (.bin) onto flight controller ## st-flash : flash firmware (.bin) onto flight controller
st-flash: st-flash_$(TARGET) st-flash: st-flash_$(TARGET)
binary: $(TARGET_BIN) binary:
hex: $(TARGET_HEX) $(MAKE) -j $(TARGET_BIN)
hex:
$(MAKE) -j $(TARGET_HEX)
unbrick_$(TARGET): $(TARGET_HEX) unbrick_$(TARGET): $(TARGET_HEX)
stty -F $(SERIAL_DEVICE) raw speed 115200 -crtscts cs8 -parenb -cstopb -ixon stty -F $(SERIAL_DEVICE) raw speed 115200 -crtscts cs8 -parenb -cstopb -ixon

View file

@ -1,6 +1,6 @@
# Betaflight # Betaflight
![Betaflight](https://dl.dropboxusercontent.com/u/31537757/betaflight%20logo.jpg) ![Betaflight](https://camo.githubusercontent.com/8178215d6cb90842dc95c9d437b1bdf09b2d57a7/687474703a2f2f7374617469632e726367726f7570732e6e65742f666f72756d732f6174746163686d656e74732f362f312f302f332f372f362f61393038383930302d3232382d62665f6c6f676f2e6a7067)
Clean-code version of baseflight flight-controller - flight controllers are used to fly multi-rotor craft and fixed wing craft. Clean-code version of baseflight flight-controller - flight controllers are used to fly multi-rotor craft and fixed wing craft.

View file

@ -20,7 +20,10 @@ targets=("PUBLISHMETA=True" \
"TARGET=ALIENFLIGHTF3" \ "TARGET=ALIENFLIGHTF3" \
"TARGET=DOGE" \ "TARGET=DOGE" \
"TARGET=SINGULARITY" \ "TARGET=SINGULARITY" \
"TARGET=SIRINFPV") "TARGET=SIRINFPV" \
"TARGET=X_RACERSPI")
#fake a travis build environment #fake a travis build environment
export TRAVIS_BUILD_NUMBER=$(date +%s) export TRAVIS_BUILD_NUMBER=$(date +%s)
@ -30,9 +33,9 @@ export TRAVIS_REPO_SLUG=${TRAVIS_REPO_SLUG:=$USER/simulated}
for target in "${targets[@]}" for target in "${targets[@]}"
do do
unset RUNTESTS PUBLISHMETA TARGET unset RUNTESTS PUBLISHMETA TARGET
echo echo
echo echo
echo "BUILDING '$target'" echo "BUILDING '$target'"
eval "export $target" eval "export $target"
make -f Makefile clean make -f Makefile clean
./.travis.sh ./.travis.sh

View file

@ -325,9 +325,6 @@ extern uint32_t currentTime;
//From rx.c: //From rx.c:
extern uint16_t rssi; extern uint16_t rssi;
//From gyro.c
extern uint32_t targetLooptime;
//From rc_controls.c //From rc_controls.c
extern uint32_t rcModeActivationMask; extern uint32_t rcModeActivationMask;
@ -1169,7 +1166,7 @@ static bool blackboxWriteSysinfo()
} }
); );
BLACKBOX_PRINT_HEADER_LINE("looptime:%d", targetLooptime); BLACKBOX_PRINT_HEADER_LINE("looptime:%d", gyro.targetLooptime);
BLACKBOX_PRINT_HEADER_LINE("rcRate:%d", masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile].rcRate8); BLACKBOX_PRINT_HEADER_LINE("rcRate:%d", masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile].rcRate8);
BLACKBOX_PRINT_HEADER_LINE("rcExpo:%d", masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile].rcExpo8); BLACKBOX_PRINT_HEADER_LINE("rcExpo:%d", masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile].rcExpo8);
BLACKBOX_PRINT_HEADER_LINE("rcYawRate:%d", masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile].rcYawRate8); BLACKBOX_PRINT_HEADER_LINE("rcYawRate:%d", masterConfig.profile[masterConfig.current_profile_index].controlRateProfile[masterConfig.profile[masterConfig.current_profile_index].activeRateProfile].rcYawRate8);

View file

@ -22,7 +22,6 @@
#include "drivers/accgyro.h" #include "drivers/accgyro.h"
#include "drivers/light_led.h" #include "drivers/light_led.h"
#include "drivers/sound_beeper.h" #include "drivers/sound_beeper.h"
#include "drivers/gyro_sync.h"
#include "sensors/sensors.h" #include "sensors/sensors.h"
#include "sensors/boardalignment.h" #include "sensors/boardalignment.h"

View file

@ -85,7 +85,7 @@ static inline uint8_t __basepriSetRetVal(uint8_t prio)
// ideally this would only protect memory passed as parameter (any type should work), but gcc is curently creating almost full barrier // ideally this would only protect memory passed as parameter (any type should work), but gcc is curently creating almost full barrier
// this macro can be used only ONCE PER LINE, but multiple uses per block are fine // this macro can be used only ONCE PER LINE, but multiple uses per block are fine
#if (__GNUC__ > 4) #if (__GNUC__ > 5)
#warning "Please verify that ATOMIC_BARRIER works as intended" #warning "Please verify that ATOMIC_BARRIER works as intended"
// increment version number is BARRIER works // increment version number is BARRIER works
// TODO - use flag to disable ATOMIC_BARRIER and use full barrier instead // TODO - use flag to disable ATOMIC_BARRIER and use full barrier instead

View file

@ -17,76 +17,81 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <math.h> #include <math.h>
#include "common/axis.h"
#include "common/filter.h" #include "common/filter.h"
#include "common/maths.h" #include "common/maths.h"
#define M_LN2_FLOAT 0.69314718055994530942f #define M_LN2_FLOAT 0.69314718055994530942f
#define M_PI_FLOAT 3.14159265358979323846f #define M_PI_FLOAT 3.14159265358979323846f
#define BIQUAD_BANDWIDTH 1.9f /* bandwidth in octaves */ #define BIQUAD_BANDWIDTH 1.9f /* bandwidth in octaves */
#define BIQUAD_Q 1.0f / sqrtf(2.0f) /* quality factor - butterworth*/ #define BIQUAD_Q 1.0f / sqrtf(2.0f) /* quality factor - butterworth*/
// PT1 Low Pass filter (when no dT specified it will be calculated from the cycleTime) // PT1 Low Pass filter
float filterApplyPt1(float input, filterStatePt1_t *filter, float f_cut, float dT) {
// Pre calculate and store RC void pt1FilterInit(pt1Filter_t *filter, uint8_t f_cut, float dT)
if (!filter->RC) { {
filter->RC = 1.0f / ( 2.0f * M_PI_FLOAT * f_cut ); filter->RC = 1.0f / ( 2.0f * M_PI_FLOAT * f_cut );
} filter->dT = dT;
}
filter->state = filter->state + dT / (filter->RC + dT) * (input - filter->state); float pt1FilterApply(pt1Filter_t *filter, float input)
{
filter->state = filter->state + filter->dT / (filter->RC + filter->dT) * (input - filter->state);
return filter->state;
}
float pt1FilterApply4(pt1Filter_t *filter, float input, uint8_t f_cut, float dT)
{
// Pre calculate and store RC
if (!filter->RC) {
filter->RC = 1.0f / ( 2.0f * M_PI_FLOAT * f_cut );
filter->dT = dT;
}
filter->state = filter->state + filter->dT / (filter->RC + filter->dT) * (input - filter->state);
return filter->state; return filter->state;
} }
/* sets up a biquad Filter */ /* sets up a biquad Filter */
void BiQuadNewLpf(float filterCutFreq, biquad_t *newState, uint32_t refreshRate) void biquadFilterInit(biquadFilter_t *filter, float filterCutFreq, uint32_t refreshRate)
{ {
float sampleRate; const float sampleRate = 1 / ((float)refreshRate * 0.000001f);
sampleRate = 1 / ((float)refreshRate * 0.000001f); // setup variables
const float omega = 2 * M_PI_FLOAT * filterCutFreq / sampleRate;
float omega, sn, cs, alpha; const float sn = sinf(omega);
float a0, a1, a2, b0, b1, b2; const float cs = cosf(omega);
/* setup variables */
omega = 2 * M_PI_FLOAT * filterCutFreq / sampleRate;
sn = sinf(omega);
cs = cosf(omega);
//this is wrong, should be hyperbolic sine //this is wrong, should be hyperbolic sine
//alpha = sn * sinf(M_LN2_FLOAT /2 * BIQUAD_BANDWIDTH * omega /sn); //alpha = sn * sinf(M_LN2_FLOAT /2 * BIQUAD_BANDWIDTH * omega /sn);
alpha = sn / (2 * BIQUAD_Q); const float alpha = sn / (2 * BIQUAD_Q);
b0 = (1 - cs) / 2; const float b0 = (1 - cs) / 2;
b1 = 1 - cs; const float b1 = 1 - cs;
b2 = (1 - cs) / 2; const float b2 = (1 - cs) / 2;
a0 = 1 + alpha; const float a0 = 1 + alpha;
a1 = -2 * cs; const float a1 = -2 * cs;
a2 = 1 - alpha; const float a2 = 1 - alpha;
/* precompute the coefficients */ // precompute the coefficients
newState->b0 = b0 / a0; filter->b0 = b0 / a0;
newState->b1 = b1 / a0; filter->b1 = b1 / a0;
newState->b2 = b2 / a0; filter->b2 = b2 / a0;
newState->a1 = a1 / a0; filter->a1 = a1 / a0;
newState->a2 = a2 / a0; filter->a2 = a2 / a0;
/* zero initial samples */ // zero initial samples
newState->d1 = newState->d2 = 1; filter->d1 = filter->d2 = 0;
} }
/* Computes a biquad_t filter on a sample */ /* Computes a biquad_t filter on a sample */
float applyBiQuadFilter(float sample, biquad_t *state) //direct form 2 transposed float biquadFilterApply(biquadFilter_t *filter, float input)
{ {
float result; const float result = filter->b0 * input + filter->d1;
filter->d1 = filter->b1 * input - filter->a1 * result + filter->d2;
result = state->b0 * sample + state->d1; filter->d2 = filter->b2 * input - filter->a2 * result;
state->d1 = state->b1 * sample - state->a1 * result + state->d2;
state->d2 = state->b2 * sample - state->a2 * result;
return result; return result;
} }

View file

@ -17,20 +17,26 @@
#define DELTA_MAX_SAMPLES 12 #define DELTA_MAX_SAMPLES 12
typedef struct filterStatePt1_s { typedef struct pt1Filter_s {
float state; float state;
float RC; float RC;
float constdT; float dT;
} filterStatePt1_t; } pt1Filter_t;
/* this holds the data required to update samples thru a filter */ /* this holds the data required to update samples thru a filter */
typedef struct biquad_s { typedef struct biquadFilter_s {
float b0, b1, b2, a1, a2; float b0, b1, b2, a1, a2;
float d1, d2; float d1, d2;
} biquad_t; } biquadFilter_t;
void biquadFilterInit(biquadFilter_t *filter, float filterCutFreq, uint32_t refreshRate);
float biquadFilterApply(biquadFilter_t *filter, float input);
void pt1FilterInit(pt1Filter_t *filter, uint8_t f_cut, float dT);
float pt1FilterApply(pt1Filter_t *filter, float input);
float pt1FilterApply4(pt1Filter_t *filter, float input, uint8_t f_cut, float dT);
float applyBiQuadFilter(float sample, biquad_t *state);
float filterApplyPt1(float input, filterStatePt1_t *filter, float f_cut, float dt);
int32_t filterApplyAverage(int32_t input, uint8_t averageCount, int32_t averageState[DELTA_MAX_SAMPLES]); int32_t filterApplyAverage(int32_t input, uint8_t averageCount, int32_t averageState[DELTA_MAX_SAMPLES]);
float filterApplyAveragef(float input, uint8_t averageCount, float averageState[DELTA_MAX_SAMPLES]); float filterApplyAveragef(float input, uint8_t averageCount, float averageState[DELTA_MAX_SAMPLES]);
void BiQuadNewLpf(float filterCutFreq, biquad_t *newState, uint32_t refreshRate);

View file

@ -87,7 +87,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
putf(putp, ch); written++; putf(putp, ch); written++;
} else { } else {
char lz = 0; char lz = 0;
#ifdef REQUIRE_PRINTF_LONG_SUPPORT #ifdef REQUIRE_PRINTF_LONG_SUPPORT
char lng = 0; char lng = 0;
#endif #endif
int w = 0; int w = 0;
@ -99,7 +99,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
ch = a2i(ch, &fmt, 10, &w); ch = a2i(ch, &fmt, 10, &w);
} }
#ifdef REQUIRE_PRINTF_LONG_SUPPORT #ifdef REQUIRE_PRINTF_LONG_SUPPORT
if (ch == 'l') { if (ch == 'l') {
ch = *(fmt++); ch = *(fmt++);
lng = 1; lng = 1;
@ -109,7 +109,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
case 0: case 0:
goto abort; goto abort;
case 'u':{ case 'u':{
#ifdef REQUIRE_PRINTF_LONG_SUPPORT #ifdef REQUIRE_PRINTF_LONG_SUPPORT
if (lng) if (lng)
uli2a(va_arg(va, unsigned long int), 10, 0, bf); uli2a(va_arg(va, unsigned long int), 10, 0, bf);
else else
@ -119,7 +119,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
break; break;
} }
case 'd':{ case 'd':{
#ifdef REQUIRE_PRINTF_LONG_SUPPORT #ifdef REQUIRE_PRINTF_LONG_SUPPORT
if (lng) if (lng)
li2a(va_arg(va, unsigned long int), bf); li2a(va_arg(va, unsigned long int), bf);
else else
@ -130,7 +130,7 @@ int tfp_format(void *putp, putcf putf, const char *fmt, va_list va)
} }
case 'x': case 'x':
case 'X': case 'X':
#ifdef REQUIRE_PRINTF_LONG_SUPPORT #ifdef REQUIRE_PRINTF_LONG_SUPPORT
if (lng) if (lng)
uli2a(va_arg(va, unsigned long int), 16, (ch == 'X'), bf); uli2a(va_arg(va, unsigned long int), 16, (ch == 'X'), bf);
else else

View file

@ -66,10 +66,10 @@ To use the printf you need to supply your own character output function,
something like : something like :
void putc ( void* p, char c) void putc ( void* p, char c)
{ {
while (!SERIAL_PORT_EMPTY) ; while (!SERIAL_PORT_EMPTY) ;
SERIAL_PORT_TX_REGISTER = c; SERIAL_PORT_TX_REGISTER = c;
} }
Before you can call printf you need to initialize it to use your Before you can call printf you need to initialize it to use your
character output function with something like: character output function with something like:

View file

@ -38,7 +38,6 @@
#include "drivers/timer.h" #include "drivers/timer.h"
#include "drivers/pwm_rx.h" #include "drivers/pwm_rx.h"
#include "drivers/serial.h" #include "drivers/serial.h"
#include "drivers/gyro_sync.h"
#include "drivers/pwm_output.h" #include "drivers/pwm_output.h"
#include "drivers/max7456.h" #include "drivers/max7456.h"
@ -90,6 +89,7 @@
#endif #endif
void useRcControlsConfig(modeActivationCondition_t *modeActivationConditions, escAndServoConfig_t *escAndServoConfigToUse, pidProfile_t *pidProfileToUse); void useRcControlsConfig(modeActivationCondition_t *modeActivationConditions, escAndServoConfig_t *escAndServoConfigToUse, pidProfile_t *pidProfileToUse);
void targetConfiguration(void);
#if !defined(FLASH_SIZE) #if !defined(FLASH_SIZE)
#error "Flash size not defined for target. (specify in KB)" #error "Flash size not defined for target. (specify in KB)"
@ -269,8 +269,13 @@ void resetSensorAlignment(sensorAlignmentConfig_t *sensorAlignmentConfig)
void resetEscAndServoConfig(escAndServoConfig_t *escAndServoConfig) void resetEscAndServoConfig(escAndServoConfig_t *escAndServoConfig)
{ {
#ifdef BRUSHED_MOTORS
escAndServoConfig->minthrottle = 1000;
escAndServoConfig->maxthrottle = 2000;
#else
escAndServoConfig->minthrottle = 1150; escAndServoConfig->minthrottle = 1150;
escAndServoConfig->maxthrottle = 1850; escAndServoConfig->maxthrottle = 1850;
#endif
escAndServoConfig->mincommand = 1000; escAndServoConfig->mincommand = 1000;
escAndServoConfig->servoCenterPulse = 1500; escAndServoConfig->servoCenterPulse = 1500;
escAndServoConfig->escDesyncProtection = 0; escAndServoConfig->escDesyncProtection = 0;
@ -416,8 +421,6 @@ uint16_t getCurrentMinthrottle(void)
// Default settings // Default settings
static void resetConf(void) static void resetConf(void)
{ {
int i;
// Clear all configuration // Clear all configuration
memset(&masterConfig, 0, sizeof(master_t)); memset(&masterConfig, 0, sizeof(master_t));
setProfile(0); setProfile(0);
@ -478,7 +481,11 @@ static void resetConf(void)
resetTelemetryConfig(&masterConfig.telemetryConfig); resetTelemetryConfig(&masterConfig.telemetryConfig);
#ifdef SERIALRX_PROVIDER
masterConfig.rxConfig.serialrx_provider = SERIALRX_PROVIDER;
#else
masterConfig.rxConfig.serialrx_provider = 0; masterConfig.rxConfig.serialrx_provider = 0;
#endif
masterConfig.rxConfig.sbus_inversion = 1; masterConfig.rxConfig.sbus_inversion = 1;
masterConfig.rxConfig.spektrum_sat_bind = 0; masterConfig.rxConfig.spektrum_sat_bind = 0;
masterConfig.rxConfig.spektrum_sat_bind_autoreset = 1; masterConfig.rxConfig.spektrum_sat_bind_autoreset = 1;
@ -488,7 +495,7 @@ static void resetConf(void)
masterConfig.rxConfig.rx_min_usec = 885; // any of first 4 channels below this value will trigger rx loss detection masterConfig.rxConfig.rx_min_usec = 885; // any of first 4 channels below this value will trigger rx loss detection
masterConfig.rxConfig.rx_max_usec = 2115; // any of first 4 channels above this value will trigger rx loss detection masterConfig.rxConfig.rx_max_usec = 2115; // any of first 4 channels above this value will trigger rx loss detection
for (i = 0; i < MAX_SUPPORTED_RC_CHANNEL_COUNT; i++) { for (int i = 0; i < MAX_SUPPORTED_RC_CHANNEL_COUNT; i++) {
rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &masterConfig.rxConfig.failsafe_channel_configurations[i]; rxFailsafeChannelConfiguration_t *channelFailsafeConfiguration = &masterConfig.rxConfig.failsafe_channel_configurations[i];
channelFailsafeConfiguration->mode = (i < NON_AUX_CHANNEL_COUNT) ? RX_FAILSAFE_MODE_AUTO : RX_FAILSAFE_MODE_HOLD; channelFailsafeConfiguration->mode = (i < NON_AUX_CHANNEL_COUNT) ? RX_FAILSAFE_MODE_AUTO : RX_FAILSAFE_MODE_HOLD;
channelFailsafeConfiguration->step = (i == THROTTLE) ? CHANNEL_VALUE_TO_RXFAIL_STEP(masterConfig.rxConfig.rx_min_usec) : CHANNEL_VALUE_TO_RXFAIL_STEP(masterConfig.rxConfig.midrc); channelFailsafeConfiguration->step = (i == THROTTLE) ? CHANNEL_VALUE_TO_RXFAIL_STEP(masterConfig.rxConfig.rx_min_usec) : CHANNEL_VALUE_TO_RXFAIL_STEP(masterConfig.rxConfig.midrc);
@ -550,8 +557,7 @@ static void resetConf(void)
resetPidProfile(&currentProfile->pidProfile); resetPidProfile(&currentProfile->pidProfile);
uint8_t rI; for (int rI = 0; rI<MAX_RATEPROFILES; rI++) {
for (rI = 0; rI<MAX_RATEPROFILES; rI++) {
resetControlRateConfig(&masterConfig.profile[0].controlRateProfile[rI]); resetControlRateConfig(&masterConfig.profile[0].controlRateProfile[rI]);
} }
resetRollAndPitchTrims(&masterConfig.accelerometerTrims); resetRollAndPitchTrims(&masterConfig.accelerometerTrims);
@ -582,7 +588,7 @@ static void resetConf(void)
#ifdef USE_SERVOS #ifdef USE_SERVOS
// servos // servos
for (i = 0; i < MAX_SUPPORTED_SERVOS; i++) { for (int i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
masterConfig.servoConf[i].min = DEFAULT_SERVO_MIN; masterConfig.servoConf[i].min = DEFAULT_SERVO_MIN;
masterConfig.servoConf[i].max = DEFAULT_SERVO_MAX; masterConfig.servoConf[i].max = DEFAULT_SERVO_MAX;
masterConfig.servoConf[i].middle = DEFAULT_SERVO_MIDDLE; masterConfig.servoConf[i].middle = DEFAULT_SERVO_MIDDLE;
@ -601,8 +607,9 @@ static void resetConf(void)
#endif #endif
// custom mixer. clear by defaults. // custom mixer. clear by defaults.
for (i = 0; i < MAX_SUPPORTED_MOTORS; i++) for (int i = 0; i < MAX_SUPPORTED_MOTORS; i++) {
masterConfig.customMotorMixer[i].throttle = 0.0f; masterConfig.customMotorMixer[i].throttle = 0.0f;
}
#ifdef LED_STRIP #ifdef LED_STRIP
applyDefaultColors(masterConfig.colors, CONFIGURABLE_COLOR_COUNT); applyDefaultColors(masterConfig.colors, CONFIGURABLE_COLOR_COUNT);
@ -640,61 +647,18 @@ static void resetConf(void)
#endif // BLACKBOX #endif // BLACKBOX
// alternative defaults settings for COLIBRI RACE targets #ifdef SERIALRX_UART
#if defined(COLIBRI_RACE) if (featureConfigured(FEATURE_RX_SERIAL)) {
masterConfig.escAndServoConfig.minthrottle = 1025; masterConfig.serialConfig.portConfigs[SERIALRX_UART].functionMask = FUNCTION_RX_SERIAL;
masterConfig.escAndServoConfig.maxthrottle = 1980; }
masterConfig.batteryConfig.vbatmaxcellvoltage = 45;
masterConfig.batteryConfig.vbatmincellvoltage = 30;
#endif #endif
#if defined(TARGET_CONFIG) #if defined(TARGET_CONFIG)
targetConfiguration(&masterConfig); targetConfiguration();
#endif
#if defined(ALIENFLIGHT)
featureClear(FEATURE_ONESHOT125);
#ifdef ALIENFLIGHTF1
masterConfig.serialConfig.portConfigs[1].functionMask = FUNCTION_RX_SERIAL;
#else
masterConfig.serialConfig.portConfigs[2].functionMask = FUNCTION_RX_SERIAL;
#endif
#ifdef ALIENFLIGHTF3
masterConfig.batteryConfig.vbatscale = 20;
masterConfig.mag_hardware = MAG_NONE; // disabled by default
#endif
masterConfig.rxConfig.serialrx_provider = SERIALRX_SPEKTRUM2048;
masterConfig.rxConfig.spektrum_sat_bind = 5;
masterConfig.rxConfig.spektrum_sat_bind_autoreset = 1;
masterConfig.escAndServoConfig.minthrottle = 1000;
masterConfig.escAndServoConfig.maxthrottle = 2000;
masterConfig.motor_pwm_rate = 32000;
masterConfig.failsafeConfig.failsafe_delay = 2;
masterConfig.failsafeConfig.failsafe_off_delay = 0;
currentControlRateProfile->rates[FD_PITCH] = 40;
currentControlRateProfile->rates[FD_ROLL] = 40;
currentControlRateProfile->rates[FD_YAW] = 40;
parseRcChannels("TAER1234", &masterConfig.rxConfig);
masterConfig.customMotorMixer[0] = (motorMixer_t){ 1.0f, -0.414178f, 1.0f, -1.0f }; // REAR_R
masterConfig.customMotorMixer[1] = (motorMixer_t){ 1.0f, -0.414178f, -1.0f, 1.0f }; // FRONT_R
masterConfig.customMotorMixer[2] = (motorMixer_t){ 1.0f, 0.414178f, 1.0f, 1.0f }; // REAR_L
masterConfig.customMotorMixer[3] = (motorMixer_t){ 1.0f, 0.414178f, -1.0f, -1.0f }; // FRONT_L
masterConfig.customMotorMixer[4] = (motorMixer_t){ 1.0f, -1.0f, -0.414178f, -1.0f }; // MIDFRONT_R
masterConfig.customMotorMixer[5] = (motorMixer_t){ 1.0f, 1.0f, -0.414178f, 1.0f }; // MIDFRONT_L
masterConfig.customMotorMixer[6] = (motorMixer_t){ 1.0f, -1.0f, 0.414178f, 1.0f }; // MIDREAR_R
masterConfig.customMotorMixer[7] = (motorMixer_t){ 1.0f, 1.0f, 0.414178f, -1.0f }; // MIDREAR_L#endif
#endif
#if defined(SINGULARITY)
// alternative defaults settings for SINGULARITY target
masterConfig.batteryConfig.vbatscale = 77;
masterConfig.serialConfig.portConfigs[2].functionMask = FUNCTION_RX_SERIAL;
#endif #endif
// copy first profile into remaining profile // copy first profile into remaining profile
for (i = 1; i < MAX_PROFILE_COUNT; i++) { for (int i = 1; i < MAX_PROFILE_COUNT; i++) {
memcpy(&masterConfig.profile[i], currentProfile, sizeof(profile_t)); memcpy(&masterConfig.profile[i], currentProfile, sizeof(profile_t));
} }
@ -751,7 +715,7 @@ void activateConfig(void)
&currentProfile->pidProfile &currentProfile->pidProfile
); );
useGyroConfig(&masterConfig.gyroConfig, masterConfig.gyro_soft_lpf_hz); gyroUseConfig(&masterConfig.gyroConfig, masterConfig.gyro_soft_lpf_hz);
#ifdef TELEMETRY #ifdef TELEMETRY
telemetryUseConfig(&masterConfig.telemetryConfig); telemetryUseConfig(&masterConfig.telemetryConfig);
@ -806,7 +770,7 @@ void activateConfig(void)
void validateAndFixConfig(void) void validateAndFixConfig(void)
{ {
if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) { if (!(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_PPM) || featureConfigured(FEATURE_RX_SERIAL) || featureConfigured(FEATURE_RX_MSP))) {
featureSet(FEATURE_RX_PARALLEL_PWM); // Consider changing the default to PPM featureSet(DEFAULT_RX_FEATURE);
} }
if (featureConfigured(FEATURE_RX_PPM)) { if (featureConfigured(FEATURE_RX_PPM)) {
@ -848,10 +812,10 @@ void validateAndFixConfig(void)
if (featureConfigured(FEATURE_SOFTSERIAL) && ( if (featureConfigured(FEATURE_SOFTSERIAL) && (
0 0
#ifdef USE_SOFTSERIAL1 #ifdef USE_SOFTSERIAL1
|| (LED_STRIP_TIMER == SOFTSERIAL_1_TIMER) || (WS2811_TIMER == SOFTSERIAL_1_TIMER)
#endif #endif
#ifdef USE_SOFTSERIAL2 #ifdef USE_SOFTSERIAL2
|| (LED_STRIP_TIMER == SOFTSERIAL_2_TIMER) || (WS2811_TIMER == SOFTSERIAL_2_TIMER)
#endif #endif
)) { )) {
// led strip needs the same timer as softserial // led strip needs the same timer as softserial
@ -871,7 +835,7 @@ void validateAndFixConfig(void)
} }
#endif #endif
#if defined(CC3D) && defined(DISPLAY) && defined(USE_USART3) #if defined(CC3D) && defined(DISPLAY) && defined(USE_UART3)
if (doesConfigurationUsePort(SERIAL_PORT_USART3) && feature(FEATURE_DISPLAY)) { if (doesConfigurationUsePort(SERIAL_PORT_USART3) && feature(FEATURE_DISPLAY)) {
featureClear(FEATURE_DISPLAY); featureClear(FEATURE_DISPLAY);
} }
@ -901,15 +865,11 @@ void validateAndFixConfig(void)
#if defined(COLIBRI_RACE) #if defined(COLIBRI_RACE)
masterConfig.serialConfig.portConfigs[0].functionMask = FUNCTION_MSP; masterConfig.serialConfig.portConfigs[0].functionMask = FUNCTION_MSP;
if(featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_MSP)) { if (featureConfigured(FEATURE_RX_PARALLEL_PWM) || featureConfigured(FEATURE_RX_MSP)) {
featureClear(FEATURE_RX_PARALLEL_PWM); featureClear(FEATURE_RX_PARALLEL_PWM);
featureClear(FEATURE_RX_MSP); featureClear(FEATURE_RX_MSP);
featureSet(FEATURE_RX_PPM); featureSet(FEATURE_RX_PPM);
} }
if(featureConfigured(FEATURE_RX_SERIAL)) {
masterConfig.serialConfig.portConfigs[2].functionMask = FUNCTION_RX_SERIAL;
//masterConfig.rxConfig.serialrx_provider = SERIALRX_SBUS;
}
#endif #endif
useRxConfig(&masterConfig.rxConfig); useRxConfig(&masterConfig.rxConfig);

View file

@ -17,7 +17,11 @@
#pragma once #pragma once
#if FLASH_SIZE <= 128
#define MAX_PROFILE_COUNT 2 #define MAX_PROFILE_COUNT 2
#else
#define MAX_PROFILE_COUNT 3
#endif
#define MAX_RATEPROFILES 3 #define MAX_RATEPROFILES 3
#define ONESHOT_FEATURE_CHANGED_DELAY_ON_BOOT_MS 1500 #define ONESHOT_FEATURE_CHANGED_DELAY_ON_BOOT_MS 1500

View file

@ -27,6 +27,7 @@ typedef struct gyro_s {
sensorReadFuncPtr temperature; // read temperature if available sensorReadFuncPtr temperature; // read temperature if available
sensorInterruptFuncPtr intStatus; sensorInterruptFuncPtr intStatus;
float scale; // scalefactor float scale; // scalefactor
uint32_t targetLooptime;
} gyro_t; } gyro_t;
typedef struct acc_s { typedef struct acc_s {

View file

@ -40,7 +40,7 @@ bool bma280Detect(acc_t *acc)
bool ack = false; bool ack = false;
uint8_t sig = 0; uint8_t sig = 0;
ack = i2cRead(MPU_I2C_INSTANCE, BMA280_ADDRESS, 0x00, 1, &sig); ack = i2cRead(MPU_I2C_INSTANCE, BMA280_ADDRESS, 0x00, 1, &sig);
if (!ack || sig != 0xFB) if (!ack || sig != 0xFB)
return false; return false;
@ -51,8 +51,8 @@ bool bma280Detect(acc_t *acc)
static void bma280Init(acc_t *acc) static void bma280Init(acc_t *acc)
{ {
i2cWrite(MPU_I2C_INSTANCE, BMA280_ADDRESS, BMA280_PMU_RANGE, 0x08); // +-8g range i2cWrite(MPU_I2C_INSTANCE, BMA280_ADDRESS, BMA280_PMU_RANGE, 0x08); // +-8g range
i2cWrite(MPU_I2C_INSTANCE, BMA280_ADDRESS, BMA280_PMU_BW, 0x0E); // 500Hz BW i2cWrite(MPU_I2C_INSTANCE, BMA280_ADDRESS, BMA280_PMU_BW, 0x0E); // 500Hz BW
acc->acc_1G = 512 * 8; acc->acc_1G = 512 * 8;
} }
@ -61,7 +61,7 @@ static bool bma280Read(int16_t *accelData)
{ {
uint8_t buf[6]; uint8_t buf[6];
if (!i2cRead(MPU_I2C_INSTANCE, BMA280_ADDRESS, BMA280_ACC_X_LSB, 6, buf)) { if (!i2cRead(MPU_I2C_INSTANCE, BMA280_ADDRESS, BMA280_ACC_X_LSB, 6, buf)) {
return false; return false;
} }

View file

@ -63,7 +63,7 @@ bool l3g4200dDetect(gyro_t *gyro)
delay(25); delay(25);
i2cRead(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_WHO_AM_I, 1, &deviceid); i2cRead(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_WHO_AM_I, 1, &deviceid);
if (deviceid != L3G4200D_ID) if (deviceid != L3G4200D_ID)
return false; return false;
@ -100,12 +100,12 @@ static void l3g4200dInit(uint8_t lpf)
delay(100); delay(100);
ack = i2cWrite(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_CTRL_REG4, L3G4200D_FS_SEL_2000DPS); ack = i2cWrite(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_CTRL_REG4, L3G4200D_FS_SEL_2000DPS);
if (!ack) if (!ack)
failureMode(FAILURE_ACC_INIT); failureMode(FAILURE_ACC_INIT);
delay(5); delay(5);
i2cWrite(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_CTRL_REG1, L3G4200D_POWER_ON | mpuLowPassFilter); i2cWrite(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_CTRL_REG1, L3G4200D_POWER_ON | mpuLowPassFilter);
} }
// Read 3 gyro values into user-provided buffer. No overrun checking is done. // Read 3 gyro values into user-provided buffer. No overrun checking is done.
@ -113,7 +113,7 @@ static bool l3g4200dRead(int16_t *gyroADC)
{ {
uint8_t buf[6]; uint8_t buf[6];
if (!i2cRead(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_AUTOINCR | L3G4200D_GYRO_OUT, 6, buf)) { if (!i2cRead(MPU_I2C_INSTANCE, L3G4200D_ADDRESS, L3G4200D_AUTOINCR | L3G4200D_GYRO_OUT, 6, buf)) {
return false; return false;
} }

View file

@ -62,7 +62,7 @@
#define BLOCK_DATA_UPDATE_CONTINUOUS ((uint8_t)0x00) #define BLOCK_DATA_UPDATE_CONTINUOUS ((uint8_t)0x00)
#define BLE_MSB ((uint8_t)0x40) #define BLE_MSB ((uint8_t)0x40)
#define BOOT ((uint8_t)0x80) #define BOOT ((uint8_t)0x80)
@ -76,7 +76,7 @@ static void l3gd20SpiInit(SPI_TypeDef *SPIx)
UNUSED(SPIx); // FIXME UNUSED(SPIx); // FIXME
mpul3gd20CsPin = IOGetByTag(IO_TAG(L3GD20_CS_PIN)); mpul3gd20CsPin = IOGetByTag(IO_TAG(L3GD20_CS_PIN));
IOInit(mpul3gd20CsPin, OWNER_SYSTEM, RESOURCE_SPI); IOInit(mpul3gd20CsPin, OWNER_MPU, RESOURCE_SPI_CS, 0);
IOConfigGPIO(mpul3gd20CsPin, SPI_IO_CS_CFG); IOConfigGPIO(mpul3gd20CsPin, SPI_IO_CS_CFG);
DISABLE_L3GD20; DISABLE_L3GD20;

View file

@ -19,14 +19,13 @@
#include <stdint.h> #include <stdint.h>
#include "platform.h" #include "platform.h"
#include "build_config.h"
#include "debug.h" #include "debug.h"
#include "common/maths.h" #include "common/maths.h"
#include "common/axis.h" #include "common/axis.h"
#include "system.h" #include "system.h"
#include "gpio.h" #include "io.h"
#include "bus_i2c.h" #include "bus_i2c.h"
#include "sensor.h" #include "sensor.h"
@ -115,15 +114,15 @@ int32_t accelSummedSamples500Hz[3];
void lsm303dlhcAccInit(acc_t *acc) void lsm303dlhcAccInit(acc_t *acc)
{ {
i2cWrite(MPU_I2C_INSTANCE, LSM303DLHC_ACCEL_ADDRESS, CTRL_REG5_A, BOOT); i2cWrite(MPU_I2C_INSTANCE, LSM303DLHC_ACCEL_ADDRESS, CTRL_REG5_A, BOOT);
delay(100); delay(100);
i2cWrite(MPU_I2C_INSTANCE, LSM303DLHC_ACCEL_ADDRESS, CTRL_REG1_A, ODR_1344_HZ | AXES_ENABLE); i2cWrite(MPU_I2C_INSTANCE, LSM303DLHC_ACCEL_ADDRESS, CTRL_REG1_A, ODR_1344_HZ | AXES_ENABLE);
delay(10); delay(10);
i2cWrite(MPU_I2C_INSTANCE, LSM303DLHC_ACCEL_ADDRESS, CTRL_REG4_A, FULLSCALE_4G); i2cWrite(MPU_I2C_INSTANCE, LSM303DLHC_ACCEL_ADDRESS, CTRL_REG4_A, FULLSCALE_4G);
delay(100); delay(100);

View file

@ -22,8 +22,7 @@
*/ */
/* LSM303DLHC ACC struct */ /* LSM303DLHC ACC struct */
typedef struct typedef struct {
{
uint8_t Power_Mode; /* Power-down/Normal Mode */ uint8_t Power_Mode; /* Power-down/Normal Mode */
uint8_t AccOutput_DataRate; /* OUT data rate */ uint8_t AccOutput_DataRate; /* OUT data rate */
uint8_t Axes_Enable; /* Axes enable */ uint8_t Axes_Enable; /* Axes enable */
@ -31,25 +30,23 @@ typedef struct
uint8_t BlockData_Update; /* Block Data Update */ uint8_t BlockData_Update; /* Block Data Update */
uint8_t Endianness; /* Endian Data selection */ uint8_t Endianness; /* Endian Data selection */
uint8_t AccFull_Scale; /* Full Scale selection */ uint8_t AccFull_Scale; /* Full Scale selection */
}LSM303DLHCAcc_InitTypeDef; } LSM303DLHCAcc_InitTypeDef;
/* LSM303DLHC Acc High Pass Filter struct */ /* LSM303DLHC Acc High Pass Filter struct */
typedef struct typedef struct {
{
uint8_t HighPassFilter_Mode_Selection; /* Internal filter mode */ uint8_t HighPassFilter_Mode_Selection; /* Internal filter mode */
uint8_t HighPassFilter_CutOff_Frequency; /* High pass filter cut-off frequency */ uint8_t HighPassFilter_CutOff_Frequency; /* High pass filter cut-off frequency */
uint8_t HighPassFilter_AOI1; /* HPF_enabling/disabling for AOI function on interrupt 1 */ uint8_t HighPassFilter_AOI1; /* HPF_enabling/disabling for AOI function on interrupt 1 */
uint8_t HighPassFilter_AOI2; /* HPF_enabling/disabling for AOI function on interrupt 2 */ uint8_t HighPassFilter_AOI2; /* HPF_enabling/disabling for AOI function on interrupt 2 */
}LSM303DLHCAcc_FilterConfigTypeDef; } LSM303DLHCAcc_FilterConfigTypeDef;
/* LSM303DLHC Mag struct */ /* LSM303DLHC Mag struct */
typedef struct typedef struct {
{
uint8_t Temperature_Sensor; /* Temperature sensor enable/disable */ uint8_t Temperature_Sensor; /* Temperature sensor enable/disable */
uint8_t MagOutput_DataRate; /* OUT data rate */ uint8_t MagOutput_DataRate; /* OUT data rate */
uint8_t Working_Mode; /* operating mode */ uint8_t Working_Mode; /* operating mode */
uint8_t MagFull_Scale; /* Full Scale selection */ uint8_t MagFull_Scale; /* Full Scale selection */
}LSM303DLHCMag_InitTypeDef; } LSM303DLHCMag_InitTypeDef;
/** /**
* @} * @}
*/ */
@ -78,43 +75,11 @@ typedef struct
* @brief LSM303DLHC I2C Interface pins * @brief LSM303DLHC I2C Interface pins
*/ */
#define LSM303DLHC_I2C I2C1 #define LSM303DLHC_I2C I2C1
#define LSM303DLHC_I2C_CLK RCC_APB1Periph_I2C1 #define LSM303DLHC_I2C_SCK_PIN PB6 /* PB.06 */
#define LSM303DLHC_I2C_SDA_PIN PB7 /* PB.7 */
#define LSM303DLHC_I2C_SCK_PIN GPIO_Pin_6 /* PB.06 */ #define LSM303DLHC_DRDY_PIN PE2 /* PE.02 */
#define LSM303DLHC_I2C_SCK_GPIO_PORT GPIOB /* GPIOB */ #define LSM303DLHC_I2C_INT1_PIN PE4 /* PE.04 */
#define LSM303DLHC_I2C_SCK_GPIO_CLK RCC_AHBPeriph_GPIOB #define LSM303DLHC_I2C_INT2_PIN PE5 /* PE.05 */
#define LSM303DLHC_I2C_SCK_SOURCE GPIO_PinSource6
#define LSM303DLHC_I2C_SCK_AF GPIO_AF_4
#define LSM303DLHC_I2C_SDA_PIN GPIO_Pin_7 /* PB.7 */
#define LSM303DLHC_I2C_SDA_GPIO_PORT GPIOB /* GPIOB */
#define LSM303DLHC_I2C_SDA_GPIO_CLK RCC_AHBPeriph_GPIOB
#define LSM303DLHC_I2C_SDA_SOURCE GPIO_PinSource7
#define LSM303DLHC_I2C_SDA_AF GPIO_AF_4
#define LSM303DLHC_DRDY_PIN GPIO_Pin_2 /* PE.02 */
#define LSM303DLHC_DRDY_GPIO_PORT GPIOE /* GPIOE */
#define LSM303DLHC_DRDY_GPIO_CLK RCC_AHBPeriph_GPIOE
#define LSM303DLHC_DRDY_EXTI_LINE EXTI_Line2
#define LSM303DLHC_DRDY_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
#define LSM303DLHC_DRDY_EXTI_PIN_SOURCE EXTI_PinSource2
#define LSM303DLHC_DRDY_EXTI_IRQn EXTI2_TS_IRQn
#define LSM303DLHC_I2C_INT1_PIN GPIO_Pin_4 /* PE.04 */
#define LSM303DLHC_I2C_INT1_GPIO_PORT GPIOE /* GPIOE */
#define LSM303DLHC_I2C_INT1_GPIO_CLK RCC_AHBPeriph_GPIOE
#define LSM303DLHC_I2C_INT1_EXTI_LINE EXTI_Line4
#define LSM303DLHC_I2C_INT1_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
#define LSM303DLHC_I2C_INT1_EXTI_PIN_SOURCE EXTI_PinSource4
#define LSM303DLHC_I2C_INT1_EXTI_IRQn EXTI4_IRQn
#define LSM303DLHC_I2C_INT2_PIN GPIO_Pin_5 /* PE.05 */
#define LSM303DLHC_I2C_INT2_GPIO_PORT GPIOE /* GPIOE */
#define LSM303DLHC_I2C_INT2_GPIO_CLK RCC_AHBPeriph_GPIOE
#define LSM303DLHC_I2C_INT2_EXTI_LINE EXTI_Line5
#define LSM303DLHC_I2C_INT2_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
#define LSM303DLHC_I2C_INT2_EXTI_PIN_SOURCE EXTI_PinSource5ss
#define LSM303DLHC_I2C_INT2_EXTI_IRQn EXTI9_5_IRQn
/******************************************************************************/ /******************************************************************************/
/*************************** START REGISTER MAPPING **************************/ /*************************** START REGISTER MAPPING **************************/

View file

@ -89,7 +89,7 @@ bool mma8452Detect(acc_t *acc)
bool ack = false; bool ack = false;
uint8_t sig = 0; uint8_t sig = 0;
ack = i2cRead(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_WHO_AM_I, 1, &sig); ack = i2cRead(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_WHO_AM_I, 1, &sig);
if (!ack || (sig != MMA8452_DEVICE_SIGNATURE && sig != MMA8451_DEVICE_SIGNATURE)) if (!ack || (sig != MMA8452_DEVICE_SIGNATURE && sig != MMA8451_DEVICE_SIGNATURE))
return false; return false;
@ -105,13 +105,13 @@ static inline void mma8451ConfigureInterrupt(void)
// PA5 - ACC_INT2 output on NAZE rev3/4 hardware // PA5 - ACC_INT2 output on NAZE rev3/4 hardware
// NAZE rev.5 hardware has PA5 (ADC1_IN5) on breakout pad on bottom of board // NAZE rev.5 hardware has PA5 (ADC1_IN5) on breakout pad on bottom of board
// OLIMEXINO - The PA5 pin is wired up to LED1, if you need to use an mma8452 on an Olimexino use a different pin and provide support in code. // OLIMEXINO - The PA5 pin is wired up to LED1, if you need to use an mma8452 on an Olimexino use a different pin and provide support in code.
IOInit(IOGetByTag(IO_TAG(PA5)), OWNER_SYSTEM, RESOURCE_I2C); IOInit(IOGetByTag(IO_TAG(PA5)), OWNER_MPU, RESOURCE_EXTI, 0);
IOConfigGPIO(IOGetByTag(IO_TAG(PA5)), IOCFG_IN_FLOATING); // TODO - maybe pullup / pulldown ? IOConfigGPIO(IOGetByTag(IO_TAG(PA5)), IOCFG_IN_FLOATING); // TODO - maybe pullup / pulldown ?
#endif #endif
i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG3, MMA8452_CTRL_REG3_IPOL); // Interrupt polarity (active HIGH) i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG3, MMA8452_CTRL_REG3_IPOL); // Interrupt polarity (active HIGH)
i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG4, MMA8452_CTRL_REG4_INT_EN_DRDY); // Enable DRDY interrupt (unused by this driver) i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG4, MMA8452_CTRL_REG4_INT_EN_DRDY); // Enable DRDY interrupt (unused by this driver)
i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG5, 0); // DRDY routed to INT2 i2cWrite(MPU_I2C_INSTANCE, MMA8452_ADDRESS, MMA8452_CTRL_REG5, 0); // DRDY routed to INT2
} }
static void mma8452Init(acc_t *acc) static void mma8452Init(acc_t *acc)

View file

@ -32,7 +32,6 @@
#include "gpio.h" #include "gpio.h"
#include "exti.h" #include "exti.h"
#include "bus_i2c.h" #include "bus_i2c.h"
#include "gyro_sync.h"
#include "sensor.h" #include "sensor.h"
#include "accgyro.h" #include "accgyro.h"
@ -228,43 +227,43 @@ void mpuIntExtiHandler(extiCallbackRec_t *cb)
void mpuIntExtiInit(void) void mpuIntExtiInit(void)
{ {
static bool mpuExtiInitDone = false; static bool mpuExtiInitDone = false;
if (mpuExtiInitDone || !mpuIntExtiConfig) { if (mpuExtiInitDone || !mpuIntExtiConfig) {
return; return;
} }
#if defined(USE_MPU_DATA_READY_SIGNAL) && defined(USE_EXTI) #if defined(USE_MPU_DATA_READY_SIGNAL) && defined(USE_EXTI)
IO_t mpuIntIO = IOGetByTag(mpuIntExtiConfig->tag); IO_t mpuIntIO = IOGetByTag(mpuIntExtiConfig->tag);
#ifdef ENSURE_MPU_DATA_READY_IS_LOW #ifdef ENSURE_MPU_DATA_READY_IS_LOW
uint8_t status = IORead(mpuIntIO); uint8_t status = IORead(mpuIntIO);
if (status) { if (status) {
return; return;
} }
#endif #endif
IOInit(mpuIntIO, OWNER_SYSTEM, RESOURCE_INPUT | RESOURCE_EXTI); IOInit(mpuIntIO, OWNER_MPU, RESOURCE_EXTI, 0);
IOConfigGPIO(mpuIntIO, IOCFG_IN_FLOATING); // TODO - maybe pullup / pulldown ? IOConfigGPIO(mpuIntIO, IOCFG_IN_FLOATING); // TODO - maybe pullup / pulldown ?
EXTIHandlerInit(&mpuIntCallbackRec, mpuIntExtiHandler); EXTIHandlerInit(&mpuIntCallbackRec, mpuIntExtiHandler);
EXTIConfig(mpuIntIO, &mpuIntCallbackRec, NVIC_PRIO_MPU_INT_EXTI, EXTI_Trigger_Rising); EXTIConfig(mpuIntIO, &mpuIntCallbackRec, NVIC_PRIO_MPU_INT_EXTI, EXTI_Trigger_Rising);
EXTIEnable(mpuIntIO, true); EXTIEnable(mpuIntIO, true);
#endif #endif
mpuExtiInitDone = true; mpuExtiInitDone = true;
} }
static bool mpuReadRegisterI2C(uint8_t reg, uint8_t length, uint8_t* data) static bool mpuReadRegisterI2C(uint8_t reg, uint8_t length, uint8_t* data)
{ {
bool ack = i2cRead(MPU_I2C_INSTANCE, MPU_ADDRESS, reg, length, data); bool ack = i2cRead(MPU_I2C_INSTANCE, MPU_ADDRESS, reg, length, data);
return ack; return ack;
} }
static bool mpuWriteRegisterI2C(uint8_t reg, uint8_t data) static bool mpuWriteRegisterI2C(uint8_t reg, uint8_t data)
{ {
bool ack = i2cWrite(MPU_I2C_INSTANCE, MPU_ADDRESS, reg, data); bool ack = i2cWrite(MPU_I2C_INSTANCE, MPU_ADDRESS, reg, data);
return ack; return ack;
} }
@ -300,11 +299,14 @@ bool mpuGyroRead(int16_t *gyroADC)
return true; return true;
} }
void checkMPUDataReady(bool *mpuDataReadyPtr) { bool checkMPUDataReady(void)
{
bool ret;
if (mpuDataReady) { if (mpuDataReady) {
*mpuDataReadyPtr = true; ret = true;
mpuDataReady= false; mpuDataReady= false;
} else { } else {
*mpuDataReadyPtr = false; ret = false;
} }
return ret;
} }

View file

@ -17,6 +17,8 @@
#pragma once #pragma once
#include "exti.h"
// MPU6050 // MPU6050
#define MPU_RA_WHO_AM_I 0x75 #define MPU_RA_WHO_AM_I 0x75
#define MPU_RA_WHO_AM_I_LEGACY 0x00 #define MPU_RA_WHO_AM_I_LEGACY 0x00
@ -120,12 +122,12 @@ typedef bool (*mpuWriteRegisterFunc)(uint8_t reg, uint8_t data);
typedef void(*mpuResetFuncPtr)(void); typedef void(*mpuResetFuncPtr)(void);
typedef struct mpuConfiguration_s { typedef struct mpuConfiguration_s {
uint8_t gyroReadXRegister; // Y and Z must registers follow this, 2 words each uint8_t gyroReadXRegister; // Y and Z must registers follow this, 2 words each
mpuReadRegisterFunc read; mpuReadRegisterFunc read;
mpuWriteRegisterFunc write; mpuWriteRegisterFunc write;
mpuReadRegisterFunc slowread; mpuReadRegisterFunc slowread;
mpuWriteRegisterFunc verifywrite; mpuWriteRegisterFunc verifywrite;
mpuResetFuncPtr reset; mpuResetFuncPtr reset;
} mpuConfiguration_t; } mpuConfiguration_t;
extern mpuConfiguration_t mpuConfiguration; extern mpuConfiguration_t mpuConfiguration;
@ -185,4 +187,4 @@ void mpuIntExtiInit(void);
bool mpuAccRead(int16_t *accData); bool mpuAccRead(int16_t *accData);
bool mpuGyroRead(int16_t *gyroADC); bool mpuGyroRead(int16_t *gyroADC);
mpuDetectionResult_t *detectMpu(const extiConfig_t *configToUse); mpuDetectionResult_t *detectMpu(const extiConfig_t *configToUse);
void checkMPUDataReady(bool *mpuDataReadyPtr); bool checkMPUDataReady(void);

View file

@ -30,7 +30,6 @@
#include "accgyro.h" #include "accgyro.h"
#include "accgyro_mpu.h" #include "accgyro_mpu.h"
#include "accgyro_mpu3050.h" #include "accgyro_mpu3050.h"
#include "gyro_sync.h"
// MPU3050, Standard address 0x68 // MPU3050, Standard address 0x68
#define MPU3050_ADDRESS 0x68 #define MPU3050_ADDRESS 0x68

View file

@ -1,4 +1,4 @@
/* /*
* This file is part of Cleanflight. * This file is part of Cleanflight.
* *
* Cleanflight is free software: you can redistribute it and/or modify * Cleanflight is free software: you can redistribute it and/or modify
@ -38,8 +38,6 @@
#include "accgyro_mpu.h" #include "accgyro_mpu.h"
#include "accgyro_mpu6050.h" #include "accgyro_mpu6050.h"
extern uint8_t mpuLowPassFilter;
//#define DEBUG_MPU_DATA_READY_INTERRUPT //#define DEBUG_MPU_DATA_READY_INTERRUPT
// MPU6050, Standard address 0x68 // MPU6050, Standard address 0x68

View file

@ -20,7 +20,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "platform.h" #include "platform.h"
#include "build_config.h"
#include "common/axis.h" #include "common/axis.h"
#include "common/maths.h" #include "common/maths.h"

View file

@ -24,7 +24,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
@ -41,6 +40,9 @@
#include "sensor.h" #include "sensor.h"
#include "accgyro.h" #include "accgyro.h"
#include "accgyro_mpu.h" #include "accgyro_mpu.h"
#if defined(USE_GYRO_SPI_MPU6000) || defined(USE_ACC_SPI_MPU6000)
#include "accgyro_spi_mpu6000.h" #include "accgyro_spi_mpu6000.h"
static void mpu6000AccAndGyroInit(void); static void mpu6000AccAndGyroInit(void);
@ -49,12 +51,12 @@ static bool mpuSpi6000InitDone = false;
// Bits // Bits
#define BIT_SLEEP 0x40 #define BIT_SLEEP 0x40
#define BIT_H_RESET 0x80 #define BIT_H_RESET 0x80
#define BITS_CLKSEL 0x07 #define BITS_CLKSEL 0x07
#define MPU_CLK_SEL_PLLGYROX 0x01 #define MPU_CLK_SEL_PLLGYROX 0x01
#define MPU_CLK_SEL_PLLGYROZ 0x03 #define MPU_CLK_SEL_PLLGYROZ 0x03
#define MPU_EXT_SYNC_GYROX 0x02 #define MPU_EXT_SYNC_GYROX 0x02
#define BITS_FS_250DPS 0x00 #define BITS_FS_250DPS 0x00
#define BITS_FS_500DPS 0x08 #define BITS_FS_500DPS 0x08
#define BITS_FS_1000DPS 0x10 #define BITS_FS_1000DPS 0x10
@ -74,9 +76,9 @@ static bool mpuSpi6000InitDone = false;
#define BITS_DLPF_CFG_2100HZ_NOLPF 0x07 #define BITS_DLPF_CFG_2100HZ_NOLPF 0x07
#define BITS_DLPF_CFG_MASK 0x07 #define BITS_DLPF_CFG_MASK 0x07
#define BIT_INT_ANYRD_2CLEAR 0x10 #define BIT_INT_ANYRD_2CLEAR 0x10
#define BIT_RAW_RDY_EN 0x01 #define BIT_RAW_RDY_EN 0x01
#define BIT_I2C_IF_DIS 0x10 #define BIT_I2C_IF_DIS 0x10
#define BIT_INT_STATUS_DATA 0x01 #define BIT_INT_STATUS_DATA 0x01
#define BIT_GYRO 3 #define BIT_GYRO 3
#define BIT_ACC 2 #define BIT_ACC 2
#define BIT_TEMP 1 #define BIT_TEMP 1
@ -159,7 +161,7 @@ bool mpu6000SpiDetect(void)
#ifdef MPU6000_CS_PIN #ifdef MPU6000_CS_PIN
mpuSpi6000CsPin = IOGetByTag(IO_TAG(MPU6000_CS_PIN)); mpuSpi6000CsPin = IOGetByTag(IO_TAG(MPU6000_CS_PIN));
#endif #endif
IOInit(mpuSpi6000CsPin, OWNER_SYSTEM, RESOURCE_SPI); IOInit(mpuSpi6000CsPin, OWNER_MPU, RESOURCE_SPI_CS, 0);
IOConfigGPIO(mpuSpi6000CsPin, SPI_IO_CS_CFG); IOConfigGPIO(mpuSpi6000CsPin, SPI_IO_CS_CFG);
spiSetDivisor(MPU6000_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); spiSetDivisor(MPU6000_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON);
@ -283,3 +285,5 @@ bool mpu6000SpiGyroDetect(gyro_t *gyro)
return true; return true;
} }
#endif

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#define MPU6000_CONFIG 0x1A #define MPU6000_CONFIG 0x1A
#define BITS_DLPF_CFG_256HZ 0x00 #define BITS_DLPF_CFG_256HZ 0x00
#define BITS_DLPF_CFG_188HZ 0x01 #define BITS_DLPF_CFG_188HZ 0x01

View file

@ -17,7 +17,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
@ -69,10 +68,10 @@ static void mpu6500SpiInit(void)
} }
mpuSpi6500CsPin = IOGetByTag(IO_TAG(MPU6500_CS_PIN)); mpuSpi6500CsPin = IOGetByTag(IO_TAG(MPU6500_CS_PIN));
IOInit(mpuSpi6500CsPin, OWNER_SYSTEM, RESOURCE_SPI); IOInit(mpuSpi6500CsPin, OWNER_MPU, RESOURCE_SPI_CS, 0);
IOConfigGPIO(mpuSpi6500CsPin, SPI_IO_CS_CFG); IOConfigGPIO(mpuSpi6500CsPin, SPI_IO_CS_CFG);
spiSetDivisor(MPU6500_SPI_INSTANCE, SPI_CLOCK_FAST); spiSetDivisor(MPU6500_SPI_INSTANCE, SPI_CLOCK_FAST);
hardwareInitialised = true; hardwareInitialised = true;
} }

View file

@ -25,7 +25,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
#include "light_led.h" #include "light_led.h"
@ -64,7 +63,7 @@ void mpu9250ResetGyro(void)
bool mpu9250WriteRegister(uint8_t reg, uint8_t data) bool mpu9250WriteRegister(uint8_t reg, uint8_t data)
{ {
ENABLE_MPU9250; ENABLE_MPU9250;
delayMicroseconds(1); delayMicroseconds(1);
spiTransferByte(MPU9250_SPI_INSTANCE, reg); spiTransferByte(MPU9250_SPI_INSTANCE, reg);
spiTransferByte(MPU9250_SPI_INSTANCE, data); spiTransferByte(MPU9250_SPI_INSTANCE, data);
@ -76,7 +75,7 @@ bool mpu9250WriteRegister(uint8_t reg, uint8_t data)
bool mpu9250ReadRegister(uint8_t reg, uint8_t length, uint8_t *data) bool mpu9250ReadRegister(uint8_t reg, uint8_t length, uint8_t *data)
{ {
ENABLE_MPU9250; ENABLE_MPU9250;
spiTransferByte(MPU9250_SPI_INSTANCE, reg | 0x80); // read transaction spiTransferByte(MPU9250_SPI_INSTANCE, reg | 0x80); // read transaction
spiTransfer(MPU9250_SPI_INSTANCE, data, NULL, length); spiTransfer(MPU9250_SPI_INSTANCE, data, NULL, length);
DISABLE_MPU9250; DISABLE_MPU9250;
@ -86,7 +85,7 @@ bool mpu9250ReadRegister(uint8_t reg, uint8_t length, uint8_t *data)
bool mpu9250SlowReadRegister(uint8_t reg, uint8_t length, uint8_t *data) bool mpu9250SlowReadRegister(uint8_t reg, uint8_t length, uint8_t *data)
{ {
ENABLE_MPU9250; ENABLE_MPU9250;
delayMicroseconds(1); delayMicroseconds(1);
spiTransferByte(MPU9250_SPI_INSTANCE, reg | 0x80); // read transaction spiTransferByte(MPU9250_SPI_INSTANCE, reg | 0x80); // read transaction
spiTransfer(MPU9250_SPI_INSTANCE, data, NULL, length); spiTransfer(MPU9250_SPI_INSTANCE, data, NULL, length);
@ -98,7 +97,7 @@ bool mpu9250SlowReadRegister(uint8_t reg, uint8_t length, uint8_t *data)
void mpu9250SpiGyroInit(uint8_t lpf) void mpu9250SpiGyroInit(uint8_t lpf)
{ {
(void)(lpf); (void)(lpf);
mpuIntExtiInit(); mpuIntExtiInit();
@ -126,55 +125,55 @@ void mpu9250SpiAccInit(acc_t *acc)
bool verifympu9250WriteRegister(uint8_t reg, uint8_t data) bool verifympu9250WriteRegister(uint8_t reg, uint8_t data)
{ {
uint8_t in; uint8_t in;
uint8_t attemptsRemaining = 20; uint8_t attemptsRemaining = 20;
mpu9250WriteRegister(reg, data); mpu9250WriteRegister(reg, data);
delayMicroseconds(100); delayMicroseconds(100);
do { do {
mpu9250SlowReadRegister(reg, 1, &in); mpu9250SlowReadRegister(reg, 1, &in);
if (in == data) { if (in == data) {
return true; return true;
} else { } else {
debug[3]++; debug[3]++;
mpu9250WriteRegister(reg, data); mpu9250WriteRegister(reg, data);
delayMicroseconds(100); delayMicroseconds(100);
} }
} while (attemptsRemaining--); } while (attemptsRemaining--);
return false; return false;
} }
static void mpu9250AccAndGyroInit(uint8_t lpf) { static void mpu9250AccAndGyroInit(uint8_t lpf) {
if (mpuSpi9250InitDone) { if (mpuSpi9250InitDone) {
return; return;
} }
spiSetDivisor(MPU9250_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); //low speed for writing to slow registers spiSetDivisor(MPU9250_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); //low speed for writing to slow registers
mpu9250WriteRegister(MPU_RA_PWR_MGMT_1, MPU9250_BIT_RESET); mpu9250WriteRegister(MPU_RA_PWR_MGMT_1, MPU9250_BIT_RESET);
delay(50); delay(50);
verifympu9250WriteRegister(MPU_RA_PWR_MGMT_1, INV_CLK_PLL); verifympu9250WriteRegister(MPU_RA_PWR_MGMT_1, INV_CLK_PLL);
verifympu9250WriteRegister(MPU_RA_GYRO_CONFIG, INV_FSR_2000DPS << 3 | FCB_DISABLED); //Fchoice_b defaults to 00 which makes fchoice 11 verifympu9250WriteRegister(MPU_RA_GYRO_CONFIG, INV_FSR_2000DPS << 3 | FCB_DISABLED); //Fchoice_b defaults to 00 which makes fchoice 11
if (lpf == 4) { if (lpf == 4) {
verifympu9250WriteRegister(MPU_RA_CONFIG, 1); //1KHz, 184DLPF verifympu9250WriteRegister(MPU_RA_CONFIG, 1); //1KHz, 184DLPF
} else if (lpf < 4) { } else if (lpf < 4) {
verifympu9250WriteRegister(MPU_RA_CONFIG, 7); //8KHz, 3600DLPF verifympu9250WriteRegister(MPU_RA_CONFIG, 7); //8KHz, 3600DLPF
} else if (lpf > 4) { } else if (lpf > 4) {
verifympu9250WriteRegister(MPU_RA_CONFIG, 0); //8KHz, 250DLPF verifympu9250WriteRegister(MPU_RA_CONFIG, 0); //8KHz, 250DLPF
} }
verifympu9250WriteRegister(MPU_RA_SMPLRT_DIV, gyroMPU6xxxGetDividerDrops()); // Get Divider Drops verifympu9250WriteRegister(MPU_RA_SMPLRT_DIV, gyroMPU6xxxGetDividerDrops()); // Get Divider Drops
verifympu9250WriteRegister(MPU_RA_ACCEL_CONFIG, INV_FSR_8G << 3); verifympu9250WriteRegister(MPU_RA_ACCEL_CONFIG, INV_FSR_8G << 3);
verifympu9250WriteRegister(MPU_RA_INT_PIN_CFG, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0); // INT_ANYRD_2CLEAR, BYPASS_EN verifympu9250WriteRegister(MPU_RA_INT_PIN_CFG, 0 << 7 | 0 << 6 | 0 << 5 | 1 << 4 | 0 << 3 | 0 << 2 | 1 << 1 | 0 << 0); // INT_ANYRD_2CLEAR, BYPASS_EN
#if defined(USE_MPU_DATA_READY_SIGNAL) #if defined(USE_MPU_DATA_READY_SIGNAL)
verifympu9250WriteRegister(MPU_RA_INT_ENABLE, 0x01); //this resets register MPU_RA_PWR_MGMT_1 and won't read back correctly. verifympu9250WriteRegister(MPU_RA_INT_ENABLE, 0x01); //this resets register MPU_RA_PWR_MGMT_1 and won't read back correctly.
#endif #endif
spiSetDivisor(MPU9250_SPI_INSTANCE, SPI_CLOCK_FAST); spiSetDivisor(MPU9250_SPI_INSTANCE, SPI_CLOCK_FAST);
@ -191,10 +190,10 @@ bool mpu9250SpiDetect(void)
#ifdef MPU9250_CS_PIN #ifdef MPU9250_CS_PIN
mpuSpi9250CsPin = IOGetByTag(IO_TAG(MPU9250_CS_PIN)); mpuSpi9250CsPin = IOGetByTag(IO_TAG(MPU9250_CS_PIN));
#endif #endif
IOInit(mpuSpi9250CsPin, OWNER_SYSTEM, RESOURCE_SPI); IOInit(mpuSpi9250CsPin, OWNER_MPU, RESOURCE_SPI_CS, 0);
IOConfigGPIO(mpuSpi9250CsPin, SPI_IO_CS_CFG); IOConfigGPIO(mpuSpi9250CsPin, SPI_IO_CS_CFG);
spiSetDivisor(MPU9250_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); //low speed spiSetDivisor(MPU9250_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); //low speed
mpu9250WriteRegister(MPU_RA_PWR_MGMT_1, MPU9250_BIT_RESET); mpu9250WriteRegister(MPU_RA_PWR_MGMT_1, MPU9250_BIT_RESET);
do { do {

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#define mpu9250_CONFIG 0x1A #define mpu9250_CONFIG 0x1A
/* We should probably use these. :) /* We should probably use these. :)
#define BITS_DLPF_CFG_256HZ 0x00 #define BITS_DLPF_CFG_256HZ 0x00

View file

@ -35,11 +35,11 @@ volatile uint16_t adcValues[ADC_CHANNEL_COUNT];
uint8_t adcChannelByTag(ioTag_t ioTag) uint8_t adcChannelByTag(ioTag_t ioTag)
{ {
for (uint8_t i = 0; i < ARRAYLEN(adcTagMap); i++) { for (uint8_t i = 0; i < ARRAYLEN(adcTagMap); i++) {
if (ioTag == adcTagMap[i].tag) if (ioTag == adcTagMap[i].tag)
return adcTagMap[i].channel; return adcTagMap[i].channel;
} }
return 0; return 0;
} }
uint16_t adcGetChannel(uint8_t channel) uint16_t adcGetChannel(uint8_t channel)

View file

@ -17,6 +17,8 @@
#pragma once #pragma once
#include "io.h"
typedef enum { typedef enum {
ADC_BATTERY = 0, ADC_BATTERY = 0,
ADC_RSSI = 1, ADC_RSSI = 1,
@ -28,6 +30,7 @@ typedef enum {
#define ADC_CHANNEL_COUNT (ADC_CHANNEL_MAX + 1) #define ADC_CHANNEL_COUNT (ADC_CHANNEL_MAX + 1)
typedef struct adc_config_s { typedef struct adc_config_s {
ioTag_t tag;
uint8_t adcChannel; // ADC1_INxx channel number uint8_t adcChannel; // ADC1_INxx channel number
uint8_t dmaIndex; // index into DMA buffer in case of sparse channels uint8_t dmaIndex; // index into DMA buffer in case of sparse channels
bool enabled; bool enabled;

View file

@ -81,7 +81,7 @@ void adcInit(drv_adc_config_t *init)
{ {
#if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN) #if !defined(VBAT_ADC_PIN) && !defined(EXTERNAL1_ADC_PIN) && !defined(RSSI_ADC_PIN) && !defined(CURRENT_METER_ADC_PIN)
UNUSED(init); UNUSED(init);
#endif #endif
uint8_t i; uint8_t i;
@ -91,45 +91,25 @@ void adcInit(drv_adc_config_t *init)
#ifdef VBAT_ADC_PIN #ifdef VBAT_ADC_PIN
if (init->enableVBat) { if (init->enableVBat) {
IOInit(IOGetByTag(IO_TAG(VBAT_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_BATTERY].tag = IO_TAG(VBAT_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(VBAT_ADC_PIN)), IO_CONFIG(GPIO_Mode_AIN, 0));
adcConfig[ADC_BATTERY].adcChannel = adcChannelByTag(IO_TAG(VBAT_ADC_PIN));
adcConfig[ADC_BATTERY].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_BATTERY].enabled = true;
adcConfig[ADC_BATTERY].sampleTime = ADC_SampleTime_239Cycles5;
} }
#endif #endif
#ifdef RSSI_ADC_PIN #ifdef RSSI_ADC_PIN
if (init->enableRSSI) { if (init->enableRSSI) {
IOInit(IOGetByTag(IO_TAG(RSSI_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_RSSI].tag = IO_TAG(RSSI_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(RSSI_ADC_PIN)), IO_CONFIG(GPIO_Mode_AIN, 0));
adcConfig[ADC_RSSI].adcChannel = adcChannelByTag(IO_TAG(RSSI_ADC_PIN));
adcConfig[ADC_RSSI].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_RSSI].enabled = true;
adcConfig[ADC_RSSI].sampleTime = ADC_SampleTime_239Cycles5;
} }
#endif #endif
#ifdef EXTERNAL1_ADC_PIN #ifdef EXTERNAL1_ADC_PIN
if (init->enableExternal1) { if (init->enableExternal1) {
IOInit(IOGetByTag(IO_TAG(EXTERNAL1_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_EXTERNAL1].tag = IO_TAG(EXTERNAL1_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(EXTERNAL1_ADC_PIN)), IO_CONFIG(GPIO_Mode_AIN, 0));
adcConfig[ADC_EXTERNAL1].adcChannel = adcChannelByTag(IO_TAG(EXTERNAL1_ADC_PIN));
adcConfig[ADC_EXTERNAL1].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_EXTERNAL1].enabled = true;
adcConfig[ADC_EXTERNAL1].sampleTime = ADC_SampleTime_239Cycles5;
} }
#endif #endif
#ifdef CURRENT_METER_ADC_PIN #ifdef CURRENT_METER_ADC_PIN
if (init->enableCurrentMeter) { if (init->enableCurrentMeter) {
IOInit(IOGetByTag(IO_TAG(CURRENT_METER_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_CURRENT].tag = IO_TAG(CURRENT_METER_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(CURRENT_METER_ADC_PIN)), IO_CONFIG(GPIO_Mode_AIN, 0));
adcConfig[ADC_CURRENT].adcChannel = adcChannelByTag(IO_TAG(CURRENT_METER_ADC_PIN));
adcConfig[ADC_CURRENT].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_CURRENT].enabled = true;
adcConfig[ADC_CURRENT].sampleTime = ADC_SampleTime_239Cycles5;
} }
#endif #endif
@ -139,12 +119,22 @@ void adcInit(drv_adc_config_t *init)
adcDevice_t adc = adcHardware[device]; adcDevice_t adc = adcHardware[device];
for (uint8_t i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].tag)
continue;
IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC, RESOURCE_ADC_BATTERY+i, 0);
IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_Mode_AIN, 0));
adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag);
adcConfig[i].dmaIndex = configuredAdcChannels++;
adcConfig[i].sampleTime = ADC_SampleTime_239Cycles5;
adcConfig[i].enabled = true;
}
RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI) RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI)
RCC_ClockCmd(adc.rccADC, ENABLE); RCC_ClockCmd(adc.rccADC, ENABLE);
RCC_ClockCmd(adc.rccDMA, ENABLE); RCC_ClockCmd(adc.rccDMA, ENABLE);
// FIXME ADC driver assumes all the GPIO was already placed in 'AIN' mode
DMA_DeInit(adc.DMAy_Channelx); DMA_DeInit(adc.DMAy_Channelx);
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
DMA_StructInit(&DMA_InitStructure); DMA_StructInit(&DMA_InitStructure);

View file

@ -107,53 +107,25 @@ void adcInit(drv_adc_config_t *init)
#ifdef VBAT_ADC_PIN #ifdef VBAT_ADC_PIN
if (init->enableVBat) { if (init->enableVBat) {
IOInit(IOGetByTag(IO_TAG(VBAT_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_BATTERY].tag = IO_TAG(VBAT_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(VBAT_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[ADC_BATTERY].adcChannel = adcChannelByTag(IO_TAG(VBAT_ADC_PIN));
adcConfig[ADC_BATTERY].dmaIndex = adcChannelCount;
adcConfig[ADC_BATTERY].sampleTime = ADC_SampleTime_601Cycles5;
adcConfig[ADC_BATTERY].enabled = true;
adcChannelCount++;
} }
#endif #endif
#ifdef RSSI_ADC_PIN #ifdef RSSI_ADC_PIN
if (init->enableRSSI) { if (init->enableRSSI) {
IOInit(IOGetByTag(IO_TAG(RSSI_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_RSSI].tag = IO_TAG(RSSI_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(RSSI_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[ADC_RSSI].adcChannel = adcChannelByTag(IO_TAG(RSSI_ADC_PIN));
adcConfig[ADC_RSSI].dmaIndex = adcChannelCount;
adcConfig[ADC_RSSI].sampleTime = ADC_SampleTime_601Cycles5;
adcConfig[ADC_RSSI].enabled = true;
adcChannelCount++;
} }
#endif #endif
#ifdef CURRENT_METER_ADC_GPIO #ifdef CURRENT_METER_ADC_PIN
if (init->enableCurrentMeter) { if (init->enableCurrentMeter) {
IOInit(IOGetByTag(IO_TAG(CURRENT_METER_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_CURRENT].tag = IO_TAG(CURRENT_METER_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(CURRENT_METER_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[ADC_CURRENT].adcChannel = adcChannelByTag(IO_TAG(CURRENT_METER_ADC_PIN));
adcConfig[ADC_CURRENT].dmaIndex = adcChannelCount;
adcConfig[ADC_CURRENT].sampleTime = ADC_SampleTime_601Cycles5;
adcConfig[ADC_CURRENT].enabled = true;
adcChannelCount++;
} }
#endif #endif
#ifdef EXTERNAL1_ADC_GPIO #ifdef EXTERNAL1_ADC_PIN
if (init->enableExternal1) { if (init->enableExternal1) {
IOInit(IOGetByTag(IO_TAG(EXTERNAL1_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_EXTERNAL1].tag = IO_TAG(EXTERNAL1_ADC_PIN);
IOConfigGPIO(IOGetByTag(IO_TAG(EXTERNAL1_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[ADC_EXTERNAL1].adcChannel = adcChannelByTag(IO_TAG(EXTERNAL1_ADC_PIN));
adcConfig[ADC_EXTERNAL1].dmaIndex = adcChannelCount;
adcConfig[ADC_EXTERNAL1].sampleTime = ADC_SampleTime_601Cycles5;
adcConfig[ADC_EXTERNAL1].enabled = true;
adcChannelCount++;
} }
#endif #endif
@ -163,6 +135,18 @@ void adcInit(drv_adc_config_t *init)
adcDevice_t adc = adcHardware[device]; adcDevice_t adc = adcHardware[device];
for (uint8_t i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].tag)
continue;
IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC, RESOURCE_ADC_BATTERY+i,0);
IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag);
adcConfig[i].dmaIndex = adcChannelCount++;
adcConfig[i].sampleTime = ADC_SampleTime_601Cycles5;
adcConfig[i].enabled = true;
}
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div256); // 72 MHz divided by 256 = 281.25 kHz RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div256); // 72 MHz divided by 256 = 281.25 kHz
RCC_ClockCmd(adc.rccADC, ENABLE); RCC_ClockCmd(adc.rccADC, ENABLE);
RCC_ClockCmd(adc.rccDMA, ENABLE); RCC_ClockCmd(adc.rccDMA, ENABLE);

View file

@ -39,8 +39,8 @@
#endif #endif
const adcDevice_t adcHardware[] = { const adcDevice_t adcHardware[] = {
{ .ADCx = ADC1, .rccADC = RCC_APB2(ADC1), .rccDMA = RCC_AHB1(DMA2), .DMAy_Streamx = DMA2_Stream4, .channel = DMA_Channel_0 }, { .ADCx = ADC1, .rccADC = RCC_APB2(ADC1), .rccDMA = RCC_AHB1(DMA2), .DMAy_Streamx = DMA2_Stream4, .channel = DMA_Channel_0 },
//{ .ADCx = ADC2, .rccADC = RCC_APB2(ADC2), .rccDMA = RCC_AHB1(DMA2), .DMAy_Streamx = DMA2_Stream1, .channel = DMA_Channel_0 } //{ .ADCx = ADC2, .rccADC = RCC_APB2(ADC2), .rccDMA = RCC_AHB1(DMA2), .DMAy_Streamx = DMA2_Stream1, .channel = DMA_Channel_0 }
}; };
/* note these could be packed up for saving space */ /* note these could be packed up for saving space */
@ -75,13 +75,13 @@ const adcTagMap_t adcTagMap[] = {
ADCDevice adcDeviceByInstance(ADC_TypeDef *instance) ADCDevice adcDeviceByInstance(ADC_TypeDef *instance)
{ {
if (instance == ADC1) if (instance == ADC1)
return ADCDEV_1; return ADCDEV_1;
/* /*
if (instance == ADC2) // TODO add ADC2 and 3 if (instance == ADC2) // TODO add ADC2 and 3
return ADCDEV_2; return ADCDEV_2;
*/ */
return ADCINVALID; return ADCINVALID;
} }
void adcInit(drv_adc_config_t *init) void adcInit(drv_adc_config_t *init)
@ -100,45 +100,25 @@ void adcInit(drv_adc_config_t *init)
#ifdef VBAT_ADC_PIN #ifdef VBAT_ADC_PIN
if (init->enableVBat) { if (init->enableVBat) {
IOInit(IOGetByTag(IO_TAG(VBAT_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_BATTERY].tag = IO_TAG(VBAT_ADC_PIN); //VBAT_ADC_CHANNEL;
IOConfigGPIO(IOGetByTag(IO_TAG(VBAT_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[ADC_BATTERY].adcChannel = adcChannelByTag(IO_TAG(VBAT_ADC_PIN)); //VBAT_ADC_CHANNEL;
adcConfig[ADC_BATTERY].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_BATTERY].enabled = true;
adcConfig[ADC_BATTERY].sampleTime = ADC_SampleTime_480Cycles;
}
#endif
#ifdef EXTERNAL1_ADC_PIN
if (init->enableExternal1) {
IOInit(IOGetByTag(IO_TAG(EXTERNAL1_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC);
IOConfigGPIO(IOGetByTag(IO_TAG(EXTERNAL1_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[ADC_EXTERNAL1].adcChannel = adcChannelByTag(IO_TAG(EXTERNAL1_ADC_PIN)); //EXTERNAL1_ADC_CHANNEL;
adcConfig[ADC_EXTERNAL1].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_EXTERNAL1].enabled = true;
adcConfig[ADC_EXTERNAL1].sampleTime = ADC_SampleTime_480Cycles;
} }
#endif #endif
#ifdef RSSI_ADC_PIN #ifdef RSSI_ADC_PIN
if (init->enableRSSI) { if (init->enableRSSI) {
IOInit(IOGetByTag(IO_TAG(RSSI_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_RSSI].tag = IO_TAG(RSSI_ADC_PIN); //RSSI_ADC_CHANNEL;
IOConfigGPIO(IOGetByTag(IO_TAG(RSSI_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL)); }
adcConfig[ADC_RSSI].adcChannel = adcChannelByTag(IO_TAG(RSSI_ADC_PIN)); //RSSI_ADC_CHANNEL; #endif
adcConfig[ADC_RSSI].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_RSSI].enabled = true; #ifdef EXTERNAL1_ADC_PIN
adcConfig[ADC_RSSI].sampleTime = ADC_SampleTime_480Cycles; if (init->enableExternal1) {
adcConfig[ADC_EXTERNAL1].tag = IO_TAG(EXTERNAL1_ADC_PIN); //EXTERNAL1_ADC_CHANNEL;
} }
#endif #endif
#ifdef CURRENT_METER_ADC_PIN #ifdef CURRENT_METER_ADC_PIN
if (init->enableCurrentMeter) { if (init->enableCurrentMeter) {
IOInit(IOGetByTag(IO_TAG(CURRENT_METER_ADC_PIN)), OWNER_SYSTEM, RESOURCE_ADC); adcConfig[ADC_CURRENT].tag = IO_TAG(CURRENT_METER_ADC_PIN); //CURRENT_METER_ADC_CHANNEL;
IOConfigGPIO(IOGetByTag(IO_TAG(CURRENT_METER_ADC_PIN)), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[ADC_CURRENT].adcChannel = adcChannelByTag(IO_TAG(CURRENT_METER_ADC_PIN)); //CURRENT_METER_ADC_CHANNEL;
adcConfig[ADC_CURRENT].dmaIndex = configuredAdcChannels++;
adcConfig[ADC_CURRENT].enabled = true;
adcConfig[ADC_CURRENT].sampleTime = ADC_SampleTime_480Cycles;
} }
#endif #endif
@ -150,6 +130,18 @@ void adcInit(drv_adc_config_t *init)
adcDevice_t adc = adcHardware[device]; adcDevice_t adc = adcHardware[device];
for (uint8_t i = 0; i < ADC_CHANNEL_COUNT; i++) {
if (!adcConfig[i].tag)
continue;
IOInit(IOGetByTag(adcConfig[i].tag), OWNER_ADC, RESOURCE_ADC_BATTERY + i, 0);
IOConfigGPIO(IOGetByTag(adcConfig[i].tag), IO_CONFIG(GPIO_Mode_AN, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL));
adcConfig[i].adcChannel = adcChannelByTag(adcConfig[i].tag);
adcConfig[i].dmaIndex = configuredAdcChannels++;
adcConfig[i].sampleTime = ADC_SampleTime_480Cycles;
adcConfig[i].enabled = true;
}
RCC_ClockCmd(adc.rccDMA, ENABLE); RCC_ClockCmd(adc.rccDMA, ENABLE);
RCC_ClockCmd(adc.rccADC, ENABLE); RCC_ClockCmd(adc.rccADC, ENABLE);
@ -174,21 +166,21 @@ void adcInit(drv_adc_config_t *init)
ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonStructInit(&ADC_CommonInitStructure); ADC_CommonStructInit(&ADC_CommonInitStructure);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure); ADC_CommonInit(&ADC_CommonInitStructure);
ADC_StructInit(&ADC_InitStructure); ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = configuredAdcChannels; ADC_InitStructure.ADC_NbrOfConversion = configuredAdcChannels;
ADC_InitStructure.ADC_ScanConvMode = configuredAdcChannels > 1 ? ENABLE : DISABLE; // 1=scan more that one channel in group ADC_InitStructure.ADC_ScanConvMode = configuredAdcChannels > 1 ? ENABLE : DISABLE; // 1=scan more that one channel in group
ADC_Init(adc.ADCx, &ADC_InitStructure); ADC_Init(adc.ADCx, &ADC_InitStructure);

View file

@ -45,8 +45,8 @@ static bool isEOCConnected = true;
// EXTI14 for BMP085 End of Conversion Interrupt // EXTI14 for BMP085 End of Conversion Interrupt
void bmp085_extiHandler(extiCallbackRec_t* cb) void bmp085_extiHandler(extiCallbackRec_t* cb)
{ {
UNUSED(cb); UNUSED(cb);
isConversionComplete = true; isConversionComplete = true;
} }
bool bmp085TestEOCConnected(const bmp085Config_t *config); bool bmp085TestEOCConnected(const bmp085Config_t *config);
@ -143,7 +143,7 @@ void bmp085InitXclrIO(const bmp085Config_t *config)
{ {
if (!xclrIO && config && config->xclrIO) { if (!xclrIO && config && config->xclrIO) {
xclrIO = IOGetByTag(config->xclrIO); xclrIO = IOGetByTag(config->xclrIO);
IOInit(xclrIO, OWNER_SYSTEM, RESOURCE_OUTPUT); IOInit(xclrIO, OWNER_BARO, RESOURCE_OUTPUT, 0);
IOConfigGPIO(xclrIO, IOCFG_OUT_PP); IOConfigGPIO(xclrIO, IOCFG_OUT_PP);
} }
} }
@ -184,13 +184,13 @@ bool bmp085Detect(const bmp085Config_t *config, baro_t *baro)
delay(20); // datasheet says 10ms, we'll be careful and do 20. delay(20); // datasheet says 10ms, we'll be careful and do 20.
ack = i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_CHIP_ID__REG, 1, &data); /* read Chip Id */ ack = i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_CHIP_ID__REG, 1, &data); /* read Chip Id */
if (ack) { if (ack) {
bmp085.chip_id = BMP085_GET_BITSLICE(data, BMP085_CHIP_ID); bmp085.chip_id = BMP085_GET_BITSLICE(data, BMP085_CHIP_ID);
bmp085.oversampling_setting = 3; bmp085.oversampling_setting = 3;
if (bmp085.chip_id == BMP085_CHIP_ID) { /* get bitslice */ if (bmp085.chip_id == BMP085_CHIP_ID) { /* get bitslice */
i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_VERSION_REG, 1, &data); /* read Version reg */ i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_VERSION_REG, 1, &data); /* read Version reg */
bmp085.ml_version = BMP085_GET_BITSLICE(data, BMP085_ML_VERSION); /* get ML Version */ bmp085.ml_version = BMP085_GET_BITSLICE(data, BMP085_ML_VERSION); /* get ML Version */
bmp085.al_version = BMP085_GET_BITSLICE(data, BMP085_AL_VERSION); /* get AL Version */ bmp085.al_version = BMP085_GET_BITSLICE(data, BMP085_AL_VERSION); /* get AL Version */
bmp085_get_cal_param(); /* readout bmp085 calibparam structure */ bmp085_get_cal_param(); /* readout bmp085 calibparam structure */
@ -277,7 +277,7 @@ static void bmp085_start_ut(void)
#if defined(BARO_EOC_GPIO) #if defined(BARO_EOC_GPIO)
isConversionComplete = false; isConversionComplete = false;
#endif #endif
i2cWrite(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_CTRL_MEAS_REG, BMP085_T_MEASURE); i2cWrite(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_CTRL_MEAS_REG, BMP085_T_MEASURE);
} }
static void bmp085_get_ut(void) static void bmp085_get_ut(void)
@ -291,7 +291,7 @@ static void bmp085_get_ut(void)
} }
#endif #endif
i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_ADC_OUT_MSB_REG, 2, data); i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_ADC_OUT_MSB_REG, 2, data);
bmp085_ut = (data[0] << 8) | data[1]; bmp085_ut = (data[0] << 8) | data[1];
} }
@ -305,7 +305,7 @@ static void bmp085_start_up(void)
isConversionComplete = false; isConversionComplete = false;
#endif #endif
i2cWrite(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_CTRL_MEAS_REG, ctrl_reg_data); i2cWrite(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_CTRL_MEAS_REG, ctrl_reg_data);
} }
/** read out up for pressure conversion /** read out up for pressure conversion
@ -323,7 +323,7 @@ static void bmp085_get_up(void)
} }
#endif #endif
i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_ADC_OUT_MSB_REG, 3, data); i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_ADC_OUT_MSB_REG, 3, data);
bmp085_up = (((uint32_t) data[0] << 16) | ((uint32_t) data[1] << 8) | (uint32_t) data[2]) bmp085_up = (((uint32_t) data[0] << 16) | ((uint32_t) data[1] << 8) | (uint32_t) data[2])
>> (8 - bmp085.oversampling_setting); >> (8 - bmp085.oversampling_setting);
} }
@ -343,7 +343,7 @@ STATIC_UNIT_TESTED void bmp085_calculate(int32_t *pressure, int32_t *temperature
static void bmp085_get_cal_param(void) static void bmp085_get_cal_param(void)
{ {
uint8_t data[22]; uint8_t data[22];
i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_PROM_START__ADDR, BMP085_PROM_DATA__LEN, data); i2cRead(BARO_I2C_INSTANCE, BMP085_I2C_ADDR, BMP085_PROM_START__ADDR, BMP085_PROM_DATA__LEN, data);
/*parameters AC1-AC6*/ /*parameters AC1-AC6*/
bmp085.cal_param.ac1 = (data[0] << 8) | data[1]; bmp085.cal_param.ac1 = (data[0] << 8) | data[1];

View file

@ -18,8 +18,8 @@
#pragma once #pragma once
typedef struct bmp085Config_s { typedef struct bmp085Config_s {
ioTag_t xclrIO; ioTag_t xclrIO;
ioTag_t eocIO; ioTag_t eocIO;
} bmp085Config_t; } bmp085Config_t;
bool bmp085Detect(const bmp085Config_t *config, baro_t *baro); bool bmp085Detect(const bmp085Config_t *config, baro_t *baro);

View file

@ -83,14 +83,14 @@ bool bmp280Detect(baro_t *baro)
// set oversampling + power mode (forced), and start sampling // set oversampling + power mode (forced), and start sampling
bmp280WriteRegister(BMP280_CTRL_MEAS_REG, BMP280_MODE); bmp280WriteRegister(BMP280_CTRL_MEAS_REG, BMP280_MODE);
#else #else
i2cRead(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_CHIP_ID_REG, 1, &bmp280_chip_id); /* read Chip Id */ i2cRead(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_CHIP_ID_REG, 1, &bmp280_chip_id); /* read Chip Id */
if (bmp280_chip_id != BMP280_DEFAULT_CHIP_ID) if (bmp280_chip_id != BMP280_DEFAULT_CHIP_ID)
return false; return false;
// read calibration // read calibration
i2cRead(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, 24, (uint8_t *)&bmp280_cal); i2cRead(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, 24, (uint8_t *)&bmp280_cal);
// set oversampling + power mode (forced), and start sampling // set oversampling + power mode (forced), and start sampling
i2cWrite(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE); i2cWrite(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE);
#endif #endif
bmp280InitDone = true; bmp280InitDone = true;
@ -129,7 +129,7 @@ static void bmp280_start_up(void)
{ {
// start measurement // start measurement
// set oversampling + power mode (forced), and start sampling // set oversampling + power mode (forced), and start sampling
i2cWrite(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE); i2cWrite(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE);
} }
static void bmp280_get_up(void) static void bmp280_get_up(void)
@ -137,7 +137,7 @@ static void bmp280_get_up(void)
uint8_t data[BMP280_DATA_FRAME_SIZE]; uint8_t data[BMP280_DATA_FRAME_SIZE];
// read data from sensor // read data from sensor
i2cRead(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_PRESSURE_MSB_REG, BMP280_DATA_FRAME_SIZE, data); i2cRead(BARO_I2C_INSTANCE, BMP280_I2C_ADDR, BMP280_PRESSURE_MSB_REG, BMP280_DATA_FRAME_SIZE, data);
bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4)); bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));
bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4)); bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4));
} }

View file

@ -67,7 +67,7 @@ bool ms5611Detect(baro_t *baro)
delay(10); // No idea how long the chip takes to power-up, but let's make it 10ms delay(10); // No idea how long the chip takes to power-up, but let's make it 10ms
ack = i2cRead(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_PROM_RD, 1, &sig); ack = i2cRead(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_PROM_RD, 1, &sig);
if (!ack) if (!ack)
return false; return false;
@ -93,14 +93,14 @@ bool ms5611Detect(baro_t *baro)
static void ms5611_reset(void) static void ms5611_reset(void)
{ {
i2cWrite(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_RESET, 1); i2cWrite(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_RESET, 1);
delayMicroseconds(2800); delayMicroseconds(2800);
} }
static uint16_t ms5611_prom(int8_t coef_num) static uint16_t ms5611_prom(int8_t coef_num)
{ {
uint8_t rxbuf[2] = { 0, 0 }; uint8_t rxbuf[2] = { 0, 0 };
i2cRead(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_PROM_RD + coef_num * 2, 2, rxbuf); // send PROM READ command i2cRead(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_PROM_RD + coef_num * 2, 2, rxbuf); // send PROM READ command
return rxbuf[0] << 8 | rxbuf[1]; return rxbuf[0] << 8 | rxbuf[1];
} }
@ -137,13 +137,13 @@ STATIC_UNIT_TESTED int8_t ms5611_crc(uint16_t *prom)
static uint32_t ms5611_read_adc(void) static uint32_t ms5611_read_adc(void)
{ {
uint8_t rxbuf[3]; uint8_t rxbuf[3];
i2cRead(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_ADC_READ, 3, rxbuf); // read ADC i2cRead(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_ADC_READ, 3, rxbuf); // read ADC
return (rxbuf[0] << 16) | (rxbuf[1] << 8) | rxbuf[2]; return (rxbuf[0] << 16) | (rxbuf[1] << 8) | rxbuf[2];
} }
static void ms5611_start_ut(void) static void ms5611_start_ut(void)
{ {
i2cWrite(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D2 + ms5611_osr, 1); // D2 (temperature) conversion start! i2cWrite(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D2 + ms5611_osr, 1); // D2 (temperature) conversion start!
} }
static void ms5611_get_ut(void) static void ms5611_get_ut(void)
@ -153,7 +153,7 @@ static void ms5611_get_ut(void)
static void ms5611_start_up(void) static void ms5611_start_up(void)
{ {
i2cWrite(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D1 + ms5611_osr, 1); // D1 (pressure) conversion start! i2cWrite(BARO_I2C_INSTANCE, MS5611_ADDR, CMD_ADC_CONV + CMD_ADC_D1 + ms5611_osr, 1); // D1 (pressure) conversion start!
} }
static void ms5611_get_up(void) static void ms5611_get_up(void)

View file

@ -17,17 +17,15 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <platform.h> #include <platform.h>
#include "build_config.h"
#include "bus_spi.h" #include "bus_spi.h"
#include "barometer.h" #include "barometer.h"
#include "barometer_bmp280.h" #include "barometer_bmp280.h"
#ifdef USE_BARO_SPI_BMP280
#define DISABLE_BMP280 IOHi(bmp280CsPin) #define DISABLE_BMP280 IOHi(bmp280CsPin)
#define ENABLE_BMP280 IOLo(bmp280CsPin) #define ENABLE_BMP280 IOLo(bmp280CsPin)
@ -65,7 +63,7 @@ void bmp280SpiInit(void)
} }
bmp280CsPin = IOGetByTag(IO_TAG(BMP280_CS_PIN)); bmp280CsPin = IOGetByTag(IO_TAG(BMP280_CS_PIN));
IOInit(bmp280CsPin, OWNER_BARO, RESOURCE_SPI); IOInit(bmp280CsPin, OWNER_BARO, RESOURCE_SPI_CS, 0);
IOConfigGPIO(bmp280CsPin, IOCFG_OUT_PP); IOConfigGPIO(bmp280CsPin, IOCFG_OUT_PP);
DISABLE_BMP280; DISABLE_BMP280;
@ -91,3 +89,4 @@ void bmp280_spi_get_up(void)
bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4)); bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));
bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4)); bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4));
} }
#endif

View file

@ -48,218 +48,218 @@ static volatile uint16_t i2cErrorCount = 0;
static void I2C_delay(void) static void I2C_delay(void)
{ {
volatile int i = 7; volatile int i = 7;
while (i) { while (i) {
i--; i--;
} }
} }
static bool I2C_Start(void) static bool I2C_Start(void)
{ {
SDA_H; SDA_H;
SCL_H; SCL_H;
I2C_delay(); I2C_delay();
if (!SDA_read) { if (!SDA_read) {
return false; return false;
} }
SDA_L; SDA_L;
I2C_delay(); I2C_delay();
if (SDA_read) { if (SDA_read) {
return false; return false;
} }
SDA_L; SDA_L;
I2C_delay(); I2C_delay();
return true; return true;
} }
static void I2C_Stop(void) static void I2C_Stop(void)
{ {
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
SDA_L; SDA_L;
I2C_delay(); I2C_delay();
SCL_H; SCL_H;
I2C_delay(); I2C_delay();
SDA_H; SDA_H;
I2C_delay(); I2C_delay();
} }
static void I2C_Ack(void) static void I2C_Ack(void)
{ {
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
SDA_L; SDA_L;
I2C_delay(); I2C_delay();
SCL_H; SCL_H;
I2C_delay(); I2C_delay();
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
} }
static void I2C_NoAck(void) static void I2C_NoAck(void)
{ {
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
SDA_H; SDA_H;
I2C_delay(); I2C_delay();
SCL_H; SCL_H;
I2C_delay(); I2C_delay();
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
} }
static bool I2C_WaitAck(void) static bool I2C_WaitAck(void)
{ {
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
SDA_H; SDA_H;
I2C_delay(); I2C_delay();
SCL_H; SCL_H;
I2C_delay(); I2C_delay();
if (SDA_read) { if (SDA_read) {
SCL_L; SCL_L;
return false; return false;
} }
SCL_L; SCL_L;
return true; return true;
} }
static void I2C_SendByte(uint8_t byte) static void I2C_SendByte(uint8_t byte)
{ {
uint8_t i = 8; uint8_t i = 8;
while (i--) { while (i--) {
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
if (byte & 0x80) { if (byte & 0x80) {
SDA_H; SDA_H;
} }
else { else {
SDA_L; SDA_L;
} }
byte <<= 1; byte <<= 1;
I2C_delay(); I2C_delay();
SCL_H; SCL_H;
I2C_delay(); I2C_delay();
} }
SCL_L; SCL_L;
} }
static uint8_t I2C_ReceiveByte(void) static uint8_t I2C_ReceiveByte(void)
{ {
uint8_t i = 8; uint8_t i = 8;
uint8_t byte = 0; uint8_t byte = 0;
SDA_H; SDA_H;
while (i--) { while (i--) {
byte <<= 1; byte <<= 1;
SCL_L; SCL_L;
I2C_delay(); I2C_delay();
SCL_H; SCL_H;
I2C_delay(); I2C_delay();
if (SDA_read) { if (SDA_read) {
byte |= 0x01; byte |= 0x01;
} }
} }
SCL_L; SCL_L;
return byte; return byte;
} }
void i2cInit(I2CDevice device) void i2cInit(I2CDevice device)
{ {
UNUSED(device); UNUSED(device);
scl = IOGetByTag(IO_TAG(SOFT_I2C_SCL)); scl = IOGetByTag(IO_TAG(SOFT_I2C_SCL));
sda = IOGetByTag(IO_TAG(SOFT_I2C_SDA)); sda = IOGetByTag(IO_TAG(SOFT_I2C_SDA));
IOConfigGPIO(scl, IOCFG_OUT_OD); IOConfigGPIO(scl, IOCFG_OUT_OD);
IOConfigGPIO(sda, IOCFG_OUT_OD); IOConfigGPIO(sda, IOCFG_OUT_OD);
} }
bool i2cWriteBuffer(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t len, uint8_t * data) bool i2cWriteBuffer(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t len, uint8_t * data)
{ {
UNUSED(device); UNUSED(device);
int i; int i;
if (!I2C_Start()) { if (!I2C_Start()) {
i2cErrorCount++; i2cErrorCount++;
return false; return false;
} }
I2C_SendByte(addr << 1 | I2C_Direction_Transmitter); I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
if (!I2C_WaitAck()) { if (!I2C_WaitAck()) {
I2C_Stop(); I2C_Stop();
return false; return false;
} }
I2C_SendByte(reg); I2C_SendByte(reg);
I2C_WaitAck(); I2C_WaitAck();
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
I2C_SendByte(data[i]); I2C_SendByte(data[i]);
if (!I2C_WaitAck()) { if (!I2C_WaitAck()) {
I2C_Stop(); I2C_Stop();
i2cErrorCount++; i2cErrorCount++;
return false; return false;
} }
} }
I2C_Stop(); I2C_Stop();
return true; return true;
} }
bool i2cWrite(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t data) bool i2cWrite(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t data)
{ {
UNUSED(device); UNUSED(device);
if (!I2C_Start()) { if (!I2C_Start()) {
return false; return false;
} }
I2C_SendByte(addr << 1 | I2C_Direction_Transmitter); I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
if (!I2C_WaitAck()) { if (!I2C_WaitAck()) {
I2C_Stop(); I2C_Stop();
i2cErrorCount++; i2cErrorCount++;
return false; return false;
} }
I2C_SendByte(reg); I2C_SendByte(reg);
I2C_WaitAck(); I2C_WaitAck();
I2C_SendByte(data); I2C_SendByte(data);
I2C_WaitAck(); I2C_WaitAck();
I2C_Stop(); I2C_Stop();
return true; return true;
} }
bool i2cRead(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf) bool i2cRead(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf)
{ {
UNUSED(device); UNUSED(device);
if (!I2C_Start()) { if (!I2C_Start()) {
return false; return false;
} }
I2C_SendByte(addr << 1 | I2C_Direction_Transmitter); I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
if (!I2C_WaitAck()) { if (!I2C_WaitAck()) {
I2C_Stop(); I2C_Stop();
i2cErrorCount++; i2cErrorCount++;
return false; return false;
} }
I2C_SendByte(reg); I2C_SendByte(reg);
I2C_WaitAck(); I2C_WaitAck();
I2C_Start(); I2C_Start();
I2C_SendByte(addr << 1 | I2C_Direction_Receiver); I2C_SendByte(addr << 1 | I2C_Direction_Receiver);
I2C_WaitAck(); I2C_WaitAck();
while (len) { while (len) {
*buf = I2C_ReceiveByte(); *buf = I2C_ReceiveByte();
if (len == 1) { if (len == 1) {
I2C_NoAck(); I2C_NoAck();
} }
else { else {
I2C_Ack(); I2C_Ack();
} }
buf++; buf++;
len--; len--;
} }
I2C_Stop(); I2C_Stop();
return true; return true;
} }
uint16_t i2cGetErrorCounter(void) uint16_t i2cGetErrorCounter(void)
{ {
return i2cErrorCount; return i2cErrorCount;
} }
#endif #endif

View file

@ -21,8 +21,6 @@
#include <platform.h> #include <platform.h>
#include "build_config.h"
#include "io.h" #include "io.h"
#include "system.h" #include "system.h"
@ -385,8 +383,8 @@ void i2cInit(I2CDevice device)
IO_t scl = IOGetByTag(i2c->scl); IO_t scl = IOGetByTag(i2c->scl);
IO_t sda = IOGetByTag(i2c->sda); IO_t sda = IOGetByTag(i2c->sda);
IOInit(scl, OWNER_SYSTEM, RESOURCE_I2C); IOInit(scl, OWNER_I2C, RESOURCE_I2C_SCL, RESOURCE_INDEX(device));
IOInit(sda, OWNER_SYSTEM, RESOURCE_I2C); IOInit(sda, OWNER_I2C, RESOURCE_I2C_SDA, RESOURCE_INDEX(device));
// Enable RCC // Enable RCC
RCC_ClockCmd(i2c->rcc, ENABLE); RCC_ClockCmd(i2c->rcc, ENABLE);
@ -423,6 +421,9 @@ void i2cInit(I2CDevice device)
I2C_Cmd(i2c->dev, ENABLE); I2C_Cmd(i2c->dev, ENABLE);
I2C_Init(i2c->dev, &i2cInit); I2C_Init(i2c->dev, &i2cInit);
I2C_StretchClockCmd(i2c->dev, ENABLE);
// I2C ER Interrupt // I2C ER Interrupt
nvic.NVIC_IRQChannel = i2c->er_irq; nvic.NVIC_IRQChannel = i2c->er_irq;
nvic.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_ER); nvic.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_ER);

View file

@ -17,12 +17,9 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <platform.h> #include <platform.h>
#include "build_config.h"
#include "gpio.h" #include "gpio.h"
#include "system.h" #include "system.h"
#include "drivers/io_impl.h" #include "drivers/io_impl.h"
@ -31,6 +28,15 @@
#ifndef SOFT_I2C #ifndef SOFT_I2C
#if defined(USE_I2C_PULLUP)
#define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_OD, GPIO_PuPd_UP)
#else
#define IOCFG_I2C IOCFG_AF_OD
#endif
#define I2C_HIGHSPEED_TIMING 0x00500E30 // 1000 Khz, 72Mhz Clock, Analog Filter Delay ON, Setup 40, Hold 4.
#define I2C_STANDARD_TIMING 0x00E0257A // 400 Khz, 72Mhz Clock, Analog Filter Delay ON, Rise 100, Fall 10.
#define I2C_SHORT_TIMEOUT ((uint32_t)0x1000) #define I2C_SHORT_TIMEOUT ((uint32_t)0x1000)
#define I2C_LONG_TIMEOUT ((uint32_t)(10 * I2C_SHORT_TIMEOUT)) #define I2C_LONG_TIMEOUT ((uint32_t)(10 * I2C_SHORT_TIMEOUT))
#define I2C_GPIO_AF GPIO_AF_4 #define I2C_GPIO_AF GPIO_AF_4
@ -83,8 +89,11 @@ void i2cInit(I2CDevice device)
RCC_ClockCmd(i2c->rcc, ENABLE); RCC_ClockCmd(i2c->rcc, ENABLE);
RCC_I2CCLKConfig(I2Cx == I2C2 ? RCC_I2C2CLK_SYSCLK : RCC_I2C1CLK_SYSCLK); RCC_I2CCLKConfig(I2Cx == I2C2 ? RCC_I2C2CLK_SYSCLK : RCC_I2C1CLK_SYSCLK);
IOConfigGPIOAF(scl, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL), GPIO_AF_4); IOInit(scl, OWNER_I2C, RESOURCE_I2C_SCL, RESOURCE_INDEX(device));
IOConfigGPIOAF(sda, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL), GPIO_AF_4); IOConfigGPIOAF(scl, IOCFG_I2C, GPIO_AF_4);
IOInit(sda, OWNER_I2C, RESOURCE_I2C_SDA, RESOURCE_INDEX(device));
IOConfigGPIOAF(sda, IOCFG_I2C, GPIO_AF_4);
I2C_InitTypeDef i2cInit = { I2C_InitTypeDef i2cInit = {
.I2C_Mode = I2C_Mode_I2C, .I2C_Mode = I2C_Mode_I2C,
@ -93,14 +102,13 @@ void i2cInit(I2CDevice device)
.I2C_OwnAddress1 = 0x00, .I2C_OwnAddress1 = 0x00,
.I2C_Ack = I2C_Ack_Enable, .I2C_Ack = I2C_Ack_Enable,
.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit,
.I2C_Timing = i2c->overClock ? .I2C_Timing = (i2c->overClock ? I2C_HIGHSPEED_TIMING : I2C_STANDARD_TIMING)
0x00500E30 : // 1000 Khz, 72Mhz Clock, Analog Filter Delay ON, Setup 40, Hold 4.
0x00E0257A, // 400 Khz, 72Mhz Clock, Analog Filter Delay ON, Rise 100, Fall 10.
//.I2C_Timing = 0x8000050B;
}; };
I2C_Init(I2Cx, &i2cInit); I2C_Init(I2Cx, &i2cInit);
I2C_StretchClockCmd(I2Cx, ENABLE);
I2C_Cmd(I2Cx, ENABLE); I2C_Cmd(I2Cx, ENABLE);
} }

View file

@ -20,8 +20,6 @@
#include <platform.h> #include <platform.h>
#include "build_config.h"
#include "bus_spi.h" #include "bus_spi.h"
#include "io.h" #include "io.h"
#include "io_impl.h" #include "io_impl.h"
@ -113,28 +111,22 @@ void spiInitDevice(SPIDevice device)
RCC_ClockCmd(spi->rcc, ENABLE); RCC_ClockCmd(spi->rcc, ENABLE);
RCC_ResetCmd(spi->rcc, ENABLE); RCC_ResetCmd(spi->rcc, ENABLE);
IOInit(IOGetByTag(spi->sck), OWNER_SYSTEM, RESOURCE_SPI); IOInit(IOGetByTag(spi->sck), OWNER_SPI, RESOURCE_SPI_SCK, device + 1);
IOInit(IOGetByTag(spi->miso), OWNER_SYSTEM, RESOURCE_SPI); IOInit(IOGetByTag(spi->miso), OWNER_SPI, RESOURCE_SPI_MISO, device + 1);
IOInit(IOGetByTag(spi->mosi), OWNER_SYSTEM, RESOURCE_SPI); IOInit(IOGetByTag(spi->mosi), OWNER_SPI, RESOURCE_SPI_MOSI, device + 1);
#if defined(STM32F303xC) || defined(STM32F4) #if defined(STM32F3) || defined(STM32F4)
if (spi->sdcard) { IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_CFG, spi->af);
IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG, spi->af); IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_CFG, spi->af);
IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG, spi->af);
}
else {
IOConfigGPIOAF(IOGetByTag(spi->sck), SPI_IO_AF_CFG, spi->af);
IOConfigGPIOAF(IOGetByTag(spi->miso), SPI_IO_AF_CFG, spi->af);
}
IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->af); IOConfigGPIOAF(IOGetByTag(spi->mosi), SPI_IO_AF_CFG, spi->af);
if (spi->nss) if (spi->nss)
IOConfigGPIOAF(IOGetByTag(spi->nss), SPI_IO_CS_CFG, spi->af); IOConfigGPIOAF(IOGetByTag(spi->nss), SPI_IO_CS_CFG, spi->af);
#endif #endif
#if defined(STM32F10X) #if defined(STM32F10X)
IOConfigGPIO(IOGetByTag(spi->sck), SPI_IO_AF_CFG); IOConfigGPIO(IOGetByTag(spi->sck), SPI_IO_AF_SCK_CFG);
IOConfigGPIO(IOGetByTag(spi->miso), SPI_IO_AF_CFG); IOConfigGPIO(IOGetByTag(spi->miso), SPI_IO_AF_MISO_CFG);
IOConfigGPIO(IOGetByTag(spi->mosi), SPI_IO_AF_CFG); IOConfigGPIO(IOGetByTag(spi->mosi), SPI_IO_AF_MOSI_CFG);
if (spi->nss) if (spi->nss)
IOConfigGPIO(IOGetByTag(spi->nss), SPI_IO_CS_CFG); IOConfigGPIO(IOGetByTag(spi->nss), SPI_IO_CS_CFG);

View file

@ -27,8 +27,10 @@
#define SPI_IO_AF_MISO_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP) #define SPI_IO_AF_MISO_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP)
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL) #define SPI_IO_CS_CFG IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL)
#elif defined(STM32F1) #elif defined(STM32F1)
#define SPI_IO_AF_CFG IO_CONFIG(GPIO_Mode_AF_OD, GPIO_Speed_50MHz) #define SPI_IO_AF_SCK_CFG IO_CONFIG(GPIO_Mode_AF_PP, GPIO_Speed_50MHz)
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_Mode_Out_OD, GPIO_Speed_50MHz) #define SPI_IO_AF_MOSI_CFG IO_CONFIG(GPIO_Mode_AF_PP, GPIO_Speed_50MHz)
#define SPI_IO_AF_MISO_CFG IO_CONFIG(GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz)
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_Mode_Out_PP, GPIO_Speed_50MHz)
#else #else
#error "Unknown processor" #error "Unknown processor"
#endif #endif
@ -52,23 +54,23 @@ typedef enum {
} SPIClockDivider_e; } SPIClockDivider_e;
typedef enum SPIDevice { typedef enum SPIDevice {
SPIINVALID = -1, SPIINVALID = -1,
SPIDEV_1 = 0, SPIDEV_1 = 0,
SPIDEV_2, SPIDEV_2,
SPIDEV_3, SPIDEV_3,
SPIDEV_MAX = SPIDEV_3, SPIDEV_MAX = SPIDEV_3,
} SPIDevice; } SPIDevice;
typedef struct SPIDevice_s { typedef struct SPIDevice_s {
SPI_TypeDef *dev; SPI_TypeDef *dev;
ioTag_t nss; ioTag_t nss;
ioTag_t sck; ioTag_t sck;
ioTag_t mosi; ioTag_t mosi;
ioTag_t miso; ioTag_t miso;
rccPeriphTag_t rcc; rccPeriphTag_t rcc;
uint8_t af; uint8_t af;
volatile uint16_t errorCount; volatile uint16_t errorCount;
bool sdcard; bool sdcard;
} spiDevice_t; } spiDevice_t;
bool spiInit(SPIDevice device); bool spiInit(SPIDevice device);

View file

@ -30,8 +30,6 @@
#include "common/maths.h" #include "common/maths.h"
#include "system.h" #include "system.h"
#include "gpio.h"
#include "exti.h"
#include "bus_i2c.h" #include "bus_i2c.h"
#include "bus_spi.h" #include "bus_spi.h"

View file

@ -64,7 +64,7 @@ bool ak8975detect(mag_t *mag)
bool ack = false; bool ack = false;
uint8_t sig = 0; uint8_t sig = 0;
ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_WHO_AM_I, 1, &sig); ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_WHO_AM_I, 1, &sig);
if (!ack || sig != 'H') // 0x48 / 01001000 / 'H' if (!ack || sig != 'H') // 0x48 / 01001000 / 'H'
return false; return false;
@ -86,24 +86,24 @@ void ak8975Init()
UNUSED(ack); UNUSED(ack);
ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x00); // power down before entering fuse mode ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x00); // power down before entering fuse mode
delay(20); delay(20);
ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x0F); // Enter Fuse ROM access mode ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x0F); // Enter Fuse ROM access mode
delay(10); delay(10);
ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975A_ASAX, 3, &buffer[0]); // Read the x-, y-, and z-axis calibration values ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975A_ASAX, 3, &buffer[0]); // Read the x-, y-, and z-axis calibration values
delay(10); delay(10);
ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x00); // power down after reading. ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x00); // power down after reading.
delay(10); delay(10);
// Clear status registers // Clear status registers
ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS1, 1, &status); ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS1, 1, &status);
ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS2, 1, &status); ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS2, 1, &status);
// Trigger first measurement // Trigger first measurement
ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x01); ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x01);
} }
#define BIT_STATUS1_REG_DATA_READY (1 << 0) #define BIT_STATUS1_REG_DATA_READY (1 << 0)
@ -118,13 +118,13 @@ bool ak8975Read(int16_t *magData)
uint8_t status; uint8_t status;
uint8_t buf[6]; uint8_t buf[6];
ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS1, 1, &status); ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS1, 1, &status);
if (!ack || (status & BIT_STATUS1_REG_DATA_READY) == 0) { if (!ack || (status & BIT_STATUS1_REG_DATA_READY) == 0) {
return false; return false;
} }
#if 1 // USE_I2C_SINGLE_BYTE_READS #if 1 // USE_I2C_SINGLE_BYTE_READS
ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_HXL, 6, buf); // read from AK8975_MAG_REG_HXL to AK8975_MAG_REG_HZH ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_HXL, 6, buf); // read from AK8975_MAG_REG_HXL to AK8975_MAG_REG_HZH
#else #else
for (uint8_t i = 0; i < 6; i++) { for (uint8_t i = 0; i < 6; i++) {
ack = i2cRead(AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_HXL + i, 1, &buf[i]); // read from AK8975_MAG_REG_HXL to AK8975_MAG_REG_HZH ack = i2cRead(AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_HXL + i, 1, &buf[i]); // read from AK8975_MAG_REG_HXL to AK8975_MAG_REG_HZH
@ -134,7 +134,7 @@ bool ak8975Read(int16_t *magData)
} }
#endif #endif
ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS2, 1, &status); ack = i2cRead(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_STATUS2, 1, &status);
if (!ack) { if (!ack) {
return false; return false;
} }
@ -152,6 +152,6 @@ bool ak8975Read(int16_t *magData)
magData[Z] = -(int16_t)(buf[5] << 8 | buf[4]) * 4; magData[Z] = -(int16_t)(buf[5] << 8 | buf[4]) * 4;
ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x01); // start reading again ack = i2cWrite(MAG_I2C_INSTANCE, AK8975_MAG_I2C_ADDRESS, AK8975_MAG_REG_CNTL, 0x01); // start reading again
return true; return true;
} }

View file

@ -17,7 +17,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <math.h> #include <math.h>
@ -29,7 +28,8 @@
#include "system.h" #include "system.h"
#include "nvic.h" #include "nvic.h"
#include "gpio.h" #include "io.h"
#include "exti.h"
#include "bus_i2c.h" #include "bus_i2c.h"
#include "light_led.h" #include "light_led.h"
@ -120,14 +120,14 @@ static float magGain[3] = { 1.0f, 1.0f, 1.0f };
static const hmc5883Config_t *hmc5883Config = NULL; static const hmc5883Config_t *hmc5883Config = NULL;
void MAG_DATA_READY_EXTI_Handler(void) #ifdef USE_MAG_DATA_READY_SIGNAL
static IO_t intIO;
static extiCallbackRec_t hmc5883_extiCallbackRec;
void hmc5883_extiHandler(extiCallbackRec_t* cb)
{ {
if (EXTI_GetITStatus(hmc5883Config->exti_line) == RESET) { UNUSED(cb);
return;
}
EXTI_ClearITPendingBit(hmc5883Config->exti_line);
#ifdef DEBUG_MAG_DATA_READY_INTERRUPT #ifdef DEBUG_MAG_DATA_READY_INTERRUPT
// Measure the delta between calls to the interrupt handler // Measure the delta between calls to the interrupt handler
// currently should be around 65/66 milli seconds / 15hz output rate // currently should be around 65/66 milli seconds / 15hz output rate
@ -143,57 +143,26 @@ void MAG_DATA_READY_EXTI_Handler(void)
lastCalledAt = now; lastCalledAt = now;
#endif #endif
} }
#endif
static void hmc5883lConfigureDataReadyInterruptHandling(void) static void hmc5883lConfigureDataReadyInterruptHandling(void)
{ {
#ifdef USE_MAG_DATA_READY_SIGNAL #ifdef USE_MAG_DATA_READY_SIGNAL
if (!(hmc5883Config->exti_port_source && hmc5883Config->exti_pin_source)) { if (!(hmc5883Config->intTag)) {
return; return;
} }
#ifdef STM32F10X intIO = IOGetByTag(hmc5883Config->intTag);
// enable AFIO for EXTI support
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
#endif
#ifdef STM32F303xC
/* Enable SYSCFG clock otherwise the EXTI irq handlers are not called */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
#endif
#ifdef STM32F10X
gpioExtiLineConfig(hmc5883Config->exti_port_source, hmc5883Config->exti_pin_source);
#endif
#ifdef STM32F303xC
gpioExtiLineConfig(hmc5883Config->exti_port_source, hmc5883Config->exti_pin_source);
#endif
#ifdef ENSURE_MAG_DATA_READY_IS_HIGH #ifdef ENSURE_MAG_DATA_READY_IS_HIGH
uint8_t status = GPIO_ReadInputDataBit(hmc5883Config->gpioPort, hmc5883Config->gpioPin); uint8_t status = IORead(intIO);
if (!status) { if (!status) {
return; return;
} }
#endif #endif
registerExtiCallbackHandler(hmc5883Config->exti_irqn, MAG_DATA_READY_EXTI_Handler); EXTIHandlerInit(&hmc5883_extiCallbackRec, hmc5883_extiHandler);
EXTIConfig(intIO, &hmc5883_extiCallbackRec, NVIC_PRIO_MAG_INT_EXTI, EXTI_Trigger_Rising);
EXTI_ClearITPendingBit(hmc5883Config->exti_line); EXTIEnable(intIO, true);
EXTI_InitTypeDef EXTIInit;
EXTIInit.EXTI_Line = hmc5883Config->exti_line;
EXTIInit.EXTI_Mode = EXTI_Mode_Interrupt;
EXTIInit.EXTI_Trigger = EXTI_Trigger_Falling;
EXTIInit.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTIInit);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = hmc5883Config->exti_irqn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_MAG_DATA_READY);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_MAG_DATA_READY);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif #endif
} }
@ -204,7 +173,7 @@ bool hmc5883lDetect(mag_t* mag, const hmc5883Config_t *hmc5883ConfigToUse)
hmc5883Config = hmc5883ConfigToUse; hmc5883Config = hmc5883ConfigToUse;
ack = i2cRead(MAG_I2C_INSTANCE, MAG_ADDRESS, 0x0A, 1, &sig); ack = i2cRead(MAG_I2C_INSTANCE, MAG_ADDRESS, 0x0A, 1, &sig);
if (!ack || sig != 'H') if (!ack || sig != 'H')
return false; return false;
@ -221,35 +190,16 @@ void hmc5883lInit(void)
int32_t xyz_total[3] = { 0, 0, 0 }; // 32 bit totals so they won't overflow. int32_t xyz_total[3] = { 0, 0, 0 }; // 32 bit totals so they won't overflow.
bool bret = true; // Error indicator bool bret = true; // Error indicator
gpio_config_t gpio;
if (hmc5883Config) {
#ifdef STM32F303
if (hmc5883Config->gpioAHBPeripherals) {
RCC_AHBPeriphClockCmd(hmc5883Config->gpioAHBPeripherals, ENABLE);
}
#endif
#ifdef STM32F10X
if (hmc5883Config->gpioAPB2Peripherals) {
RCC_APB2PeriphClockCmd(hmc5883Config->gpioAPB2Peripherals, ENABLE);
}
#endif
gpio.pin = hmc5883Config->gpioPin;
gpio.speed = Speed_2MHz;
gpio.mode = Mode_IN_FLOATING;
gpioInit(hmc5883Config->gpioPort, &gpio);
}
delay(50); delay(50);
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x010 + HMC_POS_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to pos bias i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x010 + HMC_POS_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to pos bias
// Note that the very first measurement after a gain change maintains the same gain as the previous setting. // Note that the very first measurement after a gain change maintains the same gain as the previous setting.
// The new gain setting is effective from the second measurement and on. // The new gain setting is effective from the second measurement and on.
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFB, 0x60); // Set the Gain to 2.5Ga (7:5->011) i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFB, 0x60); // Set the Gain to 2.5Ga (7:5->011)
delay(100); delay(100);
hmc5883lRead(magADC); hmc5883lRead(magADC);
for (i = 0; i < 10; i++) { // Collect 10 samples for (i = 0; i < 10; i++) { // Collect 10 samples
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 1); i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 1);
delay(50); delay(50);
hmc5883lRead(magADC); // Get the raw values in case the scales have already been changed. hmc5883lRead(magADC); // Get the raw values in case the scales have already been changed.
@ -267,9 +217,9 @@ void hmc5883lInit(void)
} }
// Apply the negative bias. (Same gain) // Apply the negative bias. (Same gain)
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x010 + HMC_NEG_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to negative bias. i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x010 + HMC_NEG_BIAS); // Reg A DOR = 0x010 + MS1, MS0 set to negative bias.
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 1); i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 1);
delay(50); delay(50);
hmc5883lRead(magADC); // Get the raw values in case the scales have already been changed. hmc5883lRead(magADC); // Get the raw values in case the scales have already been changed.
@ -291,9 +241,9 @@ void hmc5883lInit(void)
magGain[Z] = fabsf(660.0f * HMC58X3_Z_SELF_TEST_GAUSS * 2.0f * 10.0f / xyz_total[Z]); magGain[Z] = fabsf(660.0f * HMC58X3_Z_SELF_TEST_GAUSS * 2.0f * 10.0f / xyz_total[Z]);
// leave test mode // leave test mode
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x70); // Configuration Register A -- 0 11 100 00 num samples: 8 ; output rate: 15Hz ; normal measurement mode i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFA, 0x70); // Configuration Register A -- 0 11 100 00 num samples: 8 ; output rate: 15Hz ; normal measurement mode
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFB, 0x20); // Configuration Register B -- 001 00000 configuration gain 1.3Ga i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_CONFB, 0x20); // Configuration Register B -- 001 00000 configuration gain 1.3Ga
i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 0x00); // Mode register -- 000000 00 continuous Conversion Mode i2cWrite(MAG_I2C_INSTANCE, MAG_ADDRESS, HMC58X3_R_MODE, 0x00); // Mode register -- 000000 00 continuous Conversion Mode
delay(100); delay(100);
if (!bret) { // Something went wrong so get a best guess if (!bret) { // Something went wrong so get a best guess
@ -309,7 +259,7 @@ bool hmc5883lRead(int16_t *magData)
{ {
uint8_t buf[6]; uint8_t buf[6];
bool ack = i2cRead(MAG_I2C_INSTANCE, MAG_ADDRESS, MAG_DATA_REGISTER, 6, buf); bool ack = i2cRead(MAG_I2C_INSTANCE, MAG_ADDRESS, MAG_DATA_REGISTER, 6, buf);
if (!ack) { if (!ack) {
return false; return false;
} }

View file

@ -17,20 +17,10 @@
#pragma once #pragma once
typedef struct hmc5883Config_s { #include "io.h"
#ifdef STM32F303
uint32_t gpioAHBPeripherals;
#endif
#ifdef STM32F10X
uint32_t gpioAPB2Peripherals;
#endif
uint16_t gpioPin;
GPIO_TypeDef *gpioPort;
uint8_t exti_port_source; typedef struct hmc5883Config_s {
uint32_t exti_line; ioTag_t intTag;
uint8_t exti_pin_source;
IRQn_Type exti_irqn;
} hmc5883Config_t; } hmc5883Config_t;
bool hmc5883lDetect(mag_t* mag, const hmc5883Config_t *hmc5883ConfigToUse); bool hmc5883lDetect(mag_t* mag, const hmc5883Config_t *hmc5883ConfigToUse);

View file

@ -17,7 +17,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"

View file

@ -21,63 +21,66 @@
#include <platform.h> #include <platform.h>
#include "build_config.h" #include "drivers/nvic.h"
#include "drivers/dma.h" #include "drivers/dma.h"
/* /*
* DMA handlers for DMA resources that are shared between different features depending on run-time configuration. * DMA descriptors.
*/ */
static dmaHandlers_t dmaHandlers; static dmaChannelDescriptor_t dmaDescriptors[] = {
DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel1, 0, DMA1_Channel1_IRQn, RCC_AHBPeriph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel2, 4, DMA1_Channel2_IRQn, RCC_AHBPeriph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel3, 8, DMA1_Channel3_IRQn, RCC_AHBPeriph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel4, 12, DMA1_Channel4_IRQn, RCC_AHBPeriph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel5, 16, DMA1_Channel5_IRQn, RCC_AHBPeriph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel6, 20, DMA1_Channel6_IRQn, RCC_AHBPeriph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Channel7, 24, DMA1_Channel7_IRQn, RCC_AHBPeriph_DMA1),
#if defined(STM32F3) || defined(STM32F10X_CL)
DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel1, 0, DMA2_Channel1_IRQn, RCC_AHBPeriph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel2, 4, DMA2_Channel2_IRQn, RCC_AHBPeriph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel3, 8, DMA2_Channel3_IRQn, RCC_AHBPeriph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel4, 12, DMA2_Channel4_IRQn, RCC_AHBPeriph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Channel5, 16, DMA2_Channel5_IRQn, RCC_AHBPeriph_DMA2),
#endif
};
void dmaNoOpHandler(DMA_Channel_TypeDef *channel) /*
{ * DMA IRQ Handlers
UNUSED(channel); */
} DEFINE_DMA_IRQ_HANDLER(1, 1, DMA1_CH1_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 2, DMA1_CH2_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 3, DMA1_CH3_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 4, DMA1_CH4_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 5, DMA1_CH5_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 6, DMA1_CH6_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 7, DMA1_CH7_HANDLER)
void DMA1_Channel2_IRQHandler(void) #if defined(STM32F3) || defined(STM32F10X_CL)
{ DEFINE_DMA_IRQ_HANDLER(2, 1, DMA2_CH1_HANDLER)
dmaHandlers.dma1Channel2IRQHandler(DMA1_Channel2); DEFINE_DMA_IRQ_HANDLER(2, 2, DMA2_CH2_HANDLER)
} DEFINE_DMA_IRQ_HANDLER(2, 3, DMA2_CH3_HANDLER)
DEFINE_DMA_IRQ_HANDLER(2, 4, DMA2_CH4_HANDLER)
DEFINE_DMA_IRQ_HANDLER(2, 5, DMA2_CH5_HANDLER)
#endif
void DMA1_Channel3_IRQHandler(void)
{
dmaHandlers.dma1Channel3IRQHandler(DMA1_Channel3);
}
void DMA1_Channel6_IRQHandler(void)
{
dmaHandlers.dma1Channel6IRQHandler(DMA1_Channel6);
}
void DMA1_Channel7_IRQHandler(void)
{
dmaHandlers.dma1Channel7IRQHandler(DMA1_Channel7);
}
void dmaInit(void) void dmaInit(void)
{ {
memset(&dmaHandlers, 0, sizeof(dmaHandlers)); // TODO: Do we need this?
dmaHandlers.dma1Channel2IRQHandler = dmaNoOpHandler;
dmaHandlers.dma1Channel3IRQHandler = dmaNoOpHandler;
dmaHandlers.dma1Channel6IRQHandler = dmaNoOpHandler;
dmaHandlers.dma1Channel7IRQHandler = dmaNoOpHandler;
} }
void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback) void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback, uint32_t priority, uint32_t userParam)
{ {
switch (identifier) { NVIC_InitTypeDef NVIC_InitStructure;
case DMA1_CH2_HANDLER:
dmaHandlers.dma1Channel2IRQHandler = callback; RCC_AHBPeriphClockCmd(dmaDescriptors[identifier].rcc, ENABLE);
break; dmaDescriptors[identifier].irqHandlerCallback = callback;
case DMA1_CH3_HANDLER: dmaDescriptors[identifier].userParam = userParam;
dmaHandlers.dma1Channel3IRQHandler = callback;
break; NVIC_InitStructure.NVIC_IRQChannel = dmaDescriptors[identifier].irqN;
case DMA1_CH6_HANDLER: NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(priority);
dmaHandlers.dma1Channel6IRQHandler = callback; NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(priority);
break; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
case DMA1_CH7_HANDLER: NVIC_Init(&NVIC_InitStructure);
dmaHandlers.dma1Channel7IRQHandler = callback;
break;
}
} }

View file

@ -15,37 +15,97 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
struct dmaChannelDescriptor_s;
typedef void (*dmaCallbackHandlerFuncPtr)(struct dmaChannelDescriptor_s *channelDescriptor);
#ifdef STM32F4 #ifdef STM32F4
typedef void(*dmaCallbackHandlerFuncPtr)(DMA_Stream_TypeDef *stream);
typedef enum { typedef enum {
DMA1_ST2_HANDLER = 0, DMA1_ST1_HANDLER = 0,
DMA1_ST2_HANDLER,
DMA1_ST3_HANDLER,
DMA1_ST4_HANDLER,
DMA1_ST5_HANDLER,
DMA1_ST6_HANDLER,
DMA1_ST7_HANDLER, DMA1_ST7_HANDLER,
DMA2_ST1_HANDLER,
DMA2_ST2_HANDLER,
DMA2_ST3_HANDLER,
DMA2_ST4_HANDLER,
DMA2_ST5_HANDLER,
DMA2_ST6_HANDLER,
DMA2_ST7_HANDLER,
} dmaHandlerIdentifier_e; } dmaHandlerIdentifier_e;
typedef struct dmaHandlers_s { typedef struct dmaChannelDescriptor_s {
dmaCallbackHandlerFuncPtr dma1Stream2IRQHandler; DMA_TypeDef* dma;
dmaCallbackHandlerFuncPtr dma1Stream7IRQHandler; DMA_Stream_TypeDef* stream;
} dmaHandlers_t; dmaCallbackHandlerFuncPtr irqHandlerCallback;
uint8_t flagsShift;
IRQn_Type irqN;
uint32_t rcc;
uint32_t userParam;
} dmaChannelDescriptor_t;
#define DEFINE_DMA_CHANNEL(d, s, f, i, r) {.dma = d, .stream = s, .irqHandlerCallback = NULL, .flagsShift = f, .irqN = i, .rcc = r, .userParam = 0}
#define DEFINE_DMA_IRQ_HANDLER(d, s, i) void DMA ## d ## _Stream ## s ## _IRQHandler(void) {\
if (dmaDescriptors[i].irqHandlerCallback)\
dmaDescriptors[i].irqHandlerCallback(&dmaDescriptors[i]);\
}
#define DMA_CLEAR_FLAG(d, flag) if(d->flagsShift > 31) d->dma->HIFCR = (flag << (d->flagsShift - 32)); else d->dma->LIFCR = (flag << d->flagsShift)
#define DMA_GET_FLAG_STATUS(d, flag) (d->flagsShift > 31 ? d->dma->HISR & (flag << (d->flagsShift - 32)): d->dma->LISR & (flag << d->flagsShift))
#define DMA_IT_TCIF ((uint32_t)0x00000020)
#define DMA_IT_HTIF ((uint32_t)0x00000010)
#define DMA_IT_TEIF ((uint32_t)0x00000008)
#define DMA_IT_DMEIF ((uint32_t)0x00000004)
#define DMA_IT_FEIF ((uint32_t)0x00000001)
#else #else
typedef void (*dmaCallbackHandlerFuncPtr)(DMA_Channel_TypeDef *channel);
typedef enum { typedef enum {
DMA1_CH2_HANDLER = 0, DMA1_CH1_HANDLER = 0,
DMA1_CH2_HANDLER,
DMA1_CH3_HANDLER, DMA1_CH3_HANDLER,
DMA1_CH4_HANDLER,
DMA1_CH5_HANDLER,
DMA1_CH6_HANDLER, DMA1_CH6_HANDLER,
DMA1_CH7_HANDLER, DMA1_CH7_HANDLER,
DMA2_CH1_HANDLER,
DMA2_CH2_HANDLER,
DMA2_CH3_HANDLER,
DMA2_CH4_HANDLER,
DMA2_CH5_HANDLER,
} dmaHandlerIdentifier_e; } dmaHandlerIdentifier_e;
typedef struct dmaHandlers_s { typedef struct dmaChannelDescriptor_s {
dmaCallbackHandlerFuncPtr dma1Channel2IRQHandler; DMA_TypeDef* dma;
dmaCallbackHandlerFuncPtr dma1Channel3IRQHandler; DMA_Channel_TypeDef* channel;
dmaCallbackHandlerFuncPtr dma1Channel6IRQHandler; dmaCallbackHandlerFuncPtr irqHandlerCallback;
dmaCallbackHandlerFuncPtr dma1Channel7IRQHandler; uint8_t flagsShift;
} dmaHandlers_t; IRQn_Type irqN;
uint32_t rcc;
uint32_t userParam;
} dmaChannelDescriptor_t;
#define DEFINE_DMA_CHANNEL(d, c, f, i, r) {.dma = d, .channel = c, .irqHandlerCallback = NULL, .flagsShift = f, .irqN = i, .rcc = r, .userParam = 0}
#define DEFINE_DMA_IRQ_HANDLER(d, c, i) void DMA ## d ## _Channel ## c ## _IRQHandler(void) {\
if (dmaDescriptors[i].irqHandlerCallback)\
dmaDescriptors[i].irqHandlerCallback(&dmaDescriptors[i]);\
}
#define DMA_CLEAR_FLAG(d, flag) d->dma->IFCR = (flag << d->flagsShift)
#define DMA_GET_FLAG_STATUS(d, flag) (d->dma->ISR & (flag << d->flagsShift))
#define DMA_IT_TCIF ((uint32_t)0x00000002)
#define DMA_IT_HTIF ((uint32_t)0x00000004)
#define DMA_IT_TEIF ((uint32_t)0x00000008)
#endif #endif
void dmaInit(void); void dmaInit(void);
void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback); void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback, uint32_t priority, uint32_t userParam);

View file

@ -16,50 +16,72 @@
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include <platform.h> #include <platform.h>
#include "build_config.h" #include "drivers/nvic.h"
#include "drivers/dma.h" #include "drivers/dma.h"
/* /*
* DMA handlers for DMA resources that are shared between different features depending on run-time configuration. * DMA descriptors.
*/ */
static dmaHandlers_t dmaHandlers; static dmaChannelDescriptor_t dmaDescriptors[] = {
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream0, 0, DMA1_Stream0_IRQn, RCC_AHB1Periph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream1, 6, DMA1_Stream1_IRQn, RCC_AHB1Periph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream2, 16, DMA1_Stream2_IRQn, RCC_AHB1Periph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream3, 22, DMA1_Stream3_IRQn, RCC_AHB1Periph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream4, 32, DMA1_Stream4_IRQn, RCC_AHB1Periph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream5, 38, DMA1_Stream5_IRQn, RCC_AHB1Periph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream6, 48, DMA1_Stream6_IRQn, RCC_AHB1Periph_DMA1),
DEFINE_DMA_CHANNEL(DMA1, DMA1_Stream7, 54, DMA1_Stream7_IRQn, RCC_AHB1Periph_DMA1),
void dmaNoOpHandler(DMA_Stream_TypeDef *stream) DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream0, 0, DMA2_Stream0_IRQn, RCC_AHB1Periph_DMA2),
{ DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream1, 6, DMA2_Stream1_IRQn, RCC_AHB1Periph_DMA2),
UNUSED(stream); DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream2, 16, DMA2_Stream2_IRQn, RCC_AHB1Periph_DMA2),
} DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream3, 22, DMA2_Stream3_IRQn, RCC_AHB1Periph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream4, 32, DMA2_Stream4_IRQn, RCC_AHB1Periph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream5, 38, DMA2_Stream5_IRQn, RCC_AHB1Periph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream6, 48, DMA2_Stream6_IRQn, RCC_AHB1Periph_DMA2),
DEFINE_DMA_CHANNEL(DMA2, DMA2_Stream7, 54, DMA2_Stream7_IRQn, RCC_AHB1Periph_DMA2),
void DMA1_Stream2_IRQHandler(void) };
{
dmaHandlers.dma1Stream2IRQHandler(DMA1_Stream2); /*
} * DMA IRQ Handlers
*/
DEFINE_DMA_IRQ_HANDLER(1, 1, DMA1_ST1_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 2, DMA1_ST2_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 3, DMA1_ST3_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 4, DMA1_ST4_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 5, DMA1_ST5_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 6, DMA1_ST6_HANDLER)
DEFINE_DMA_IRQ_HANDLER(1, 7, DMA1_ST7_HANDLER)
DEFINE_DMA_IRQ_HANDLER(2, 1, DMA2_ST1_HANDLER)
DEFINE_DMA_IRQ_HANDLER(2, 2, DMA2_ST2_HANDLER)
DEFINE_DMA_IRQ_HANDLER(2, 3, DMA2_ST3_HANDLER)
DEFINE_DMA_IRQ_HANDLER(2, 4, DMA2_ST4_HANDLER)
DEFINE_DMA_IRQ_HANDLER(2, 5, DMA2_ST5_HANDLER)
void DMA1_Stream7_IRQHandler(void)
{
dmaHandlers.dma1Stream7IRQHandler(DMA1_Stream7);
}
void dmaInit(void) void dmaInit(void)
{ {
memset(&dmaHandlers, 0, sizeof(dmaHandlers)); // TODO: Do we need this?
dmaHandlers.dma1Stream2IRQHandler = dmaNoOpHandler;
dmaHandlers.dma1Stream7IRQHandler = dmaNoOpHandler;
} }
void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback) void dmaSetHandler(dmaHandlerIdentifier_e identifier, dmaCallbackHandlerFuncPtr callback, uint32_t priority, uint32_t userParam)
{ {
switch (identifier) { NVIC_InitTypeDef NVIC_InitStructure;
case DMA1_ST2_HANDLER:
dmaHandlers.dma1Stream2IRQHandler = callback; RCC_AHB1PeriphClockCmd(dmaDescriptors[identifier].rcc, ENABLE);
break; dmaDescriptors[identifier].irqHandlerCallback = callback;
case DMA1_ST7_HANDLER: dmaDescriptors[identifier].userParam = userParam;
dmaHandlers.dma1Stream7IRQHandler = callback;
break; NVIC_InitStructure.NVIC_IRQChannel = dmaDescriptors[identifier].irqN;
} NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(priority);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(priority);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
} }

View file

@ -1,6 +1,6 @@
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include "platform.h" #include "platform.h"

View file

@ -15,7 +15,6 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@ -203,7 +202,7 @@ bool m25p16_init()
#ifdef M25P16_CS_PIN #ifdef M25P16_CS_PIN
m25p16CsPin = IOGetByTag(IO_TAG(M25P16_CS_PIN)); m25p16CsPin = IOGetByTag(IO_TAG(M25P16_CS_PIN));
#endif #endif
IOInit(m25p16CsPin, OWNER_FLASH, RESOURCE_SPI); IOInit(m25p16CsPin, OWNER_FLASH, RESOURCE_SPI_CS, 0);
IOConfigGPIO(m25p16CsPin, SPI_IO_CS_CFG); IOConfigGPIO(m25p16CsPin, SPI_IO_CS_CFG);
DISABLE_M25P16; DISABLE_M25P16;

View file

@ -20,8 +20,6 @@
#include "platform.h" #include "platform.h"
#include "build_config.h"
#include "gpio.h" #include "gpio.h"
#define MODE_OFFSET 0 #define MODE_OFFSET 0

View file

@ -4,48 +4,39 @@
* Created on: 3 aug. 2015 * Created on: 3 aug. 2015
* Author: borisb * Author: borisb
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
#include "build_config.h"
#include "common/axis.h"
#include "common/maths.h"
#include "drivers/sensor.h" #include "drivers/sensor.h"
#include "drivers/accgyro.h" #include "drivers/accgyro.h"
#include "drivers/gyro_sync.h" #include "drivers/gyro_sync.h"
#include "sensors/sensors.h"
#include "sensors/acceleration.h"
#include "config/runtime_config.h"
#include "config/config.h"
extern gyro_t gyro;
uint32_t targetLooptime;
static uint8_t mpuDividerDrops; static uint8_t mpuDividerDrops;
bool getMpuDataStatus(gyro_t *gyro) bool gyroSyncCheckUpdate(const gyro_t *gyro)
{ {
bool mpuDataStatus;
if (!gyro->intStatus) if (!gyro->intStatus)
return false; return false;
gyro->intStatus(&mpuDataStatus); return gyro->intStatus();
return mpuDataStatus;
} }
bool gyroSyncCheckUpdate(void) { #define GYRO_LPF_256HZ 0
return getMpuDataStatus(&gyro); #define GYRO_LPF_188HZ 1
} #define GYRO_LPF_98HZ 2
#define GYRO_LPF_42HZ 3
#define GYRO_LPF_20HZ 4
#define GYRO_LPF_10HZ 5
#define GYRO_LPF_5HZ 6
#define GYRO_LPF_NONE 7
void gyroUpdateSampleRate(uint8_t lpf, uint8_t gyroSyncDenominator) { uint32_t gyroSetSampleRate(uint8_t lpf, uint8_t gyroSyncDenominator)
{
int gyroSamplePeriod; int gyroSamplePeriod;
if (!lpf || lpf == 7) { if (lpf == GYRO_LPF_256HZ || lpf == GYRO_LPF_NONE) {
gyroSamplePeriod = 125; gyroSamplePeriod = 125;
} else { } else {
gyroSamplePeriod = 1000; gyroSamplePeriod = 1000;
@ -54,9 +45,11 @@ void gyroUpdateSampleRate(uint8_t lpf, uint8_t gyroSyncDenominator) {
// calculate gyro divider and targetLooptime (expected cycleTime) // calculate gyro divider and targetLooptime (expected cycleTime)
mpuDividerDrops = gyroSyncDenominator - 1; mpuDividerDrops = gyroSyncDenominator - 1;
targetLooptime = (mpuDividerDrops + 1) * gyroSamplePeriod; const uint32_t targetLooptime = gyroSyncDenominator * gyroSamplePeriod;
return targetLooptime;
} }
uint8_t gyroMPU6xxxGetDividerDrops(void) { uint8_t gyroMPU6xxxGetDividerDrops(void)
{
return mpuDividerDrops; return mpuDividerDrops;
} }

View file

@ -5,8 +5,7 @@
* Author: borisb * Author: borisb
*/ */
extern uint32_t targetLooptime; struct gyro_s;
bool gyroSyncCheckUpdate(const struct gyro_s *gyro);
bool gyroSyncCheckUpdate(void);
uint8_t gyroMPU6xxxGetDividerDrops(void); uint8_t gyroMPU6xxxGetDividerDrops(void);
void gyroUpdateSampleRate(uint8_t lpf, uint8_t gyroSyncDenominator); uint32_t gyroSetSampleRate(uint8_t lpf, uint8_t gyroSyncDenominator);

View file

@ -31,15 +31,15 @@ static const IO_t pin = DEFIO_IO(INVERTER);
void initInverter(void) void initInverter(void)
{ {
IOInit(pin, OWNER_SYSTEM, RESOURCE_OUTPUT); IOInit(pin, OWNER_INVERTER, RESOURCE_OUTPUT, 0);
IOConfigGPIO(pin, IOCFG_OUT_PP); IOConfigGPIO(pin, IOCFG_OUT_PP);
inverterSet(false); inverterSet(false);
} }
void inverterSet(bool on) void inverterSet(bool on)
{ {
IOWrite(pin, on); IOWrite(pin, on);
} }
#endif #endif

View file

@ -53,6 +53,19 @@ const struct ioPortDef_s ioPortDefs[] = {
}; };
# endif # endif
const char * const ownerNames[OWNER_TOTAL_COUNT] = {
"FREE", "PWM", "PPM", "MOTOR", "SERVO", "SOFTSERIAL", "ADC", "SERIAL", "DEBUG", "TIMER",
"SONAR", "SYSTEM", "SPI", "I2C", "SDCARD", "FLASH", "USB", "BEEPER", "OSD",
"BARO", "MPU", "INVERTER", "LED STRIP", "LED", "RECEIVER", "TRANSMITTER"
};
const char * const resourceNames[RESOURCE_TOTAL_COUNT] = {
"", // NONE
"IN", "OUT", "IN / OUT", "TIMER","UART TX","UART RX","UART TX/RX","EXTI","SCL",
"SDA", "SCK","MOSI","MISO","CS","BATTERY","RSSI","EXT","CURRENT"
};
ioRec_t* IO_Rec(IO_t io) ioRec_t* IO_Rec(IO_t io)
{ {
return io; return io;
@ -190,12 +203,12 @@ void IOToggle(IO_t io)
} }
// claim IO pin, set owner and resources // claim IO pin, set owner and resources
void IOInit(IO_t io, resourceOwner_t owner, resourceType_t resources) void IOInit(IO_t io, resourceOwner_t owner, resourceType_t resource, uint8_t index)
{ {
ioRec_t *ioRec = IO_Rec(io); ioRec_t *ioRec = IO_Rec(io);
if (owner != OWNER_FREE) // pass OWNER_FREE to keep old owner ioRec->owner = owner;
ioRec->owner = owner; ioRec->resource = resource;
ioRec->resourcesUsed |= resources; ioRec->index = index;
} }
void IORelease(IO_t io) void IORelease(IO_t io)
@ -210,10 +223,10 @@ resourceOwner_t IOGetOwner(IO_t io)
return ioRec->owner; return ioRec->owner;
} }
resourceType_t IOGetResources(IO_t io) resourceType_t IOGetResource(IO_t io)
{ {
ioRec_t *ioRec = IO_Rec(io); ioRec_t *ioRec = IO_Rec(io);
return ioRec->resourcesUsed; return ioRec->resource;
} }
#if defined(STM32F1) #if defined(STM32F1)

View file

@ -52,6 +52,7 @@ typedef uint8_t ioConfig_t; // packed IO configuration
#define IO_CONFIG(mode, speed, otype, pupd) ((mode) | ((speed) << 2) | ((otype) << 4) | ((pupd) << 5)) #define IO_CONFIG(mode, speed, otype, pupd) ((mode) | ((speed) << 2) | ((otype) << 4) | ((pupd) << 5))
#define IOCFG_OUT_PP IO_CONFIG(GPIO_Mode_OUT, 0, GPIO_OType_PP, GPIO_PuPd_NOPULL) // TODO #define IOCFG_OUT_PP IO_CONFIG(GPIO_Mode_OUT, 0, GPIO_OType_PP, GPIO_PuPd_NOPULL) // TODO
#define IOCFG_OUT_PP_25 IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_25MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL)
#define IOCFG_OUT_OD IO_CONFIG(GPIO_Mode_OUT, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL) #define IOCFG_OUT_OD IO_CONFIG(GPIO_Mode_OUT, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL)
#define IOCFG_AF_PP IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_PP, GPIO_PuPd_NOPULL) #define IOCFG_AF_PP IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_PP, GPIO_PuPd_NOPULL)
#define IOCFG_AF_PP_PD IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_PP, GPIO_PuPd_DOWN) #define IOCFG_AF_PP_PD IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_PP, GPIO_PuPd_DOWN)
@ -60,6 +61,7 @@ typedef uint8_t ioConfig_t; // packed IO configuration
#define IOCFG_IPD IO_CONFIG(GPIO_Mode_IN, 0, 0, GPIO_PuPd_DOWN) #define IOCFG_IPD IO_CONFIG(GPIO_Mode_IN, 0, 0, GPIO_PuPd_DOWN)
#define IOCFG_IPU IO_CONFIG(GPIO_Mode_IN, 0, 0, GPIO_PuPd_UP) #define IOCFG_IPU IO_CONFIG(GPIO_Mode_IN, 0, 0, GPIO_PuPd_UP)
#define IOCFG_IN_FLOATING IO_CONFIG(GPIO_Mode_IN, 0, 0, GPIO_PuPd_NOPULL) #define IOCFG_IN_FLOATING IO_CONFIG(GPIO_Mode_IN, 0, 0, GPIO_PuPd_NOPULL)
#define IOCFG_IPU_25 IO_CONFIG(GPIO_Mode_IN, GPIO_Speed_25MHz, 0, GPIO_PuPd_UP)
#elif defined(UNIT_TEST) #elif defined(UNIT_TEST)
@ -84,7 +86,7 @@ void IOHi(IO_t io);
void IOLo(IO_t io); void IOLo(IO_t io);
void IOToggle(IO_t io); void IOToggle(IO_t io);
void IOInit(IO_t io, resourceOwner_t owner, resourceType_t resources); void IOInit(IO_t io, resourceOwner_t owner, resourceType_t resource, uint8_t index);
void IORelease(IO_t io); // unimplemented void IORelease(IO_t io); // unimplemented
resourceOwner_t IOGetOwner(IO_t io); resourceOwner_t IOGetOwner(IO_t io);
resourceType_t IOGetResources(IO_t io); resourceType_t IOGetResources(IO_t io);

View file

@ -12,7 +12,8 @@ typedef struct ioRec_s {
GPIO_TypeDef *gpio; GPIO_TypeDef *gpio;
uint16_t pin; uint16_t pin;
resourceOwner_t owner; resourceOwner_t owner;
resourceType_t resourcesUsed; // TODO! resourceType_t resource;
uint8_t index;
} ioRec_t; } ioRec_t;
extern ioRec_t ioRecs[DEFIO_IO_USED_COUNT]; extern ioRec_t ioRecs[DEFIO_IO_USED_COUNT];

View file

@ -82,25 +82,25 @@ uint8_t ledOffset = 0;
void ledInit(bool alternative_led) void ledInit(bool alternative_led)
{ {
uint32_t i; uint32_t i;
#if defined(LED0_A) || defined(LED1_A) || defined(LED2_A) #if defined(LED0_A) || defined(LED1_A) || defined(LED2_A)
if (alternative_led) if (alternative_led)
ledOffset = LED_NUMBER; ledOffset = LED_NUMBER;
#else #else
UNUSED(alternative_led); UNUSED(alternative_led);
#endif #endif
LED0_OFF; LED0_OFF;
LED1_OFF; LED1_OFF;
LED2_OFF; LED2_OFF;
for (i = 0; i < LED_NUMBER; i++) { for (i = 0; i < LED_NUMBER; i++) {
if (leds[i + ledOffset]) { if (leds[i + ledOffset]) {
IOInit(leds[i + ledOffset], OWNER_SYSTEM, RESOURCE_OUTPUT); IOInit(leds[i + ledOffset], OWNER_LED, RESOURCE_OUTPUT, RESOURCE_INDEX(i));
IOConfigGPIO(leds[i + ledOffset], IOCFG_OUT_PP); IOConfigGPIO(leds[i + ledOffset], IOCFG_OUT_PP);
} }
} }
LED0_OFF; LED0_OFF;
LED1_OFF; LED1_OFF;
@ -109,11 +109,11 @@ void ledInit(bool alternative_led)
void ledToggle(int led) void ledToggle(int led)
{ {
IOToggle(leds[led + ledOffset]); IOToggle(leds[led + ledOffset]);
} }
void ledSet(int led, bool on) void ledSet(int led, bool on)
{ {
bool inverted = (1 << (led + ledOffset)) & ledPolarity; bool inverted = (1 << (led + ledOffset)) & ledPolarity;
IOWrite(leds[led + ledOffset], on ? inverted : !inverted); IOWrite(leds[led + ledOffset], on ? inverted : !inverted);
} }

View file

@ -80,18 +80,9 @@ void setStripColors(const hsvColor_t *colors)
} }
} }
void ws2811DMAHandler(DMA_Channel_TypeDef *channel) {
if (DMA_GetFlagStatus(WS2811_DMA_TC_FLAG)) {
ws2811LedDataTransferInProgress = 0;
DMA_Cmd(channel, DISABLE);
DMA_ClearFlag(WS2811_DMA_TC_FLAG);
}
}
void ws2811LedStripInit(void) void ws2811LedStripInit(void)
{ {
memset(&ledStripDMABuffer, 0, WS2811_DMA_BUFFER_SIZE); memset(&ledStripDMABuffer, 0, WS2811_DMA_BUFFER_SIZE);
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, ws2811DMAHandler);
ws2811LedStripHardwareInit(); ws2811LedStripHardwareInit();
ws2811UpdateStrip(); ws2811UpdateStrip();
} }
@ -141,12 +132,11 @@ STATIC_UNIT_TESTED void updateLEDDMABuffer(uint8_t componentValue)
*/ */
void ws2811UpdateStrip(void) void ws2811UpdateStrip(void)
{ {
static uint32_t waitCounter = 0;
static rgbColor24bpp_t *rgb24; static rgbColor24bpp_t *rgb24;
// wait until previous transfer completes // don't wait - risk of infinite block, just get an update next time round
while(ws2811LedDataTransferInProgress) { if (ws2811LedDataTransferInProgress) {
waitCounter++; return;
} }
dmaBufferOffset = 0; // reset buffer memory index dmaBufferOffset = 0; // reset buffer memory index

View file

@ -25,8 +25,13 @@
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE + WS2811_DELAY_BUFFER_LENGTH) // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes) #define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE + WS2811_DELAY_BUFFER_LENGTH) // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes)
#if defined(STM32F40_41xxx)
#define BIT_COMPARE_1 67 // timer compare value for logical 1
#define BIT_COMPARE_0 33 // timer compare value for logical 0
#else
#define BIT_COMPARE_1 17 // timer compare value for logical 1 #define BIT_COMPARE_1 17 // timer compare value for logical 1
#define BIT_COMPARE_0 9 // timer compare value for logical 0 #define BIT_COMPARE_0 9 // timer compare value for logical 0
#endif
void ws2811LedStripInit(void); void ws2811LedStripInit(void);

View file

@ -23,35 +23,40 @@
#include "common/color.h" #include "common/color.h"
#include "drivers/light_ws2811strip.h" #include "drivers/light_ws2811strip.h"
#include "nvic.h" #include "nvic.h"
#include "io.h"
#include "dma.h"
#include "timer.h"
#ifdef LED_STRIP
static IO_t ws2811IO = IO_NONE;
bool ws2811Initialised = false;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
ws2811LedDataTransferInProgress = 0;
DMA_Cmd(descriptor->channel, DISABLE);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
}
}
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(void)
{ {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
uint16_t prescalerValue; uint16_t prescalerValue;
#ifdef CC3D dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#else
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* GPIOA Configuration: TIM3 Channel 1 as alternate function push-pull */ ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
GPIO_StructInit(&GPIO_InitStructure); /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; IOConfigGPIO(ws2811IO, IO_CONFIG(GPIO_Speed_50MHz, GPIO_Mode_AF_PP));
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
#endif
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Compute the prescaler value */ /* Compute the prescaler value */
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
/* Time base configuration */ /* Time base configuration */
@ -100,24 +105,20 @@ void ws2811LedStripHardwareInit(void)
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE); DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure; ws2811Initialised = true;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_WS2811_DMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_WS2811_DMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
setStripColor(&hsv_white); setStripColor(&hsv_white);
ws2811UpdateStrip(); ws2811UpdateStrip();
} }
void ws2811LedStripDMAEnable(void) void ws2811LedStripDMAEnable(void)
{ {
if (!ws2811Initialised)
return;
DMA_SetCurrDataCounter(DMA1_Channel6, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(DMA1_Channel6, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(TIM3, 0); TIM_SetCounter(TIM3, 0);
TIM_Cmd(TIM3, ENABLE); TIM_Cmd(TIM3, ENABLE);
DMA_Cmd(DMA1_Channel6, ENABLE); DMA_Cmd(DMA1_Channel6, ENABLE);
} }
#endif

View file

@ -20,51 +20,51 @@
#include <platform.h> #include <platform.h>
#include "gpio.h" #include "io.h"
#include "nvic.h" #include "nvic.h"
#include "common/color.h" #include "common/color.h"
#include "drivers/light_ws2811strip.h" #include "drivers/light_ws2811strip.h"
#include "dma.h"
#include "rcc.h"
#include "timer.h"
#ifndef WS2811_GPIO #ifdef LED_STRIP
#define WS2811_GPIO GPIOB
#define WS2811_GPIO_AHB_PERIPHERAL RCC_AHBPeriph_GPIOB #ifndef WS2811_PIN
#define WS2811_GPIO_AF GPIO_AF_1 #define WS2811_PIN PB8 // TIM16_CH1
#define WS2811_PIN GPIO_Pin_8 // TIM16_CH1
#define WS2811_PIN_SOURCE GPIO_PinSource8
#define WS2811_TIMER TIM16 #define WS2811_TIMER TIM16
#define WS2811_TIMER_APB2_PERIPHERAL RCC_APB2Periph_TIM16
#define WS2811_DMA_CHANNEL DMA1_Channel3 #define WS2811_DMA_CHANNEL DMA1_Channel3
#define WS2811_IRQ DMA1_Channel3_IRQn
#define WS2811_DMA_TC_FLAG DMA1_FLAG_TC3
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_CH3_HANDLER #define WS2811_DMA_HANDLER_IDENTIFER DMA1_CH3_HANDLER
#endif #endif
static IO_t ws2811IO = IO_NONE;
bool ws2811Initialised = false;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
ws2811LedDataTransferInProgress = 0;
DMA_Cmd(descriptor->channel, DISABLE);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
}
}
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(void)
{ {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
uint16_t prescalerValue; uint16_t prescalerValue;
RCC_AHBPeriphClockCmd(WS2811_GPIO_AHB_PERIPHERAL, ENABLE); dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
GPIO_PinAFConfig(WS2811_GPIO, WS2811_PIN_SOURCE, WS2811_GPIO_AF); ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerGPIOAF(WS2811_TIMER));
/* Configuration alternate function push-pull */ RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = WS2811_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(WS2811_GPIO, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(WS2811_TIMER_APB2_PERIPHERAL, ENABLE);
/* Compute the prescaler value */ /* Compute the prescaler value */
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
@ -89,9 +89,6 @@ void ws2811LedStripHardwareInit(void)
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE);
/* configure DMA */ /* configure DMA */
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA1 Channel Config */ /* DMA1 Channel Config */
DMA_DeInit(WS2811_DMA_CHANNEL); DMA_DeInit(WS2811_DMA_CHANNEL);
@ -114,24 +111,20 @@ void ws2811LedStripHardwareInit(void)
DMA_ITConfig(WS2811_DMA_CHANNEL, DMA_IT_TC, ENABLE); DMA_ITConfig(WS2811_DMA_CHANNEL, DMA_IT_TC, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure; ws2811Initialised = true;
NVIC_InitStructure.NVIC_IRQChannel = WS2811_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_WS2811_DMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_WS2811_DMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
setStripColor(&hsv_white); setStripColor(&hsv_white);
ws2811UpdateStrip(); ws2811UpdateStrip();
} }
void ws2811LedStripDMAEnable(void) void ws2811LedStripDMAEnable(void)
{ {
if (!ws2811Initialised)
return;
DMA_SetCurrDataCounter(WS2811_DMA_CHANNEL, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(WS2811_DMA_CHANNEL, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(WS2811_TIMER, 0); TIM_SetCounter(WS2811_TIMER, 0);
TIM_Cmd(WS2811_TIMER, ENABLE); TIM_Cmd(WS2811_TIMER, ENABLE);
DMA_Cmd(WS2811_DMA_CHANNEL, ENABLE); DMA_Cmd(WS2811_DMA_CHANNEL, ENABLE);
} }
#endif

View file

@ -23,63 +23,116 @@
#include "common/color.h" #include "common/color.h"
#include "light_ws2811strip.h" #include "light_ws2811strip.h"
#include "nvic.h" #include "nvic.h"
#include "dma.h"
#include "io.h"
#include "system.h"
#include "rcc.h"
#include "timer.h"
#ifdef LED_STRIP #ifdef LED_STRIP
#if !defined(WS2811_PIN)
#define WS2811_PIN PA0
#define WS2811_TIMER TIM5
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER
#define WS2811_DMA_STREAM DMA1_Stream2
#define WS2811_DMA_IT DMA_IT_TCIF2
#define WS2811_DMA_CHANNEL DMA_Channel_6
#define WS2811_TIMER_CHANNEL TIM_Channel_1
#endif
static IO_t ws2811IO = IO_NONE;
static uint16_t timDMASource = 0;
bool ws2811Initialised = false;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
{
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
ws2811LedDataTransferInProgress = 0;
DMA_Cmd(descriptor->stream, DISABLE);
TIM_DMACmd(TIM5, TIM_DMA_CC1, DISABLE);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
}
}
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(void)
{ {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
uint16_t prescalerValue; uint16_t prescalerValue;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerGPIOAF(WS2811_TIMER));
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM5);
// Stop timer // Stop timer
TIM_Cmd(TIM5, DISABLE); TIM_Cmd(WS2811_TIMER, DISABLE);
/* Compute the prescaler value */ /* Compute the prescaler value */
prescalerValue = (uint16_t) (SystemCoreClock / 2 / 84000000) - 1; prescalerValue = (uint16_t)(SystemCoreClock / 2 / 84000000) - 1;
/* Time base configuration */ /* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 104; // 800kHz TIM_TimeBaseStructure.TIM_Period = 104; // 800kHz
TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue; TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */ /* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM5, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);
TIM_Cmd(TIM5, ENABLE); uint32_t channelAddress = 0;
switch (WS2811_TIMER_CHANNEL) {
case TIM_Channel_1:
TIM_OC1Init(WS2811_TIMER, &TIM_OCInitStructure);
timDMASource = TIM_DMA_CC1;
channelAddress = (uint32_t)(&WS2811_TIMER->CCR1);
TIM_OC1PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable);
break;
case TIM_Channel_2:
TIM_OC2Init(WS2811_TIMER, &TIM_OCInitStructure);
timDMASource = TIM_DMA_CC2;
channelAddress = (uint32_t)(&WS2811_TIMER->CCR2);
TIM_OC2PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable);
break;
case TIM_Channel_3:
TIM_OC3Init(WS2811_TIMER, &TIM_OCInitStructure);
timDMASource = TIM_DMA_CC3;
channelAddress = (uint32_t)(&WS2811_TIMER->CCR3);
TIM_OC3PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable);
break;
case TIM_Channel_4:
TIM_OC4Init(WS2811_TIMER, &TIM_OCInitStructure);
timDMASource = TIM_DMA_CC4;
channelAddress = (uint32_t)(&WS2811_TIMER->CCR4);
TIM_OC4PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable);
break;
}
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE);
TIM_ARRPreloadConfig(WS2811_TIMER, ENABLE);
TIM_CCxCmd(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_CCx_Enable);
TIM_Cmd(WS2811_TIMER, ENABLE);
/* configure DMA */ /* configure DMA */
/* DMA1 Channel Config */ DMA_Cmd(WS2811_DMA_STREAM, DISABLE);
DMA_Cmd(DMA1_Stream2, DISABLE); // disable DMA channel 6 DMA_DeInit(WS2811_DMA_STREAM);
DMA_DeInit(DMA1_Stream2);
DMA_StructInit(&DMA_InitStructure); DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_Channel = DMA_Channel_6; DMA_InitStructure.DMA_Channel = WS2811_DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM5->CCR1); DMA_InitStructure.DMA_PeripheralBaseAddr = channelAddress;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE;
@ -93,38 +146,28 @@ void ws2811LedStripHardwareInit(void)
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream2, &DMA_InitStructure);
DMA_ITConfig(DMA1_Stream2, DMA_IT_TC, ENABLE); DMA_Init(WS2811_DMA_STREAM, &DMA_InitStructure);
DMA_ClearITPendingBit(DMA1_Stream2, DMA_IT_TCIF2); // clear DMA1 Channel 6 transfer complete flag
NVIC_InitTypeDef NVIC_InitStructure; DMA_ITConfig(WS2811_DMA_STREAM, DMA_IT_TC, ENABLE);
DMA_ClearITPendingBit(WS2811_DMA_STREAM, WS2811_DMA_IT);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream2_IRQn; dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_WS2811_DMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_WS2811_DMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ws2811Initialised = true;
setStripColor(&hsv_white); setStripColor(&hsv_white);
ws2811UpdateStrip(); ws2811UpdateStrip();
} }
void DMA1_Stream2_IRQHandler(void)
{
if (DMA_GetFlagStatus(DMA1_Stream2, DMA_FLAG_TCIF2)) {
ws2811LedDataTransferInProgress = 0;
DMA_Cmd(DMA1_Stream2, DISABLE);
TIM_DMACmd(TIM5, TIM_DMA_CC1, DISABLE);
DMA_ClearITPendingBit(DMA1_Stream2, DMA_IT_TCIF2);
}
}
void ws2811LedStripDMAEnable(void) void ws2811LedStripDMAEnable(void)
{ {
DMA_SetCurrDataCounter(DMA1_Stream2, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred if (!ws2811Initialised)
TIM_SetCounter(TIM5, 0); return;
DMA_Cmd(DMA1_Stream2, ENABLE);
TIM_DMACmd(TIM5, TIM_DMA_CC1, ENABLE); DMA_SetCurrDataCounter(WS2811_DMA_STREAM, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(WS2811_TIMER, 0);
DMA_Cmd(WS2811_DMA_STREAM, ENABLE);
TIM_DMACmd(WS2811_TIMER, timDMASource, ENABLE);
} }
#endif #endif

View file

@ -15,20 +15,20 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include <stdint.h> #include <stdint.h>
#include "common/printf.h"
#include "platform.h" #include "platform.h"
#include "version.h" #include "version.h"
#ifdef USE_MAX7456 #ifdef USE_MAX7456
#include "common/printf.h"
#include "drivers/bus_spi.h" #include "drivers/bus_spi.h"
#include "drivers/light_led.h" #include "drivers/light_led.h"
#include "drivers/system.h" #include "drivers/system.h"
#include "drivers/nvic.h"
#include "drivers/dma.h"
#include "max7456.h" #include "max7456.h"
#include "max7456_symbols.h" #include "max7456_symbols.h"
@ -36,24 +36,116 @@
#define DISABLE_MAX7456 IOHi(max7456CsPin) #define DISABLE_MAX7456 IOHi(max7456CsPin)
#define ENABLE_MAX7456 IOLo(max7456CsPin) #define ENABLE_MAX7456 IOLo(max7456CsPin)
/** Artificial Horizon limits **/
#define AHIPITCHMAX 200 // Specify maximum AHI pitch value displayed. Default 200 = 20.0 degrees
#define AHIROLLMAX 400 // Specify maximum AHI roll value displayed. Default 400 = 40.0 degrees
#define AHISIDEBARWIDTHPOSITION 7
#define AHISIDEBARHEIGHTPOSITION 3
uint16_t max_screen_size; uint16_t max_screen_size;
char max7456_screen[VIDEO_BUFFER_CHARS_PAL]; static MAX7456_CHAR_TYPE max7456_screen[VIDEO_BUFFER_CHARS_PAL + 5];
#define SCREEN_BUFFER ((MAX7456_CHAR_TYPE*)&max7456_screen[3])
#ifdef MAX7456_DMA_CHANNEL_TX
volatile uint8_t dma_transaction_in_progress = 0;
#endif
static uint8_t video_signal_type = 0; static uint8_t video_signal_type = 0;
static uint8_t max7456_lock = 0; static uint8_t max7456_lock = 0;
static IO_t max7456CsPin = IO_NONE; static IO_t max7456CsPin = IO_NONE;
uint8_t max7456_send(uint8_t add, uint8_t data) {
MAX7456_CHAR_TYPE* max7456_get_screen_buffer(void) {
return SCREEN_BUFFER;
}
static uint8_t max7456_send(uint8_t add, uint8_t data)
{
spiTransferByte(MAX7456_SPI_INSTANCE, add); spiTransferByte(MAX7456_SPI_INSTANCE, add);
return spiTransferByte(MAX7456_SPI_INSTANCE, data); return spiTransferByte(MAX7456_SPI_INSTANCE, data);
} }
#ifdef MAX7456_DMA_CHANNEL_TX
static void max7456_send_dma(void* tx_buffer, void* rx_buffer, uint16_t buffer_size) {
DMA_InitTypeDef DMA_InitStructure;
#ifdef MAX7456_DMA_CHANNEL_RX
static uint16_t dummy[] = {0xffff};
#else
UNUSED(rx_buffer);
#endif
while (dma_transaction_in_progress); // Wait for prev DMA transaction
DMA_DeInit(MAX7456_DMA_CHANNEL_TX);
#ifdef MAX7456_DMA_CHANNEL_RX
DMA_DeInit(MAX7456_DMA_CHANNEL_RX);
#endif
// Common to both channels
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(MAX7456_SPI_INSTANCE->DR));
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_BufferSize = buffer_size;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
#ifdef MAX7456_DMA_CHANNEL_RX
// Rx Channel
DMA_InitStructure.DMA_MemoryBaseAddr = rx_buffer ? (uint32_t)rx_buffer : (uint32_t)(dummy);
DMA_InitStructure.DMA_MemoryInc = rx_buffer ? DMA_MemoryInc_Enable : DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_Init(MAX7456_DMA_CHANNEL_RX, &DMA_InitStructure);
DMA_Cmd(MAX7456_DMA_CHANNEL_RX, ENABLE);
#endif
// Tx channel
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tx_buffer; //max7456_screen;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_Init(MAX7456_DMA_CHANNEL_TX, &DMA_InitStructure);
DMA_Cmd(MAX7456_DMA_CHANNEL_TX, ENABLE);
#ifdef MAX7456_DMA_CHANNEL_RX
DMA_ITConfig(MAX7456_DMA_CHANNEL_RX, DMA_IT_TC, ENABLE);
#else
DMA_ITConfig(MAX7456_DMA_CHANNEL_TX, DMA_IT_TC, ENABLE);
#endif
// Enable SPI TX/RX request
ENABLE_MAX7456;
dma_transaction_in_progress = 1;
SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE,
#ifdef MAX7456_DMA_CHANNEL_RX
SPI_I2S_DMAReq_Rx |
#endif
SPI_I2S_DMAReq_Tx, ENABLE);
}
void max7456_dma_irq_handler(dmaChannelDescriptor_t* descriptor) {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
#ifdef MAX7456_DMA_CHANNEL_RX
DMA_Cmd(MAX7456_DMA_CHANNEL_RX, DISABLE);
#else
//Empty RX buffer. RX DMA takes care of it if enabled
while (SPI_I2S_GetFlagStatus(MAX7456_SPI_INSTANCE, SPI_I2S_FLAG_RXNE) == SET) {
MAX7456_SPI_INSTANCE->DR;
}
#endif
DMA_Cmd(MAX7456_DMA_CHANNEL_TX, DISABLE);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE,
#ifdef MAX7456_DMA_CHANNEL_RX
SPI_I2S_DMAReq_Rx |
#endif
SPI_I2S_DMAReq_Tx, DISABLE);
DISABLE_MAX7456;
for (uint16_t x = 0; x < max_screen_size; x++)
max7456_screen[x + 3] = MAX7456_CHAR(' ');
dma_transaction_in_progress = 0;
}
}
#endif
void max7456_init(uint8_t video_system) void max7456_init(uint8_t video_system)
{ {
@ -64,7 +156,7 @@ void max7456_init(uint8_t video_system)
#ifdef MAX7456_SPI_CS_PIN #ifdef MAX7456_SPI_CS_PIN
max7456CsPin = IOGetByTag(IO_TAG(MAX7456_SPI_CS_PIN)); max7456CsPin = IOGetByTag(IO_TAG(MAX7456_SPI_CS_PIN));
#endif #endif
IOInit(max7456CsPin, OWNER_SYSTEM, RESOURCE_SPI); IOInit(max7456CsPin, OWNER_OSD, RESOURCE_SPI_CS, 0);
IOConfigGPIO(max7456CsPin, SPI_IO_CS_CFG); IOConfigGPIO(max7456CsPin, SPI_IO_CS_CFG);
//Minimum spi clock period for max7456 is 100ns (10Mhz) //Minimum spi clock period for max7456 is 100ns (10Mhz)
@ -112,94 +204,66 @@ void max7456_init(uint8_t video_system)
DISABLE_MAX7456; DISABLE_MAX7456;
delay(100); delay(100);
for (x = 0; x < max_screen_size; x++)
SCREEN_BUFFER[x] = MAX7456_CHAR(' ');
#ifdef MAX7456_DMA_CHANNEL_TX
max7456_screen[0] = (uint16_t)(MAX7456ADD_DMAH | (0 << 8));
max7456_screen[1] = (uint16_t)(MAX7456ADD_DMAL | (0 << 8));
max7456_screen[2] = (uint16_t)(MAX7456ADD_DMM | (1 << 8));
max7456_screen[max_screen_size + 3] = (uint16_t)(MAX7456ADD_DMDI | (0xFF << 8));
max7456_screen[max_screen_size + 4] = (uint16_t)(MAX7456ADD_DMM | (0 << 8));
dmaSetHandler(MAX7456_DMA_IRQ_HANDLER_ID, max7456_dma_irq_handler, NVIC_PRIO_MAX7456_DMA, 0);
#endif
} }
// Copy string from ram into screen buffer // Copy string from ram into screen buffer
void max7456_write_string(const char *string, int16_t address) { void max7456_write_string(const char *string, int16_t address) {
char *dest; MAX7456_CHAR_TYPE *dest;
if (address >= 0) if (address >= 0)
dest = max7456_screen + address; dest = SCREEN_BUFFER + address;
else else
dest = max7456_screen + (max_screen_size + address); dest = SCREEN_BUFFER + (max_screen_size + address);
while(*string && dest < (max7456_screen + max_screen_size)) while(*string && dest < (SCREEN_BUFFER + max_screen_size)) {
*dest++ = *string++; *dest++ = MAX7456_CHAR(*string++);
}
// Write the artifical horizon to the screen buffer
void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars) {
uint16_t position = 194;
if(pitchAngle>AHIPITCHMAX) pitchAngle=AHIPITCHMAX;
if(pitchAngle<-AHIPITCHMAX) pitchAngle=-AHIPITCHMAX;
if(rollAngle>AHIROLLMAX) rollAngle=AHIROLLMAX;
if(rollAngle<-AHIROLLMAX) rollAngle=-AHIROLLMAX;
for(uint8_t X=0; X<=8; X++) {
if (X==4) X=5;
int Y = (rollAngle * (4-X)) / 64;
Y -= pitchAngle / 8;
Y += 41;
if(Y >= 0 && Y <= 81) {
uint16_t pos = position -7 + LINE*(Y/9) + 3 - 4*LINE + X;
max7456_screen[pos] = SYM_AH_BAR9_0+(Y%9);
}
}
max7456_screen[position-1] = SYM_AH_CENTER_LINE;
max7456_screen[position+1] = SYM_AH_CENTER_LINE_RIGHT;
max7456_screen[position] = SYM_AH_CENTER;
if (show_sidebars) {
// Draw AH sides
int8_t hudwidth = AHISIDEBARWIDTHPOSITION;
int8_t hudheight = AHISIDEBARHEIGHTPOSITION;
for(int8_t X=-hudheight; X<=hudheight; X++) {
max7456_screen[position-hudwidth+(X*LINE)] = SYM_AH_DECORATION;
max7456_screen[position+hudwidth+(X*LINE)] = SYM_AH_DECORATION;
}
// AH level indicators
max7456_screen[position-hudwidth+1] = SYM_AH_LEFT;
max7456_screen[position+hudwidth-1] = SYM_AH_RIGHT;
} }
} }
void max7456_draw_screen(void) { void max7456_draw_screen(void) {
uint16_t xx;
if (!max7456_lock) { if (!max7456_lock) {
ENABLE_MAX7456; #ifdef MAX7456_DMA_CHANNEL_TX
for (xx = 0; xx < max_screen_size; ++xx) { max7456_send_dma(max7456_screen, NULL, max_screen_size * 2 + 10);
max7456_send(MAX7456ADD_DMAH, xx>>8); #else
max7456_send(MAX7456ADD_DMAL, xx); uint16_t xx;
max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]); max7456_lock = 1;
max7456_screen[xx] = ' ';
}
DISABLE_MAX7456;
}
}
void max7456_draw_screen_fast(void) {
uint16_t xx;
if (!max7456_lock) {
ENABLE_MAX7456; ENABLE_MAX7456;
max7456_send(MAX7456ADD_DMAH, 0); max7456_send(MAX7456ADD_DMAH, 0);
max7456_send(MAX7456ADD_DMAL, 0); max7456_send(MAX7456ADD_DMAL, 0);
max7456_send(MAX7456ADD_DMM, 1); max7456_send(MAX7456ADD_DMM, 1);
for (xx = 0; xx < max_screen_size; ++xx) { for (xx = 0; xx < max_screen_size; ++xx) {
max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]); max7456_send(MAX7456ADD_DMDI, SCREEN_BUFFER[xx]);
max7456_screen[xx] = ' '; SCREEN_BUFFER[xx] = MAX7456_CHAR(0);
} }
max7456_send(MAX7456ADD_DMDI, 0xFF); max7456_send(MAX7456ADD_DMDI, 0xFF);
max7456_send(MAX7456ADD_DMM, 0); max7456_send(MAX7456ADD_DMM, 0);
DISABLE_MAX7456; DISABLE_MAX7456;
max7456_lock = 0;
#endif
} }
} }
void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) { void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) {
uint8_t x; uint8_t x;
#ifdef MAX7456_DMA_CHANNEL_TX
while (dma_transaction_in_progress);
#endif
while (max7456_lock);
max7456_lock = 1; max7456_lock = 1;
ENABLE_MAX7456; ENABLE_MAX7456;

View file

@ -143,12 +143,18 @@
enum VIDEO_TYPES { AUTO = 0, PAL, NTSC }; enum VIDEO_TYPES { AUTO = 0, PAL, NTSC };
extern uint16_t max_screen_size; extern uint16_t max_screen_size;
extern char max7456_screen[VIDEO_BUFFER_CHARS_PAL];
#ifdef MAX7456_DMA_CHANNEL_TX
#define MAX7456_CHAR_TYPE uint16_t
#define MAX7456_CHAR(X) (MAX7456ADD_DMDI | ((X) << 8))
#else
#define MAX7456_CHAR_TYPE char
#define MAX7456_CHAR(X) (X)
#endif
void max7456_init(uint8_t system); void max7456_init(uint8_t system);
void max7456_draw_screen(void); void max7456_draw_screen(void);
void max7456_draw_screen_fast(void);
void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars);
void max7456_write_string(const char *string, int16_t address); void max7456_write_string(const char *string, int16_t address);
void max7456_write_nvm(uint8_t char_address, uint8_t *font_data); void max7456_write_nvm(uint8_t char_address, uint8_t *font_data);
MAX7456_CHAR_TYPE* max7456_get_screen_buffer(void);

View file

@ -38,6 +38,7 @@
#define NVIC_PRIO_MPU_DATA_READY NVIC_BUILD_PRIORITY(0x0f, 0x0f) #define NVIC_PRIO_MPU_DATA_READY NVIC_BUILD_PRIORITY(0x0f, 0x0f)
#define NVIC_PRIO_MAG_DATA_READY NVIC_BUILD_PRIORITY(0x0f, 0x0f) #define NVIC_PRIO_MAG_DATA_READY NVIC_BUILD_PRIORITY(0x0f, 0x0f)
#define NVIC_PRIO_CALLBACK NVIC_BUILD_PRIORITY(0x0f, 0x0f) #define NVIC_PRIO_CALLBACK NVIC_BUILD_PRIORITY(0x0f, 0x0f)
#define NVIC_PRIO_MAX7456_DMA NVIC_BUILD_PRIORITY(3, 0)
// utility macros to join/split priority // utility macros to join/split priority
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING>>8))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING>>8)))))<<4)&0xf0) #define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING>>8))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING>>8)))))<<4)&0xf0)

View file

@ -18,7 +18,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
@ -93,16 +92,6 @@ pwmOutputConfiguration_t *pwmGetOutputConfiguration(void)
return &pwmOutputConfiguration; return &pwmOutputConfiguration;
} }
bool CheckGPIOPin(ioTag_t tag, GPIO_TypeDef *gpio, uint16_t pin)
{
return IO_GPIOBYTAG(tag) == gpio && IO_PINBYTAG(tag) == pin;
}
bool CheckGPIOPinSource(ioTag_t tag, GPIO_TypeDef *gpio, uint16_t pin)
{
return IO_GPIOBYTAG(tag) == gpio && IO_GPIO_PinSource(IOGetByTag(tag)) == pin;
}
pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init) pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
{ {
int i = 0; int i = 0;
@ -142,9 +131,9 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
continue; continue;
#endif #endif
#if defined(STM32F303xC) && defined(USE_USART3) #if defined(STM32F303xC) && defined(USE_UART3)
// skip UART3 ports (PB10/PB11) // skip UART3 ports (PB10/PB11)
if (init->useUART3 && (CheckGPIOPin(timerHardwarePtr->tag, UART3_GPIO, UART3_TX_PIN) || CheckGPIOPin(timerHardwarePtr->tag, UART3_GPIO, UART3_RX_PIN))) if (init->useUART3 && (timerHardwarePtr->tag == IO_TAG(UART3_TX_PIN) || timerHardwarePtr->tag == IO_TAG(UART3_RX_PIN)))
continue; continue;
#endif #endif
@ -157,33 +146,33 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
continue; continue;
#endif #endif
#ifdef LED_STRIP_TIMER #ifdef WS2811_TIMER
// skip LED Strip output // skip LED Strip output
if (init->useLEDStrip) { if (init->useLEDStrip) {
if (timerHardwarePtr->tim == LED_STRIP_TIMER) if (timerHardwarePtr->tim == WS2811_TIMER)
continue; continue;
#if defined(STM32F303xC) && defined(WS2811_GPIO) && defined(WS2811_PIN_SOURCE) #if defined(STM32F303xC) && defined(WS2811_PIN)
if (CheckGPIOPinSource(timerHardwarePtr->tag, WS2811_GPIO, WS2811_PIN_SOURCE)) if (timerHardwarePtr->tag == IO_TAG(WS2811_PIN))
continue; continue;
#endif #endif
} }
#endif #endif
#ifdef VBAT_ADC_GPIO #ifdef VBAT_ADC_PIN
if (init->useVbat && CheckGPIOPin(timerHardwarePtr->tag, VBAT_ADC_GPIO, VBAT_ADC_GPIO_PIN)) { if (init->useVbat && timerHardwarePtr->tag == IO_TAG(VBAT_ADC_PIN)) {
continue; continue;
} }
#endif #endif
#ifdef RSSI_ADC_GPIO #ifdef RSSI_ADC_GPIO
if (init->useRSSIADC && CheckGPIOPin(timerHardwarePtr->tag, RSSI_ADC_GPIO, RSSI_ADC_GPIO_PIN)) { if (init->useRSSIADC && timerHardwarePtr->tag == IO_TAG(RSSI_ADC_PIN)) {
continue; continue;
} }
#endif #endif
#ifdef CURRENT_METER_ADC_GPIO #ifdef CURRENT_METER_ADC_GPIO
if (init->useCurrentMeterADC && CheckGPIOPin(timerHardwarePtr->tag, CURRENT_METER_ADC_GPIO, CURRENT_METER_ADC_GPIO_PIN)) { if (init->useCurrentMeterADC && timerHardwarePtr->tag == IO_TAG(CURRENT_METER_ADC_PIN)) {
continue; continue;
} }
#endif #endif
@ -274,7 +263,7 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
} }
if (init->useChannelForwarding && !init->airplane) { if (init->useChannelForwarding && !init->airplane) {
#if defined(NAZE) && defined(LED_STRIP_TIMER) #if defined(NAZE) && defined(WS2811_TIMER)
// if LED strip is active, PWM5-8 are unavailable, so map AUX1+AUX2 to PWM13+PWM14 // if LED strip is active, PWM5-8 are unavailable, so map AUX1+AUX2 to PWM13+PWM14
if (init->useLEDStrip) { if (init->useLEDStrip) {
if (timerIndex >= PWM13 && timerIndex <= PWM14) { if (timerIndex >= PWM13 && timerIndex <= PWM14) {
@ -306,7 +295,7 @@ pwmOutputConfiguration_t *pwmInit(drv_pwm_config_t *init)
if (type == MAP_TO_PPM_INPUT) { if (type == MAP_TO_PPM_INPUT) {
#if defined(SPARKY) || defined(ALIENFLIGHTF3) #if defined(SPARKY) || defined(ALIENFLIGHTF3)
if (init->useFastPwm || init->pwmProtocolType == PWM_TYPE_BRUSHED) { if (init->useFastPwm || init->pwmProtocolType == PWM_TYPE_BRUSHED) {
ppmAvoidPWMTimerClash(timerHardwarePtr, TIM2); ppmAvoidPWMTimerClash(timerHardwarePtr, TIM2);
} }
#endif #endif

View file

@ -34,10 +34,20 @@
#define MAX_INPUTS 8 #define MAX_INPUTS 8
#define PWM_TIMER_MHZ 1 #define PWM_TIMER_MHZ 1
#if defined(STM32F40_41xxx) // must be multiples of timer clock
#define ONESHOT42_TIMER_MHZ 21
#define ONESHOT125_TIMER_MHZ 12
#define PWM_BRUSHED_TIMER_MHZ 21
#define MULTISHOT_TIMER_MHZ 84
#else
#define PWM_BRUSHED_TIMER_MHZ 24 #define PWM_BRUSHED_TIMER_MHZ 24
#define MULTISHOT_TIMER_MHZ 72 #define MULTISHOT_TIMER_MHZ 72
#define ONESHOT42_TIMER_MHZ 24 #define ONESHOT42_TIMER_MHZ 24
#define ONESHOT125_TIMER_MHZ 8 #define ONESHOT125_TIMER_MHZ 8
#endif
#define MULTISHOT_5US_PW (MULTISHOT_TIMER_MHZ * 5)
#define MULTISHOT_20US_MULT (MULTISHOT_TIMER_MHZ * 20 / 1000.0f)
typedef struct sonarIOConfig_s { typedef struct sonarIOConfig_s {
ioTag_t triggerTag; ioTag_t triggerTag;
@ -78,23 +88,21 @@ typedef struct drv_pwm_config_s {
} drv_pwm_config_t; } drv_pwm_config_t;
enum { enum {
MAP_TO_PPM_INPUT = 1, MAP_TO_PPM_INPUT = 1,
MAP_TO_PWM_INPUT, MAP_TO_PWM_INPUT,
MAP_TO_MOTOR_OUTPUT, MAP_TO_MOTOR_OUTPUT,
MAP_TO_SERVO_OUTPUT, MAP_TO_SERVO_OUTPUT,
}; };
typedef enum { typedef enum {
PWM_PF_NONE = 0, PWM_PF_NONE = 0,
PWM_PF_MOTOR = (1 << 0), PWM_PF_MOTOR = (1 << 0),
PWM_PF_SERVO = (1 << 1), PWM_PF_SERVO = (1 << 1),
PWM_PF_MOTOR_MODE_BRUSHED = (1 << 2), PWM_PF_MOTOR_MODE_BRUSHED = (1 << 2),
PWM_PF_OUTPUT_PROTOCOL_PWM = (1 << 3), PWM_PF_OUTPUT_PROTOCOL_PWM = (1 << 3),
PWM_PF_OUTPUT_PROTOCOL_ONESHOT = (1 << 4) PWM_PF_OUTPUT_PROTOCOL_ONESHOT = (1 << 4)
} pwmPortFlags_e; } pwmPortFlags_e;
enum {PWM_INVERTED = 1};
typedef struct pwmPortConfiguration_s { typedef struct pwmPortConfiguration_s {
uint8_t index; uint8_t index;
pwmPortFlags_e flags; pwmPortFlags_e flags;

View file

@ -84,22 +84,19 @@ static void pwmOCConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t value, uint8
} }
} }
static void pwmGPIOConfig(ioTag_t pin, ioConfig_t mode)
{
IOInit(IOGetByTag(pin), OWNER_PWMOUTPUT_MOTOR, RESOURCE_OUTPUT);
IOConfigGPIO(IOGetByTag(pin), mode);
}
static pwmOutputPort_t *pwmOutConfig(const timerHardware_t *timerHardware, uint8_t mhz, uint16_t period, uint16_t value) static pwmOutputPort_t *pwmOutConfig(const timerHardware_t *timerHardware, uint8_t mhz, uint16_t period, uint16_t value)
{ {
pwmOutputPort_t *p = &pwmOutputPorts[allocatedOutputPortCount++]; pwmOutputPort_t *p = &pwmOutputPorts[allocatedOutputPortCount++];
configTimeBase(timerHardware->tim, period, mhz); configTimeBase(timerHardware->tim, period, mhz);
pwmGPIOConfig(timerHardware->tag, IOCFG_AF_PP);
pwmOCConfig(timerHardware->tim, timerHardware->channel, value, timerHardware->outputInverted); IO_t io = IOGetByTag(timerHardware->tag);
IOInit(io, OWNER_MOTOR, RESOURCE_OUTPUT, allocatedOutputPortCount);
IOConfigGPIO(io, IOCFG_AF_PP);
if (timerHardware->outputEnable) { pwmOCConfig(timerHardware->tim, timerHardware->channel, value, timerHardware->output & TIMER_OUTPUT_INVERTED);
if (timerHardware->output & TIMER_OUTPUT_ENABLED) {
TIM_CtrlPWMOutputs(timerHardware->tim, ENABLE); TIM_CtrlPWMOutputs(timerHardware->tim, ENABLE);
} }
TIM_Cmd(timerHardware->tim, ENABLE); TIM_Cmd(timerHardware->tim, ENABLE);
@ -121,6 +118,8 @@ static pwmOutputPort_t *pwmOutConfig(const timerHardware_t *timerHardware, uint8
p->period = period; p->period = period;
p->tim = timerHardware->tim; p->tim = timerHardware->tim;
*p->ccr = 0;
return p; return p;
} }
@ -134,9 +133,19 @@ static void pwmWriteStandard(uint8_t index, uint16_t value)
*motors[index]->ccr = value; *motors[index]->ccr = value;
} }
static void pwmWriteOneShot42(uint8_t index, uint16_t value)
{
*motors[index]->ccr = lrintf((float)(value * ONESHOT42_TIMER_MHZ/24.0f));
}
static void pwmWriteOneShot125(uint8_t index, uint16_t value)
{
*motors[index]->ccr = lrintf((float)(value * ONESHOT125_TIMER_MHZ/8.0f));
}
static void pwmWriteMultiShot(uint8_t index, uint16_t value) static void pwmWriteMultiShot(uint8_t index, uint16_t value)
{ {
*motors[index]->ccr = lrintf(((float)(value-1000) / 0.69444f) + 360); *motors[index]->ccr = lrintf(((float)(value-1000) * MULTISHOT_20US_MULT) + MULTISHOT_5US_PW);
} }
void pwmWriteMotor(uint8_t index, uint16_t value) void pwmWriteMotor(uint8_t index, uint16_t value)
@ -221,7 +230,9 @@ void pwmFastPwmMotorConfig(const timerHardware_t *timerHardware, uint8_t motorIn
motors[motorIndex] = pwmOutConfig(timerHardware, timerMhzCounter, 0xFFFF, 0); motors[motorIndex] = pwmOutConfig(timerHardware, timerMhzCounter, 0xFFFF, 0);
} }
motors[motorIndex]->pwmWritePtr = (fastPwmProtocolType == PWM_TYPE_MULTISHOT) ? pwmWriteMultiShot : pwmWriteStandard; motors[motorIndex]->pwmWritePtr = (fastPwmProtocolType == PWM_TYPE_MULTISHOT) ? pwmWriteMultiShot :
((fastPwmProtocolType == PWM_TYPE_ONESHOT125) ? pwmWriteOneShot125 :
pwmWriteOneShot42);
} }
#ifdef USE_SERVOS #ifdef USE_SERVOS

View file

@ -18,9 +18,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <platform.h> #include <platform.h>
#include "build_config.h" #include "build_config.h"
#include "debug.h" #include "debug.h"
@ -337,12 +336,6 @@ static void pwmEdgeCallback(timerCCHandlerRec_t *cbRec, captureCompare_t capture
} }
} }
static void pwmGPIOConfig(ioTag_t pin, ioConfig_t mode)
{
IOInit(IOGetByTag(pin), OWNER_PWMINPUT, RESOURCE_INPUT);
IOConfigGPIO(IOGetByTag(pin), mode);
}
void pwmICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity) void pwmICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity)
{ {
TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitTypeDef TIM_ICInitStructure;
@ -372,7 +365,10 @@ void pwmInConfig(const timerHardware_t *timerHardwarePtr, uint8_t channel)
self->mode = INPUT_MODE_PWM; self->mode = INPUT_MODE_PWM;
self->timerHardware = timerHardwarePtr; self->timerHardware = timerHardwarePtr;
pwmGPIOConfig(timerHardwarePtr->tag, timerHardwarePtr->ioMode); IO_t io = IOGetByTag(timerHardwarePtr->tag);
IOInit(io, OWNER_PWMINPUT, RESOURCE_INPUT, RESOURCE_INDEX(channel));
IOConfigGPIO(io, timerHardwarePtr->ioMode);
pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising);
timerConfigure(timerHardwarePtr, (uint16_t)PWM_TIMER_PERIOD, PWM_TIMER_MHZ); timerConfigure(timerHardwarePtr, (uint16_t)PWM_TIMER_PERIOD, PWM_TIMER_MHZ);
@ -401,7 +397,10 @@ void ppmInConfig(const timerHardware_t *timerHardwarePtr)
self->mode = INPUT_MODE_PPM; self->mode = INPUT_MODE_PPM;
self->timerHardware = timerHardwarePtr; self->timerHardware = timerHardwarePtr;
pwmGPIOConfig(timerHardwarePtr->tag, timerHardwarePtr->ioMode); IO_t io = IOGetByTag(timerHardwarePtr->tag);
IOInit(io, OWNER_PPMINPUT, RESOURCE_INPUT, 0);
IOConfigGPIO(io, timerHardwarePtr->ioMode);
pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising); pwmICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Rising);
timerConfigure(timerHardwarePtr, (uint16_t)PPM_TIMER_PERIOD, PWM_TIMER_MHZ); timerConfigure(timerHardwarePtr, (uint16_t)PPM_TIMER_PERIOD, PWM_TIMER_MHZ);

View file

@ -7,7 +7,7 @@ void RCC_ClockCmd(rccPeriphTag_t periphTag, FunctionalState NewState)
int tag = periphTag >> 5; int tag = periphTag >> 5;
uint32_t mask = 1 << (periphTag & 0x1f); uint32_t mask = 1 << (periphTag & 0x1f);
switch (tag) { switch (tag) {
#if defined(STM32F303xC) #if defined(STM32F3) || defined(STM32F1)
case RCC_AHB: case RCC_AHB:
RCC_AHBPeriphClockCmd(mask, NewState); RCC_AHBPeriphClockCmd(mask, NewState);
break; break;
@ -18,7 +18,7 @@ void RCC_ClockCmd(rccPeriphTag_t periphTag, FunctionalState NewState)
case RCC_APB1: case RCC_APB1:
RCC_APB1PeriphClockCmd(mask, NewState); RCC_APB1PeriphClockCmd(mask, NewState);
break; break;
#if defined(STM32F40_41xxx) || defined(STM32F411xE) #if defined(STM32F4)
case RCC_AHB1: case RCC_AHB1:
RCC_AHB1PeriphClockCmd(mask, NewState); RCC_AHB1PeriphClockCmd(mask, NewState);
break; break;
@ -31,7 +31,7 @@ void RCC_ResetCmd(rccPeriphTag_t periphTag, FunctionalState NewState)
int tag = periphTag >> 5; int tag = periphTag >> 5;
uint32_t mask = 1 << (periphTag & 0x1f); uint32_t mask = 1 << (periphTag & 0x1f);
switch (tag) { switch (tag) {
#if defined(STM32F303xC) #if defined(STM32F3) || defined(STM32F10X_CL)
case RCC_AHB: case RCC_AHB:
RCC_AHBPeriphResetCmd(mask, NewState); RCC_AHBPeriphResetCmd(mask, NewState);
break; break;
@ -42,7 +42,7 @@ void RCC_ResetCmd(rccPeriphTag_t periphTag, FunctionalState NewState)
case RCC_APB1: case RCC_APB1:
RCC_APB1PeriphResetCmd(mask, NewState); RCC_APB1PeriphResetCmd(mask, NewState);
break; break;
#if defined(STM32F40_41xxx) || defined(STM32F411xE) #if defined(STM32F4)
case RCC_AHB1: case RCC_AHB1:
RCC_AHB1PeriphResetCmd(mask, NewState); RCC_AHB1PeriphResetCmd(mask, NewState);
break; break;

View file

@ -1,46 +1,52 @@
#pragma once #pragma once
#define RESOURCE_INDEX(x) x + 1
typedef enum { typedef enum {
OWNER_FREE = 0, OWNER_FREE = 0,
OWNER_PWMINPUT, OWNER_PWMINPUT,
OWNER_PPMINPUT, OWNER_PPMINPUT,
OWNER_PWMOUTPUT_MOTOR, OWNER_MOTOR,
OWNER_PWMOUTPUT_SERVO, OWNER_SERVO,
OWNER_SOFTSERIAL_RX, OWNER_SOFTSERIAL,
OWNER_SOFTSERIAL_TX,
OWNER_SOFTSERIAL_RXTX, // bidirectional pin for softserial
OWNER_SOFTSERIAL_AUXTIMER, // timer channel is used for softserial. No IO function on pin
OWNER_ADC, OWNER_ADC,
OWNER_SERIAL_RX, OWNER_SERIAL,
OWNER_SERIAL_TX,
OWNER_SERIAL_RXTX,
OWNER_PINDEBUG, OWNER_PINDEBUG,
OWNER_TIMER, OWNER_TIMER,
OWNER_SONAR, OWNER_SONAR,
OWNER_SYSTEM, OWNER_SYSTEM,
OWNER_SPI,
OWNER_I2C,
OWNER_SDCARD, OWNER_SDCARD,
OWNER_FLASH, OWNER_FLASH,
OWNER_USB, OWNER_USB,
OWNER_BEEPER, OWNER_BEEPER,
OWNER_OSD, OWNER_OSD,
OWNER_BARO, OWNER_BARO,
OWNER_MPU,
OWNER_INVERTER,
OWNER_LED_STRIP,
OWNER_LED,
OWNER_RX,
OWNER_TX,
OWNER_TOTAL_COUNT OWNER_TOTAL_COUNT
} resourceOwner_t; } resourceOwner_t;
extern const char * const ownerNames[OWNER_TOTAL_COUNT];
// Currently TIMER should be shared resource (softserial dualtimer and timerqueue needs to allocate timer channel, but pin can be used for other function) // Currently TIMER should be shared resource (softserial dualtimer and timerqueue needs to allocate timer channel, but pin can be used for other function)
// with mode switching (shared serial ports, ...) this will need some improvement // with mode switching (shared serial ports, ...) this will need some improvement
typedef enum { typedef enum {
RESOURCE_NONE = 0, RESOURCE_NONE = 0,
RESOURCE_INPUT = 1 << 0, RESOURCE_INPUT, RESOURCE_OUTPUT, RESOURCE_IO,
RESOURCE_OUTPUT = 1 << 1, RESOURCE_TIMER,
RESOURCE_IO = RESOURCE_INPUT | RESOURCE_OUTPUT, RESOURCE_UART_TX, RESOURCE_UART_RX, RESOURCE_UART_TXRX,
RESOURCE_TIMER = 1 << 2, RESOURCE_EXTI,
RESOURCE_TIMER_DUAL = 1 << 3, // channel used in dual-capture, other channel will be allocated too RESOURCE_I2C_SCL, RESOURCE_I2C_SDA,
RESOURCE_USART = 1 << 4, RESOURCE_SPI_SCK, RESOURCE_SPI_MOSI, RESOURCE_SPI_MISO, RESOURCE_SPI_CS,
RESOURCE_ADC = 1 << 5, RESOURCE_ADC_BATTERY, RESOURCE_ADC_RSSI, RESOURCE_ADC_EXTERNAL1, RESOURCE_ADC_CURRENT,
RESOURCE_EXTI = 1 << 6, RESOURCE_TOTAL_COUNT
RESOURCE_I2C = 1 << 7,
RESOURCE_SPI = 1 << 8,
} resourceType_t; } resourceType_t;
extern const char * const resourceNames[RESOURCE_TOTAL_COUNT];

View file

@ -15,12 +15,13 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "platform.h" #include "platform.h"
#ifdef USE_SDCARD
#include "nvic.h" #include "nvic.h"
#include "io.h" #include "io.h"
@ -30,8 +31,6 @@
#include "sdcard.h" #include "sdcard.h"
#include "sdcard_standard.h" #include "sdcard_standard.h"
#ifdef USE_SDCARD
#ifdef AFATFS_USE_INTROSPECTIVE_LOGGING #ifdef AFATFS_USE_INTROSPECTIVE_LOGGING
#define SDCARD_PROFILING #define SDCARD_PROFILING
#endif #endif
@ -44,7 +43,7 @@
// Chosen so that CMD8 will have the same CRC as CMD0: // Chosen so that CMD8 will have the same CRC as CMD0:
#define SDCARD_IF_COND_CHECK_PATTERN 0xAB #define SDCARD_IF_COND_CHECK_PATTERN 0xAB
#define SDCARD_TIMEOUT_INIT_MILLIS 2000 #define SDCARD_TIMEOUT_INIT_MILLIS 200
#define SDCARD_MAX_CONSECUTIVE_FAILURES 8 #define SDCARD_MAX_CONSECUTIVE_FAILURES 8
/* Break up 512-byte SD card sectors into chunks of this size when writing without DMA to reduce the peak overhead /* Break up 512-byte SD card sectors into chunks of this size when writing without DMA to reduce the peak overhead
@ -126,7 +125,7 @@ void sdcardInsertionDetectDeinit(void)
{ {
#ifdef SDCARD_DETECT_PIN #ifdef SDCARD_DETECT_PIN
sdCardDetectPin = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN)); sdCardDetectPin = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN));
IOInit(sdCardDetectPin, OWNER_SYSTEM, RESOURCE_SPI); IOInit(sdCardDetectPin, OWNER_FREE, RESOURCE_NONE, 0);
IOConfigGPIO(sdCardDetectPin, IOCFG_IN_FLOATING); IOConfigGPIO(sdCardDetectPin, IOCFG_IN_FLOATING);
#endif #endif
} }
@ -135,7 +134,7 @@ void sdcardInsertionDetectInit(void)
{ {
#ifdef SDCARD_DETECT_PIN #ifdef SDCARD_DETECT_PIN
sdCardDetectPin = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN)); sdCardDetectPin = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN));
IOInit(sdCardDetectPin, OWNER_SDCARD, RESOURCE_INPUT); IOInit(sdCardDetectPin, OWNER_SDCARD, RESOURCE_INPUT, 0);
IOConfigGPIO(sdCardDetectPin, IOCFG_IPU); IOConfigGPIO(sdCardDetectPin, IOCFG_IPU);
#endif #endif
} }
@ -547,7 +546,7 @@ void sdcard_init(bool useDMA)
#ifdef SDCARD_SPI_CS_PIN #ifdef SDCARD_SPI_CS_PIN
sdCardCsPin = IOGetByTag(IO_TAG(SDCARD_SPI_CS_PIN)); sdCardCsPin = IOGetByTag(IO_TAG(SDCARD_SPI_CS_PIN));
IOInit(sdCardCsPin, OWNER_SDCARD, RESOURCE_SPI); IOInit(sdCardCsPin, OWNER_SDCARD, RESOURCE_SPI_CS, 0);
IOConfigGPIO(sdCardCsPin, SPI_IO_CS_CFG); IOConfigGPIO(sdCardCsPin, SPI_IO_CS_CFG);
#endif // SDCARD_SPI_CS_PIN #endif // SDCARD_SPI_CS_PIN

View file

@ -22,4 +22,4 @@ typedef void (*sensorInitFuncPtr)(void); // sensor init proto
typedef bool (*sensorReadFuncPtr)(int16_t *data); // sensor read and align prototype typedef bool (*sensorReadFuncPtr)(int16_t *data); // sensor read and align prototype
typedef void (*sensorAccInitFuncPtr)(struct acc_s *acc); // sensor init prototype typedef void (*sensorAccInitFuncPtr)(struct acc_s *acc); // sensor init prototype
typedef void (*sensorGyroInitFuncPtr)(uint8_t lpf); // gyro sensor init prototype typedef void (*sensorGyroInitFuncPtr)(uint8_t lpf); // gyro sensor init prototype
typedef void (*sensorInterruptFuncPtr)(bool *data); // sensor Interrupt Data Ready typedef bool (*sensorInterruptFuncPtr)(void); // sensor Interrupt Data Ready

View file

@ -56,7 +56,7 @@ void serialWriteBuf(serialPort_t *instance, uint8_t *data, int count)
} }
} }
uint8_t serialRxBytesWaiting(serialPort_t *instance) uint32_t serialRxBytesWaiting(serialPort_t *instance)
{ {
return instance->vTable->serialTotalRxWaiting(instance); return instance->vTable->serialTotalRxWaiting(instance);
} }

View file

@ -81,7 +81,7 @@ struct serialPortVTable {
}; };
void serialWrite(serialPort_t *instance, uint8_t ch); void serialWrite(serialPort_t *instance, uint8_t ch);
uint8_t serialRxBytesWaiting(serialPort_t *instance); uint32_t serialRxBytesWaiting(serialPort_t *instance);
uint8_t serialTxBytesFree(serialPort_t *instance); uint8_t serialTxBytesFree(serialPort_t *instance);
void serialWriteBuf(serialPort_t *instance, uint8_t *data, int count); void serialWriteBuf(serialPort_t *instance, uint8_t *data, int count);
uint8_t serialRead(serialPort_t *instance); uint8_t serialRead(serialPort_t *instance);

View file

@ -17,7 +17,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
@ -96,23 +95,24 @@ void setTxSignal(softSerial_t *softSerial, uint8_t state)
if (state) { if (state) {
IOHi(softSerial->txIO); IOHi(softSerial->txIO);
} else { } else {
IOLo(softSerial->txIO); IOLo(softSerial->txIO);
} }
} }
static void softSerialGPIOConfig(ioTag_t pin, ioConfig_t mode) void serialInputPortConfig(ioTag_t pin, uint8_t portIndex)
{ {
IOInit(IOGetByTag(pin), OWNER_SOFTSERIAL_RXTX, RESOURCE_USART); IOInit(IOGetByTag(pin), OWNER_SOFTSERIAL, RESOURCE_UART_RX, RESOURCE_INDEX(portIndex));
IOConfigGPIO(IOGetByTag(pin), mode); #ifdef STM32F1
IOConfigGPIO(IOGetByTag(pin), IOCFG_IPU);
#else
IOConfigGPIO(IOGetByTag(pin), IOCFG_AF_PP_UP);
#endif
} }
void serialInputPortConfig(ioTag_t pin) static void serialOutputPortConfig(ioTag_t pin, uint8_t portIndex)
{ {
#ifdef STM32F1 IOInit(IOGetByTag(pin), OWNER_SOFTSERIAL, RESOURCE_UART_TX, RESOURCE_INDEX(portIndex));
softSerialGPIOConfig(pin, IOCFG_IPU); IOConfigGPIO(IOGetByTag(pin), IOCFG_OUT_PP);
#else
softSerialGPIOConfig(pin, IOCFG_AF_PP_UP);
#endif
} }
static bool isTimerPeriodTooLarge(uint32_t timerPeriod) static bool isTimerPeriodTooLarge(uint32_t timerPeriod)
@ -164,11 +164,6 @@ static void serialTimerRxConfig(const timerHardware_t *timerHardwarePtr, uint8_t
timerChConfigCallbacks(timerHardwarePtr, &softSerialPorts[reference].edgeCb, NULL); timerChConfigCallbacks(timerHardwarePtr, &softSerialPorts[reference].edgeCb, NULL);
} }
static void serialOutputPortConfig(ioTag_t pin)
{
softSerialGPIOConfig(pin, IOCFG_OUT_PP);
}
static void resetBuffers(softSerial_t *softSerial) static void resetBuffers(softSerial_t *softSerial)
{ {
softSerial->port.rxBufferSize = SOFTSERIAL_BUFFER_SIZE; softSerial->port.rxBufferSize = SOFTSERIAL_BUFFER_SIZE;
@ -219,10 +214,10 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
softSerial->softSerialPortIndex = portIndex; softSerial->softSerialPortIndex = portIndex;
softSerial->txIO = IOGetByTag(softSerial->txTimerHardware->tag); softSerial->txIO = IOGetByTag(softSerial->txTimerHardware->tag);
serialOutputPortConfig(softSerial->txTimerHardware->tag); serialOutputPortConfig(softSerial->txTimerHardware->tag, portIndex);
softSerial->rxIO = IOGetByTag(softSerial->rxTimerHardware->tag); softSerial->rxIO = IOGetByTag(softSerial->rxTimerHardware->tag);
serialInputPortConfig(softSerial->rxTimerHardware->tag); serialInputPortConfig(softSerial->rxTimerHardware->tag, portIndex);
setTxSignal(softSerial, ENABLE); setTxSignal(softSerial, ENABLE);
delay(50); delay(50);
@ -271,8 +266,6 @@ void processTxState(softSerial_t *softSerial)
softSerial->isTransmittingData = false; softSerial->isTransmittingData = false;
} }
enum { enum {
TRAILING, TRAILING,
LEADING LEADING
@ -408,7 +401,7 @@ void onSerialRxPinChange(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
} }
} }
uint8_t softSerialRxBytesWaiting(serialPort_t *instance) uint32_t softSerialRxBytesWaiting(serialPort_t *instance)
{ {
if ((instance->mode & MODE_RX) == 0) { if ((instance->mode & MODE_RX) == 0) {
return 0; return 0;

View file

@ -28,7 +28,7 @@ serialPort_t *openSoftSerial(softSerialPortIndex_e portIndex, serialReceiveCallb
// serialPort API // serialPort API
void softSerialWriteByte(serialPort_t *instance, uint8_t ch); void softSerialWriteByte(serialPort_t *instance, uint8_t ch);
uint8_t softSerialRxBytesWaiting(serialPort_t *instance); uint32_t softSerialRxBytesWaiting(serialPort_t *instance);
uint8_t softSerialTxBytesFree(serialPort_t *instance); uint8_t softSerialTxBytesFree(serialPort_t *instance);
uint8_t softSerialReadByte(serialPort_t *instance); uint8_t softSerialReadByte(serialPort_t *instance);
void softSerialSetBaudRate(serialPort_t *s, uint32_t baudRate); void softSerialSetBaudRate(serialPort_t *s, uint32_t baudRate);

View file

@ -22,7 +22,6 @@
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
@ -99,26 +98,26 @@ serialPort_t *uartOpen(USART_TypeDef *USARTx, serialReceiveCallbackPtr callback,
uartPort_t *s = NULL; uartPort_t *s = NULL;
if (USARTx == USART1) { if (USARTx == USART1) {
s = serialUSART1(baudRate, mode, options); s = serialUART1(baudRate, mode, options);
#ifdef USE_USART2 #ifdef USE_UART2
} else if (USARTx == USART2) { } else if (USARTx == USART2) {
s = serialUSART2(baudRate, mode, options); s = serialUART2(baudRate, mode, options);
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
} else if (USARTx == USART3) { } else if (USARTx == USART3) {
s = serialUSART3(baudRate, mode, options); s = serialUART3(baudRate, mode, options);
#endif #endif
#ifdef USE_USART4 #ifdef USE_UART4
} else if (USARTx == UART4) { } else if (USARTx == UART4) {
s = serialUSART4(baudRate, mode, options); s = serialUART4(baudRate, mode, options);
#endif #endif
#ifdef USE_USART5 #ifdef USE_UART5
} else if (USARTx == UART5) { } else if (USARTx == UART5) {
s = serialUSART5(baudRate, mode, options); s = serialUART5(baudRate, mode, options);
#endif #endif
#ifdef USE_USART6 #ifdef USE_UART6
} else if (USARTx == USART6) { } else if (USARTx == USART6) {
s = serialUSART6(baudRate, mode, options); s = serialUART6(baudRate, mode, options);
#endif #endif
} else { } else {

View file

@ -40,13 +40,13 @@ typedef struct {
serialPort_t port; serialPort_t port;
#ifdef STM32F4 #ifdef STM32F4
DMA_Stream_TypeDef *rxDMAStream; DMA_Stream_TypeDef *rxDMAStream;
DMA_Stream_TypeDef *txDMAStream; DMA_Stream_TypeDef *txDMAStream;
uint32_t rxDMAChannel; uint32_t rxDMAChannel;
uint32_t txDMAChannel; uint32_t txDMAChannel;
#else #else
DMA_Channel_TypeDef *rxDMAChannel; DMA_Channel_TypeDef *rxDMAChannel;
DMA_Channel_TypeDef *txDMAChannel; DMA_Channel_TypeDef *txDMAChannel;
#endif #endif
uint32_t rxDMAIrq; uint32_t rxDMAIrq;

View file

@ -23,10 +23,10 @@ extern const struct serialPortVTable uartVTable[];
void uartStartTxDMA(uartPort_t *s); void uartStartTxDMA(uartPort_t *s);
uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t options); uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t options);
uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t options); uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t options);
uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t options); uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t options);
uartPort_t *serialUSART4(uint32_t baudRate, portMode_t mode, portOptions_t options); uartPort_t *serialUART4(uint32_t baudRate, portMode_t mode, portOptions_t options);
uartPort_t *serialUSART5(uint32_t baudRate, portMode_t mode, portOptions_t options); uartPort_t *serialUART5(uint32_t baudRate, portMode_t mode, portOptions_t options);
uartPort_t *serialUSART6(uint32_t baudRate, portMode_t mode, portOptions_t options); uartPort_t *serialUART6(uint32_t baudRate, portMode_t mode, portOptions_t options);

View file

@ -24,38 +24,32 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <platform.h> #include <platform.h>
#include "system.h" #include "system.h"
#include "gpio.h" #include "io.h"
#include "nvic.h" #include "nvic.h"
#include "dma.h"
#include "rcc.h"
#include "serial.h" #include "serial.h"
#include "serial_uart.h" #include "serial_uart.h"
#include "serial_uart_impl.h" #include "serial_uart_impl.h"
#ifdef USE_USART1 #ifdef USE_UART1
static uartPort_t uartPort1; static uartPort_t uartPort1;
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
static uartPort_t uartPort2; static uartPort_t uartPort2;
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
static uartPort_t uartPort3; static uartPort_t uartPort3;
#endif #endif
// Using RX DMA disables the use of receive callbacks void uartIrqCallback(uartPort_t *s)
#define USE_USART1_RX_DMA
#if defined(CC3D) // FIXME move board specific code to target.h files.
#undef USE_USART1_RX_DMA
#endif
void usartIrqCallback(uartPort_t *s)
{ {
uint16_t SR = s->USARTx->SR; uint16_t SR = s->USARTx->SR;
@ -82,15 +76,26 @@ void usartIrqCallback(uartPort_t *s)
} }
} }
#ifdef USE_USART1 // USART1 Tx DMA Handler
void uart_tx_dma_IRQHandler(dmaChannelDescriptor_t* descriptor)
{
uartPort_t *s = (uartPort_t*)(descriptor->userParam);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
DMA_Cmd(descriptor->channel, DISABLE);
if (s->port.txBufferHead != s->port.txBufferTail)
uartStartTxDMA(s);
else
s->txDMAEmpty = true;
}
#ifdef USE_UART1
// USART1 - Telemetry (RX/TX by DMA) // USART1 - Telemetry (RX/TX by DMA)
uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx1Buffer[UART1_RX_BUFFER_SIZE]; static volatile uint8_t rx1Buffer[UART1_RX_BUFFER_SIZE];
static volatile uint8_t tx1Buffer[UART1_TX_BUFFER_SIZE]; static volatile uint8_t tx1Buffer[UART1_TX_BUFFER_SIZE];
gpio_config_t gpio;
NVIC_InitTypeDef NVIC_InitStructure;
s = &uartPort1; s = &uartPort1;
s->port.vTable = uartVTable; s->port.vTable = uartVTable;
@ -105,46 +110,40 @@ uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->USARTx = USART1; s->USARTx = USART1;
#ifdef USE_USART1_RX_DMA #ifdef USE_UART1_RX_DMA
s->rxDMAChannel = DMA1_Channel5; s->rxDMAChannel = DMA1_Channel5;
s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR;
#endif #endif
s->txDMAChannel = DMA1_Channel4; s->txDMAChannel = DMA1_Channel4;
s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_ClockCmd(RCC_APB2(USART1), ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_ClockCmd(RCC_AHB(DMA1), ENABLE);
// USART1_TX PA9 // UART1_TX PA9
// USART1_RX PA10 // UART1_RX PA10
gpio.speed = Speed_2MHz;
gpio.pin = Pin_9;
if (options & SERIAL_BIDIR) { if (options & SERIAL_BIDIR) {
gpio.mode = Mode_AF_OD; IOInit(IOGetByTag(IO_TAG(PA9)), OWNER_SERIAL, RESOURCE_UART_TXRX, 1);
gpioInit(GPIOA, &gpio); IOConfigGPIO(IOGetByTag(IO_TAG(PA9)), IOCFG_AF_OD);
} else { } else {
if (mode & MODE_TX) { if (mode & MODE_TX) {
gpio.mode = Mode_AF_PP; IOInit(IOGetByTag(IO_TAG(PA9)), OWNER_SERIAL, RESOURCE_UART_TX, 1);
gpioInit(GPIOA, &gpio); IOConfigGPIO(IOGetByTag(IO_TAG(PA9)), IOCFG_AF_PP);
} }
if (mode & MODE_RX) { if (mode & MODE_RX) {
gpio.pin = Pin_10; IOInit(IOGetByTag(IO_TAG(PA10)), OWNER_SERIAL, RESOURCE_UART_RX, 1);
gpio.mode = Mode_IPU; IOConfigGPIO(IOGetByTag(IO_TAG(PA10)), IOCFG_IPU);
gpioInit(GPIOA, &gpio);
} }
} }
// DMA TX Interrupt // DMA TX Interrupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; dmaSetHandler(DMA1_CH4_HANDLER, uart_tx_dma_IRQHandler, NVIC_PRIO_SERIALUART1_TXDMA, (uint32_t)&uartPort1);
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#ifndef USE_USART1_RX_DMA #ifndef USE_UART1_RX_DMA
// RX/TX Interrupt // RX/TX Interrupt
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1);
@ -155,37 +154,23 @@ uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t optio
return s; return s;
} }
// USART1 Tx DMA Handler
void DMA1_Channel4_IRQHandler(void)
{
uartPort_t *s = &uartPort1;
DMA_ClearITPendingBit(DMA1_IT_TC4);
DMA_Cmd(s->txDMAChannel, DISABLE);
if (s->port.txBufferHead != s->port.txBufferTail)
uartStartTxDMA(s);
else
s->txDMAEmpty = true;
}
// USART1 Rx/Tx IRQ Handler // USART1 Rx/Tx IRQ Handler
void USART1_IRQHandler(void) void USART1_IRQHandler(void)
{ {
uartPort_t *s = &uartPort1; uartPort_t *s = &uartPort1;
usartIrqCallback(s); uartIrqCallback(s);
} }
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
// USART2 - GPS or Spektrum or ?? (RX + TX by IRQ) // USART2 - GPS or Spektrum or ?? (RX + TX by IRQ)
uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx2Buffer[UART2_RX_BUFFER_SIZE]; static volatile uint8_t rx2Buffer[UART2_RX_BUFFER_SIZE];
static volatile uint8_t tx2Buffer[UART2_TX_BUFFER_SIZE]; static volatile uint8_t tx2Buffer[UART2_TX_BUFFER_SIZE];
gpio_config_t gpio;
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
s = &uartPort2; s = &uartPort2;
@ -203,27 +188,23 @@ uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR;
s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_ClockCmd(RCC_APB1(USART2), ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_ClockCmd(RCC_AHB(DMA1), ENABLE);
// USART2_TX PA2 // UART2_TX PA2
// USART2_RX PA3 // UART2_RX PA3
gpio.speed = Speed_2MHz;
gpio.pin = Pin_2;
if (options & SERIAL_BIDIR) { if (options & SERIAL_BIDIR) {
gpio.mode = Mode_AF_OD; IOInit(IOGetByTag(IO_TAG(PA2)), OWNER_SERIAL, RESOURCE_UART_TXRX, 2);
gpioInit(GPIOA, &gpio); IOConfigGPIO(IOGetByTag(IO_TAG(PA2)), IOCFG_AF_OD);
} else { } else {
if (mode & MODE_TX) { if (mode & MODE_TX) {
gpio.mode = Mode_AF_PP; IOInit(IOGetByTag(IO_TAG(PA2)), OWNER_SERIAL, RESOURCE_UART_TX, 2);
gpioInit(GPIOA, &gpio); IOConfigGPIO(IOGetByTag(IO_TAG(PA2)), IOCFG_AF_PP);
} }
if (mode & MODE_RX) { if (mode & MODE_RX) {
gpio.pin = Pin_3; IOInit(IOGetByTag(IO_TAG(PA3)), OWNER_SERIAL, RESOURCE_UART_RX, 2);
gpio.mode = Mode_IPU; IOConfigGPIO(IOGetByTag(IO_TAG(PA3)), IOCFG_IPU);
gpioInit(GPIOA, &gpio);
} }
} }
@ -242,19 +223,19 @@ uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t optio
void USART2_IRQHandler(void) void USART2_IRQHandler(void)
{ {
uartPort_t *s = &uartPort2; uartPort_t *s = &uartPort2;
usartIrqCallback(s); uartIrqCallback(s);
} }
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
// USART3 // USART3
uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx3Buffer[UART3_RX_BUFFER_SIZE]; static volatile uint8_t rx3Buffer[UART3_RX_BUFFER_SIZE];
static volatile uint8_t tx3Buffer[UART3_TX_BUFFER_SIZE]; static volatile uint8_t tx3Buffer[UART3_TX_BUFFER_SIZE];
gpio_config_t gpio;
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
s = &uartPort3; s = &uartPort3;
@ -272,29 +253,20 @@ uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR;
s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR; s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->DR;
#ifdef USART3_APB1_PERIPHERALS RCC_ClockCmd(RCC_APB1(USART3), ENABLE);
RCC_APB1PeriphClockCmd(USART3_APB1_PERIPHERALS, ENABLE);
#endif
#ifdef USART3_APB2_PERIPHERALS
RCC_APB2PeriphClockCmd(USART3_APB2_PERIPHERALS, ENABLE);
#endif
gpio.speed = Speed_2MHz;
gpio.pin = USART3_TX_PIN;
if (options & SERIAL_BIDIR) { if (options & SERIAL_BIDIR) {
gpio.mode = Mode_AF_OD; IOInit(IOGetByTag(IO_TAG(UART3_TX_PIN)), OWNER_SERIAL, RESOURCE_UART_TXRX, 3);
gpioInit(USART3_GPIO, &gpio); IOConfigGPIO(IOGetByTag(IO_TAG(UART3_TX_PIN)), IOCFG_AF_OD);
} else { } else {
if (mode & MODE_TX) { if (mode & MODE_TX) {
gpio.mode = Mode_AF_PP; IOInit(IOGetByTag(IO_TAG(UART3_TX_PIN)), OWNER_SERIAL, RESOURCE_UART_TX, 3);
gpioInit(USART3_GPIO, &gpio); IOConfigGPIO(IOGetByTag(IO_TAG(UART3_TX_PIN)), IOCFG_AF_PP);
} }
if (mode & MODE_RX) { if (mode & MODE_RX) {
gpio.pin = USART3_RX_PIN; IOInit(IOGetByTag(IO_TAG(UART3_RX_PIN)), OWNER_SERIAL, RESOURCE_UART_RX, 3);
gpio.mode = Mode_IPU; IOConfigGPIO(IOGetByTag(IO_TAG(UART3_RX_PIN)), IOCFG_IPU);
gpioInit(USART3_GPIO, &gpio);
} }
} }
@ -312,6 +284,6 @@ uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t optio
void USART3_IRQHandler(void) void USART3_IRQHandler(void)
{ {
uartPort_t *s = &uartPort3; uartPort_t *s = &uartPort3;
usartIrqCallback(s); uartIrqCallback(s);
} }
#endif #endif

View file

@ -25,94 +25,125 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <platform.h> #include <platform.h>
#include "system.h" #include "system.h"
#include "gpio.h" #include "io.h"
#include "nvic.h" #include "nvic.h"
#include "dma.h"
#include "rcc.h"
#include "serial.h" #include "serial.h"
#include "serial_uart.h" #include "serial_uart.h"
#include "serial_uart_impl.h" #include "serial_uart_impl.h"
// Using RX DMA disables the use of receive callbacks #ifdef USE_UART1
//#define USE_USART1_RX_DMA #ifndef UART1_TX_PIN
//#define USE_USART2_RX_DMA #define UART1_TX_PIN PA9 // PA9
//#define USE_USART2_TX_DMA #endif
//#define USE_USART3_RX_DMA #ifndef UART1_RX_PIN
//#define USE_USART3_TX_DMA #define UART1_RX_PIN PA10 // PA10
#endif
#ifndef UART1_GPIO
#define UART1_TX_PIN GPIO_Pin_9 // PA9
#define UART1_RX_PIN GPIO_Pin_10 // PA10
#define UART1_GPIO GPIOA
#define UART1_GPIO_AF GPIO_AF_7
#define UART1_TX_PINSOURCE GPIO_PinSource9
#define UART1_RX_PINSOURCE GPIO_PinSource10
#endif #endif
#ifndef UART2_GPIO #ifdef USE_UART2
#define UART2_TX_PIN GPIO_Pin_5 // PD5 #ifndef UART2_TX_PIN
#define UART2_RX_PIN GPIO_Pin_6 // PD6 #define UART2_TX_PIN PD5 // PD5
#define UART2_GPIO GPIOD #endif
#define UART2_GPIO_AF GPIO_AF_7 #ifndef UART2_RX_PIN
#define UART2_TX_PINSOURCE GPIO_PinSource5 #define UART2_RX_PIN PD6 // PD6
#define UART2_RX_PINSOURCE GPIO_PinSource6 #endif
#endif #endif
#ifndef UART3_GPIO #ifdef USE_UART3
#define UART3_TX_PIN GPIO_Pin_10 // PB10 (AF7) #ifndef UART3_TX_PIN
#define UART3_RX_PIN GPIO_Pin_11 // PB11 (AF7) #define UART3_TX_PIN PB10 // PB10 (AF7)
#define UART3_GPIO_AF GPIO_AF_7 #endif
#define UART3_GPIO GPIOB #ifndef UART3_RX_PIN
#define UART3_TX_PINSOURCE GPIO_PinSource10 #define UART3_RX_PIN PB11 // PB11 (AF7)
#define UART3_RX_PINSOURCE GPIO_PinSource11 #endif
#endif #endif
#ifndef UART4_GPIO #ifdef USE_UART4
#define UART4_TX_PIN GPIO_Pin_10 // PC10 (AF5) #ifndef UART4_TX_PIN
#define UART4_RX_PIN GPIO_Pin_11 // PC11 (AF5) #define UART4_TX_PIN PC10 // PC10 (AF5)
#define UART4_GPIO_AF GPIO_AF_5 #endif
#define UART4_GPIO GPIOC #ifndef UART4_RX_PIN
#define UART4_TX_PINSOURCE GPIO_PinSource10 #define UART4_RX_PIN PC11 // PC11 (AF5)
#define UART4_RX_PINSOURCE GPIO_PinSource11 #endif
#endif #endif
#ifndef UART5_GPIO // The real UART5_RX is on PD2, no board is using. #ifdef USE_UART5
#define UART5_TX_PIN GPIO_Pin_12 // PC12 (AF5) #ifndef UART5_TX_PIN // The real UART5_RX is on PD2, no board is using.
#define UART5_RX_PIN GPIO_Pin_12 // PC12 (AF5) #define UART5_TX_PIN PC12 // PC12 (AF5)
#define UART5_GPIO_AF GPIO_AF_5 #endif
#define UART5_GPIO GPIOC #ifndef UART5_RX_PIN
#define UART5_TX_PINSOURCE GPIO_PinSource12 #define UART5_RX_PIN PC12 // PC12 (AF5)
#define UART5_RX_PINSOURCE GPIO_PinSource12 #endif
#endif #endif
#ifdef USE_USART1 #ifdef USE_UART1
static uartPort_t uartPort1; static uartPort_t uartPort1;
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
static uartPort_t uartPort2; static uartPort_t uartPort2;
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
static uartPort_t uartPort3; static uartPort_t uartPort3;
#endif #endif
#ifdef USE_USART4 #ifdef USE_UART4
static uartPort_t uartPort4; static uartPort_t uartPort4;
#endif #endif
#ifdef USE_USART5 #ifdef USE_UART5
static uartPort_t uartPort5; static uartPort_t uartPort5;
#endif #endif
#ifdef USE_USART1 static void handleUsartTxDma(dmaChannelDescriptor_t* descriptor)
uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t options) {
uartPort_t *s = (uartPort_t*)(descriptor->userParam);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
DMA_Cmd(descriptor->channel, DISABLE);
if (s->port.txBufferHead != s->port.txBufferTail)
uartStartTxDMA(s);
else
s->txDMAEmpty = true;
}
void serialUARTInit(IO_t tx, IO_t rx, portMode_t mode, portOptions_t options, uint8_t af, uint8_t index)
{
if (options & SERIAL_BIDIR) {
ioConfig_t ioCfg = IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz,
(options & SERIAL_INVERTED) ? GPIO_OType_PP : GPIO_OType_OD,
(options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP
);
IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TXRX, index);
IOConfigGPIOAF(tx, ioCfg, af);
if (!(options & SERIAL_INVERTED))
IOLo(tx); // OpenDrain output should be inactive
} else {
ioConfig_t ioCfg = IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP);
if (mode & MODE_TX) {
IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TX, index);
IOConfigGPIOAF(tx, ioCfg, af);
}
if (mode & MODE_RX) {
IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TX, index);
IOConfigGPIOAF(rx, ioCfg, af);
}
}
}
#ifdef USE_UART1
uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx1Buffer[UART1_RX_BUFFER_SIZE]; static volatile uint8_t rx1Buffer[UART1_RX_BUFFER_SIZE];
static volatile uint8_t tx1Buffer[UART1_TX_BUFFER_SIZE]; static volatile uint8_t tx1Buffer[UART1_TX_BUFFER_SIZE];
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
s = &uartPort1; s = &uartPort1;
s->port.vTable = uartVTable; s->port.vTable = uartVTable;
@ -124,7 +155,7 @@ uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->port.rxBufferSize = UART1_RX_BUFFER_SIZE; s->port.rxBufferSize = UART1_RX_BUFFER_SIZE;
s->port.txBufferSize = UART1_TX_BUFFER_SIZE; s->port.txBufferSize = UART1_TX_BUFFER_SIZE;
#ifdef USE_USART1_RX_DMA #ifdef USE_UART1_RX_DMA
s->rxDMAChannel = DMA1_Channel5; s->rxDMAChannel = DMA1_Channel5;
#endif #endif
s->txDMAChannel = DMA1_Channel4; s->txDMAChannel = DMA1_Channel4;
@ -134,43 +165,16 @@ uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->RDR; s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->RDR;
s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->TDR; s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->TDR;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_ClockCmd(RCC_APB2(USART1), ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_ClockCmd(RCC_AHB(DMA1), ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; serialUARTInit(IOGetByTag(IO_TAG(UART1_TX_PIN)), IOGetByTag(IO_TAG(UART1_RX_PIN)), mode, options, GPIO_AF_7, 1);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP;
if (options & SERIAL_BIDIR) { dmaSetHandler(DMA1_CH4_HANDLER, handleUsartTxDma, NVIC_PRIO_SERIALUART1_TXDMA, (uint32_t)&uartPort1);
GPIO_InitStructure.GPIO_Pin = UART1_TX_PIN;
GPIO_InitStructure.GPIO_OType = (options & SERIAL_INVERTED) ? GPIO_OType_PP : GPIO_OType_OD;
GPIO_PinAFConfig(UART1_GPIO, UART1_TX_PINSOURCE, UART1_GPIO_AF);
GPIO_Init(UART1_GPIO, &GPIO_InitStructure);
if(!(options & SERIAL_INVERTED))
GPIO_SetBits(UART1_GPIO, UART1_TX_PIN); // OpenDrain output should be inactive
} else {
if (mode & MODE_TX) {
GPIO_InitStructure.GPIO_Pin = UART1_TX_PIN;
GPIO_PinAFConfig(UART1_GPIO, UART1_TX_PINSOURCE, UART1_GPIO_AF);
GPIO_Init(UART1_GPIO, &GPIO_InitStructure);
}
if (mode & MODE_RX) { #ifndef USE_UART1_RX_DMA
GPIO_InitStructure.GPIO_Pin = UART1_RX_PIN; NVIC_InitTypeDef NVIC_InitStructure;
GPIO_PinAFConfig(UART1_GPIO, UART1_RX_PINSOURCE, UART1_GPIO_AF);
GPIO_Init(UART1_GPIO, &GPIO_InitStructure);
}
}
// DMA TX Interrupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#ifndef USE_USART1_RX_DMA
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_RXDMA); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART1_RXDMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_RXDMA); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART1_RXDMA);
@ -182,14 +186,12 @@ uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t optio
} }
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx2Buffer[UART2_RX_BUFFER_SIZE]; static volatile uint8_t rx2Buffer[UART2_RX_BUFFER_SIZE];
static volatile uint8_t tx2Buffer[UART2_TX_BUFFER_SIZE]; static volatile uint8_t tx2Buffer[UART2_TX_BUFFER_SIZE];
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
s = &uartPort2; s = &uartPort2;
s->port.vTable = uartVTable; s->port.vTable = uartVTable;
@ -203,57 +205,31 @@ uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->USARTx = USART2; s->USARTx = USART2;
#ifdef USE_USART2_RX_DMA #ifdef USE_UART2_RX_DMA
s->rxDMAChannel = DMA1_Channel6; s->rxDMAChannel = DMA1_Channel6;
s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->RDR; s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->RDR;
#endif #endif
#ifdef USE_USART2_TX_DMA #ifdef USE_UART2_TX_DMA
s->txDMAChannel = DMA1_Channel7; s->txDMAChannel = DMA1_Channel7;
s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->TDR; s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->TDR;
#endif #endif
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_ClockCmd(RCC_APB1(USART2), ENABLE);
#if defined(USE_USART2_TX_DMA) || defined(USE_USART2_RX_DMA) #if defined(USE_UART2_TX_DMA) || defined(USE_UART2_RX_DMA)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_ClockCmd(RCC_AHB(DMA1), ENABLE);
#endif #endif
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; serialUARTInit(IOGetByTag(IO_TAG(UART2_TX_PIN)), IOGetByTag(IO_TAG(UART2_RX_PIN)), mode, options, GPIO_AF_7, 2);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP;
if (options & SERIAL_BIDIR) { #ifdef USE_UART2_TX_DMA
GPIO_InitStructure.GPIO_Pin = UART2_TX_PIN;
GPIO_InitStructure.GPIO_OType = (options & SERIAL_INVERTED) ? GPIO_OType_PP : GPIO_OType_OD;
GPIO_PinAFConfig(UART2_GPIO, UART2_TX_PINSOURCE, UART2_GPIO_AF);
GPIO_Init(UART2_GPIO, &GPIO_InitStructure);
if(!(options & SERIAL_INVERTED))
GPIO_SetBits(UART2_GPIO, UART2_TX_PIN); // OpenDrain output should be inactive
} else {
if (mode & MODE_TX) {
GPIO_InitStructure.GPIO_Pin = UART2_TX_PIN;
GPIO_PinAFConfig(UART2_GPIO, UART2_TX_PINSOURCE, UART2_GPIO_AF);
GPIO_Init(UART2_GPIO, &GPIO_InitStructure);
}
if (mode & MODE_RX) {
GPIO_InitStructure.GPIO_Pin = UART2_RX_PIN;
GPIO_PinAFConfig(UART2_GPIO, UART2_RX_PINSOURCE, UART2_GPIO_AF);
GPIO_Init(UART2_GPIO, &GPIO_InitStructure);
}
}
#ifdef USE_USART2_TX_DMA
// DMA TX Interrupt // DMA TX Interrupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn; dmaSetHandler(DMA1_CH7_HANDLER, handleUsartTxDma, NVIC_PRIO_SERIALUART2_TXDMA, (uint32_t)&uartPort2);
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART2_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART2_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif #endif
#ifndef USE_USART2_RX_DMA #ifndef USE_UART2_RX_DMA
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART2_RXDMA); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART2_RXDMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART2_RXDMA); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART2_RXDMA);
@ -265,14 +241,12 @@ uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t optio
} }
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx3Buffer[UART3_RX_BUFFER_SIZE]; static volatile uint8_t rx3Buffer[UART3_RX_BUFFER_SIZE];
static volatile uint8_t tx3Buffer[UART3_TX_BUFFER_SIZE]; static volatile uint8_t tx3Buffer[UART3_TX_BUFFER_SIZE];
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
s = &uartPort3; s = &uartPort3;
s->port.vTable = uartVTable; s->port.vTable = uartVTable;
@ -286,57 +260,31 @@ uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->USARTx = USART3; s->USARTx = USART3;
#ifdef USE_USART3_RX_DMA #ifdef USE_UART3_RX_DMA
s->rxDMAChannel = DMA1_Channel3; s->rxDMAChannel = DMA1_Channel3;
s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->RDR; s->rxDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->RDR;
#endif #endif
#ifdef USE_USART3_TX_DMA #ifdef USE_UART3_TX_DMA
s->txDMAChannel = DMA1_Channel2; s->txDMAChannel = DMA1_Channel2;
s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->TDR; s->txDMAPeripheralBaseAddr = (uint32_t)&s->USARTx->TDR;
#endif #endif
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); RCC_ClockCmd(RCC_APB1(USART3), ENABLE);
#if defined(USE_USART3_TX_DMA) || defined(USE_USART3_RX_DMA) #if defined(USE_UART3_TX_DMA) || defined(USE_UART3_RX_DMA)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_AHBClockCmd(RCC_AHB(DMA1), ENABLE);
#endif #endif
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; serialUARTInit(IOGetByTag(IO_TAG(UART3_TX_PIN)), IOGetByTag(IO_TAG(UART3_RX_PIN)), mode, options, GPIO_AF_7, 3);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP;
if (options & SERIAL_BIDIR) { #ifdef USE_UART3_TX_DMA
GPIO_InitStructure.GPIO_Pin = UART3_TX_PIN;
GPIO_InitStructure.GPIO_OType = (options & SERIAL_INVERTED) ? GPIO_OType_PP : GPIO_OType_OD;
GPIO_PinAFConfig(UART3_GPIO, UART3_TX_PINSOURCE, UART3_GPIO_AF);
GPIO_Init(UART3_GPIO, &GPIO_InitStructure);
if(!(options & SERIAL_INVERTED))
GPIO_SetBits(UART3_GPIO, UART3_TX_PIN); // OpenDrain output should be inactive
} else {
if (mode & MODE_TX) {
GPIO_InitStructure.GPIO_Pin = UART3_TX_PIN;
GPIO_PinAFConfig(UART3_GPIO, UART3_TX_PINSOURCE, UART3_GPIO_AF);
GPIO_Init(UART3_GPIO, &GPIO_InitStructure);
}
if (mode & MODE_RX) {
GPIO_InitStructure.GPIO_Pin = UART3_RX_PIN;
GPIO_PinAFConfig(UART3_GPIO, UART3_RX_PINSOURCE, UART3_GPIO_AF);
GPIO_Init(UART3_GPIO, &GPIO_InitStructure);
}
}
#ifdef USE_USART3_TX_DMA
// DMA TX Interrupt // DMA TX Interrupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn; dmaSetHandler(DMA1_CH2_HANDLER, handleUsartTxDma, NVIC_PRIO_SERIALUART3_TXDMA, (uint32_t)&uartPort3);
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART3_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART3_TXDMA);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif #endif
#ifndef USE_USART3_RX_DMA #ifndef USE_UART3_RX_DMA
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART3_RXDMA); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART3_RXDMA);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART3_RXDMA); NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_SERIALUART3_RXDMA);
@ -348,14 +296,13 @@ uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t optio
} }
#endif #endif
#ifdef USE_USART4 #ifdef USE_UART4
uartPort_t *serialUSART4(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART4(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx4Buffer[UART4_RX_BUFFER_SIZE]; static volatile uint8_t rx4Buffer[UART4_RX_BUFFER_SIZE];
static volatile uint8_t tx4Buffer[UART4_TX_BUFFER_SIZE]; static volatile uint8_t tx4Buffer[UART4_TX_BUFFER_SIZE];
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
s = &uartPort4; s = &uartPort4;
s->port.vTable = uartVTable; s->port.vTable = uartVTable;
@ -369,33 +316,9 @@ uartPort_t *serialUSART4(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->USARTx = UART4; s->USARTx = UART4;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); RCC_ClockCmd(RCC_APB1(UART4), ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; serialUARTInit(IOGetByTag(IO_TAG(UART4_TX_PIN)), IOGetByTag(IO_TAG(UART4_RX_PIN)), mode, options, GPIO_AF_5, 4);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP;
if (options & SERIAL_BIDIR) {
GPIO_InitStructure.GPIO_Pin = UART4_TX_PIN;
GPIO_InitStructure.GPIO_OType = (options & SERIAL_INVERTED) ? GPIO_OType_PP : GPIO_OType_OD;
GPIO_PinAFConfig(UART4_GPIO, UART4_TX_PINSOURCE, UART4_GPIO_AF);
GPIO_Init(UART4_GPIO, &GPIO_InitStructure);
if(!(options & SERIAL_INVERTED))
GPIO_SetBits(UART4_GPIO, UART4_TX_PIN); // OpenDrain output should be inactive
} else {
if (mode & MODE_TX) {
GPIO_InitStructure.GPIO_Pin = UART4_TX_PIN;
GPIO_PinAFConfig(UART4_GPIO, UART4_TX_PINSOURCE, UART4_GPIO_AF);
GPIO_Init(UART4_GPIO, &GPIO_InitStructure);
}
if (mode & MODE_RX) {
GPIO_InitStructure.GPIO_Pin = UART4_RX_PIN;
GPIO_PinAFConfig(UART4_GPIO, UART4_RX_PINSOURCE, UART4_GPIO_AF);
GPIO_Init(UART4_GPIO, &GPIO_InitStructure);
}
}
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART4); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART4);
@ -407,14 +330,13 @@ uartPort_t *serialUSART4(uint32_t baudRate, portMode_t mode, portOptions_t optio
} }
#endif #endif
#ifdef USE_USART5 #ifdef USE_UART5
uartPort_t *serialUSART5(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART5(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
static volatile uint8_t rx5Buffer[UART5_RX_BUFFER_SIZE]; static volatile uint8_t rx5Buffer[UART5_RX_BUFFER_SIZE];
static volatile uint8_t tx5Buffer[UART5_TX_BUFFER_SIZE]; static volatile uint8_t tx5Buffer[UART5_TX_BUFFER_SIZE];
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
s = &uartPort5; s = &uartPort5;
s->port.vTable = uartVTable; s->port.vTable = uartVTable;
@ -428,33 +350,9 @@ uartPort_t *serialUSART5(uint32_t baudRate, portMode_t mode, portOptions_t optio
s->USARTx = UART5; s->USARTx = UART5;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); RCC_ClockCmd(RCC_APB1(UART5), ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; serialUARTInit(IOGetByTag(IO_TAG(UART5_TX_PIN)), IOGetByTag(IO_TAG(UART5_RX_PIN)), mode, options, GPIO_AF_5, 5);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = (options & SERIAL_INVERTED) ? GPIO_PuPd_DOWN : GPIO_PuPd_UP;
if (options & SERIAL_BIDIR) {
GPIO_InitStructure.GPIO_Pin = UART5_TX_PIN;
GPIO_InitStructure.GPIO_OType = (options & SERIAL_INVERTED) ? GPIO_OType_PP : GPIO_OType_OD;
GPIO_PinAFConfig(UART5_GPIO, UART5_TX_PINSOURCE, UART5_GPIO_AF);
GPIO_Init(UART5_GPIO, &GPIO_InitStructure);
if(!(options & SERIAL_INVERTED))
GPIO_SetBits(UART5_GPIO, UART5_TX_PIN); // OpenDrain output should be inactive
} else {
if (mode & MODE_TX) {
GPIO_InitStructure.GPIO_Pin = UART5_TX_PIN;
GPIO_PinAFConfig(UART5_GPIO, UART5_TX_PINSOURCE, UART5_GPIO_AF);
GPIO_Init(UART5_GPIO, &GPIO_InitStructure);
}
if (mode & MODE_RX) {
GPIO_InitStructure.GPIO_Pin = UART5_RX_PIN;
GPIO_PinAFConfig(UART5_GPIO, UART5_RX_PINSOURCE, UART5_GPIO_AF);
GPIO_Init(UART5_GPIO, &GPIO_InitStructure);
}
}
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART5); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_SERIALUART5);
@ -466,48 +364,6 @@ uartPort_t *serialUSART5(uint32_t baudRate, portMode_t mode, portOptions_t optio
} }
#endif #endif
static void handleUsartTxDma(uartPort_t *s)
{
DMA_Cmd(s->txDMAChannel, DISABLE);
if (s->port.txBufferHead != s->port.txBufferTail)
uartStartTxDMA(s);
else
s->txDMAEmpty = true;
}
// USART1 Tx DMA Handler
void DMA1_Channel4_IRQHandler(void)
{
uartPort_t *s = &uartPort1;
DMA_ClearITPendingBit(DMA1_IT_TC4);
DMA_Cmd(DMA1_Channel4, DISABLE);
handleUsartTxDma(s);
}
#ifdef USE_USART2_TX_DMA
// USART2 Tx DMA Handler
void DMA1_Channel7_IRQHandler(void)
{
uartPort_t *s = &uartPort2;
DMA_ClearITPendingBit(DMA1_IT_TC7);
DMA_Cmd(DMA1_Channel7, DISABLE);
handleUsartTxDma(s);
}
#endif
// USART3 Tx DMA Handler
#ifdef USE_USART3_TX_DMA
void DMA1_Channel2_IRQHandler(void)
{
uartPort_t *s = &uartPort3;
DMA_ClearITPendingBit(DMA1_IT_TC2);
DMA_Cmd(DMA1_Channel2, DISABLE);
handleUsartTxDma(s);
}
#endif
void usartIrqHandler(uartPort_t *s) void usartIrqHandler(uartPort_t *s)
{ {
uint32_t ISR = s->USARTx->ISR; uint32_t ISR = s->USARTx->ISR;
@ -540,7 +396,7 @@ void usartIrqHandler(uartPort_t *s)
} }
} }
#ifdef USE_USART1 #ifdef USE_UART1
void USART1_IRQHandler(void) void USART1_IRQHandler(void)
{ {
uartPort_t *s = &uartPort1; uartPort_t *s = &uartPort1;
@ -549,7 +405,7 @@ void USART1_IRQHandler(void)
} }
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
void USART2_IRQHandler(void) void USART2_IRQHandler(void)
{ {
uartPort_t *s = &uartPort2; uartPort_t *s = &uartPort2;
@ -558,7 +414,7 @@ void USART2_IRQHandler(void)
} }
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
void USART3_IRQHandler(void) void USART3_IRQHandler(void)
{ {
uartPort_t *s = &uartPort3; uartPort_t *s = &uartPort3;
@ -567,7 +423,7 @@ void USART3_IRQHandler(void)
} }
#endif #endif
#ifdef USE_USART4 #ifdef USE_UART4
void UART4_IRQHandler(void) void UART4_IRQHandler(void)
{ {
uartPort_t *s = &uartPort4; uartPort_t *s = &uartPort4;
@ -576,7 +432,7 @@ void UART4_IRQHandler(void)
} }
#endif #endif
#ifdef USE_USART5 #ifdef USE_UART5
void UART5_IRQHandler(void) void UART5_IRQHandler(void)
{ {
uartPort_t *s = &uartPort5; uartPort_t *s = &uartPort5;

View file

@ -17,7 +17,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
@ -25,19 +24,12 @@
#include "io.h" #include "io.h"
#include "rcc.h" #include "rcc.h"
#include "nvic.h" #include "nvic.h"
#include "dma.h"
#include "serial.h" #include "serial.h"
#include "serial_uart.h" #include "serial_uart.h"
#include "serial_uart_impl.h" #include "serial_uart_impl.h"
// Using RX DMA disables the use of receive callbacks
//#define USE_USART1_RX_DMA
//#define USE_USART2_RX_DMA
//#define USE_USART3_RX_DMA
//#define USE_USART4_RX_DMA
//#define USE_USART5_RX_DMA
//#define USE_USART6_RX_DMA
#define UART_RX_BUFFER_SIZE UART1_RX_BUFFER_SIZE #define UART_RX_BUFFER_SIZE UART1_RX_BUFFER_SIZE
#define UART_TX_BUFFER_SIZE UART1_TX_BUFFER_SIZE #define UART_TX_BUFFER_SIZE UART1_TX_BUFFER_SIZE
@ -71,138 +63,138 @@ typedef struct uartDevice_s {
} uartDevice_t; } uartDevice_t;
//static uartPort_t uartPort[MAX_UARTS]; //static uartPort_t uartPort[MAX_UARTS];
#ifdef USE_USART1 #ifdef USE_UART1
static uartDevice_t uart1 = static uartDevice_t uart1 =
{ {
.DMAChannel = DMA_Channel_4, .DMAChannel = DMA_Channel_4,
.txDMAStream = DMA2_Stream7, .txDMAStream = DMA2_Stream7,
#ifdef USE_USART1_RX_DMA #ifdef USE_UART1_RX_DMA
.rxDMAStream = DMA2_Stream5, .rxDMAStream = DMA2_Stream5,
#endif #endif
.dev = USART1, .dev = USART1,
.rx = IO_TAG(USART1_RX_PIN), .rx = IO_TAG(UART1_RX_PIN),
.tx = IO_TAG(USART1_TX_PIN), .tx = IO_TAG(UART1_TX_PIN),
.af = GPIO_AF_USART1, .af = GPIO_AF_USART1,
#ifdef USART1_AHB1_PERIPHERALS #ifdef UART1_AHB1_PERIPHERALS
.rcc_ahb1 = USART1_AHB1_PERIPHERALS, .rcc_ahb1 = UART1_AHB1_PERIPHERALS,
#endif #endif
.rcc_apb2 = RCC_APB2(USART1), .rcc_apb2 = RCC_APB2(USART1),
.txIrq = DMA2_Stream7_IRQn, .txIrq = DMA2_ST7_HANDLER,
.rxIrq = USART1_IRQn, .rxIrq = USART1_IRQn,
.txPriority = NVIC_PRIO_SERIALUART1_TXDMA, .txPriority = NVIC_PRIO_SERIALUART1_TXDMA,
.rxPriority = NVIC_PRIO_SERIALUART1 .rxPriority = NVIC_PRIO_SERIALUART1
}; };
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
static uartDevice_t uart2 = static uartDevice_t uart2 =
{ {
.DMAChannel = DMA_Channel_4, .DMAChannel = DMA_Channel_4,
#ifdef USE_USART2_RX_DMA #ifdef USE_UART2_RX_DMA
.rxDMAStream = DMA1_Stream5, .rxDMAStream = DMA1_Stream5,
#endif #endif
.txDMAStream = DMA1_Stream6, .txDMAStream = DMA1_Stream6,
.dev = USART2, .dev = USART2,
.rx = IO_TAG(USART2_RX_PIN), .rx = IO_TAG(UART2_RX_PIN),
.tx = IO_TAG(USART2_TX_PIN), .tx = IO_TAG(UART2_TX_PIN),
.af = GPIO_AF_USART2, .af = GPIO_AF_USART2,
#ifdef USART2_AHB1_PERIPHERALS #ifdef UART2_AHB1_PERIPHERALS
.rcc_ahb1 = USART2_AHB1_PERIPHERALS, .rcc_ahb1 = UART2_AHB1_PERIPHERALS,
#endif #endif
.rcc_apb1 = RCC_APB1(USART2), .rcc_apb1 = RCC_APB1(USART2),
.txIrq = DMA1_Stream6_IRQn, .txIrq = DMA1_ST6_HANDLER,
.rxIrq = USART2_IRQn, .rxIrq = USART2_IRQn,
.txPriority = NVIC_PRIO_SERIALUART2_TXDMA, .txPriority = NVIC_PRIO_SERIALUART2_TXDMA,
.rxPriority = NVIC_PRIO_SERIALUART2 .rxPriority = NVIC_PRIO_SERIALUART2
}; };
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
static uartDevice_t uart3 = static uartDevice_t uart3 =
{ {
.DMAChannel = DMA_Channel_4, .DMAChannel = DMA_Channel_4,
#ifdef USE_USART3_RX_DMA #ifdef USE_UART3_RX_DMA
.rxDMAStream = DMA1_Stream1, .rxDMAStream = DMA1_Stream1,
#endif #endif
.txDMAStream = DMA1_Stream3, .txDMAStream = DMA1_Stream3,
.dev = USART3, .dev = USART3,
.rx = IO_TAG(USART3_RX_PIN), .rx = IO_TAG(UART3_RX_PIN),
.tx = IO_TAG(USART3_TX_PIN), .tx = IO_TAG(UART3_TX_PIN),
.af = GPIO_AF_USART3, .af = GPIO_AF_USART3,
#ifdef USART3_AHB1_PERIPHERALS #ifdef UART3_AHB1_PERIPHERALS
.rcc_ahb1 = USART3_AHB1_PERIPHERALS, .rcc_ahb1 = UART3_AHB1_PERIPHERALS,
#endif #endif
.rcc_apb1 = RCC_APB1(USART3), .rcc_apb1 = RCC_APB1(USART3),
.txIrq = DMA1_Stream3_IRQn, .txIrq = DMA1_ST3_HANDLER,
.rxIrq = USART3_IRQn, .rxIrq = USART3_IRQn,
.txPriority = NVIC_PRIO_SERIALUART3_TXDMA, .txPriority = NVIC_PRIO_SERIALUART3_TXDMA,
.rxPriority = NVIC_PRIO_SERIALUART3 .rxPriority = NVIC_PRIO_SERIALUART3
}; };
#endif #endif
#ifdef USE_USART4 #ifdef USE_UART4
static uartDevice_t uart4 = static uartDevice_t uart4 =
{ {
.DMAChannel = DMA_Channel_4, .DMAChannel = DMA_Channel_4,
#ifdef USE_USART1_RX_DMA #ifdef USE_UART1_RX_DMA
.rxDMAStream = DMA1_Stream2, .rxDMAStream = DMA1_Stream2,
#endif #endif
.txDMAStream = DMA1_Stream4, .txDMAStream = DMA1_Stream4,
.dev = UART4, .dev = UART4,
.rx = IO_TAG(USART4_RX_PIN), .rx = IO_TAG(UART4_RX_PIN),
.tx = IO_TAG(USART4_TX_PIN), .tx = IO_TAG(UART4_TX_PIN),
.af = GPIO_AF_UART4, .af = GPIO_AF_UART4,
#ifdef USART4_AHB1_PERIPHERALS #ifdef UART4_AHB1_PERIPHERALS
.rcc_ahb1 = USART4_AHB1_PERIPHERALS, .rcc_ahb1 = UART4_AHB1_PERIPHERALS,
#endif #endif
.rcc_apb1 = RCC_APB1(UART4), .rcc_apb1 = RCC_APB1(UART4),
.txIrq = DMA1_Stream4_IRQn, .txIrq = DMA1_ST4_HANDLER,
.rxIrq = UART4_IRQn, .rxIrq = UART4_IRQn,
.txPriority = NVIC_PRIO_SERIALUART4_TXDMA, .txPriority = NVIC_PRIO_SERIALUART4_TXDMA,
.rxPriority = NVIC_PRIO_SERIALUART4 .rxPriority = NVIC_PRIO_SERIALUART4
}; };
#endif #endif
#ifdef USE_USART5 #ifdef USE_UART5
static uartDevice_t uart5 = static uartDevice_t uart5 =
{ {
.DMAChannel = DMA_Channel_4, .DMAChannel = DMA_Channel_4,
#ifdef USE_USART1_RX_DMA #ifdef USE_UART1_RX_DMA
.rxDMAStream = DMA1_Stream0, .rxDMAStream = DMA1_Stream0,
#endif #endif
.txDMAStream = DMA2_Stream7, .txDMAStream = DMA2_Stream7,
.dev = UART5, .dev = UART5,
.rx = IO_TAG(USART5_RX_PIN), .rx = IO_TAG(UART5_RX_PIN),
.tx = IO_TAG(USART5_TX_PIN), .tx = IO_TAG(UART5_TX_PIN),
.af = GPIO_AF_UART5, .af = GPIO_AF_UART5,
#ifdef USART5_AHB1_PERIPHERALS #ifdef UART5_AHB1_PERIPHERALS
.rcc_ahb1 = USART5_AHB1_PERIPHERALS, .rcc_ahb1 = UART5_AHB1_PERIPHERALS,
#endif #endif
.rcc_apb1 = RCC_APB1(UART5), .rcc_apb1 = RCC_APB1(UART5),
.txIrq = DMA2_Stream7_IRQn, .txIrq = DMA2_ST7_HANDLER,
.rxIrq = UART5_IRQn, .rxIrq = UART5_IRQn,
.txPriority = NVIC_PRIO_SERIALUART5_TXDMA, .txPriority = NVIC_PRIO_SERIALUART5_TXDMA,
.rxPriority = NVIC_PRIO_SERIALUART5 .rxPriority = NVIC_PRIO_SERIALUART5
}; };
#endif #endif
#ifdef USE_USART6 #ifdef USE_UART6
static uartDevice_t uart6 = static uartDevice_t uart6 =
{ {
.DMAChannel = DMA_Channel_5, .DMAChannel = DMA_Channel_5,
#ifdef USE_USART6_RX_DMA #ifdef USE_UART6_RX_DMA
.rxDMAStream = DMA2_Stream1, .rxDMAStream = DMA2_Stream1,
#endif #endif
.txDMAStream = DMA2_Stream6, .txDMAStream = DMA2_Stream6,
.dev = USART6, .dev = USART6,
.rx = IO_TAG(USART6_RX_PIN), .rx = IO_TAG(UART6_RX_PIN),
.tx = IO_TAG(USART6_TX_PIN), .tx = IO_TAG(UART6_TX_PIN),
.af = GPIO_AF_USART6, .af = GPIO_AF_USART6,
#ifdef USART6_AHB1_PERIPHERALS #ifdef UART6_AHB1_PERIPHERALS
.rcc_ahb1 = USART6_AHB1_PERIPHERALS, .rcc_ahb1 = UART6_AHB1_PERIPHERALS,
#endif #endif
.rcc_apb2 = RCC_APB2(USART6), .rcc_apb2 = RCC_APB2(USART6),
.txIrq = DMA2_Stream6_IRQn, .txIrq = DMA2_ST6_HANDLER,
.rxIrq = USART6_IRQn, .rxIrq = USART6_IRQn,
.txPriority = NVIC_PRIO_SERIALUART6_TXDMA, .txPriority = NVIC_PRIO_SERIALUART6_TXDMA,
.rxPriority = NVIC_PRIO_SERIALUART6 .rxPriority = NVIC_PRIO_SERIALUART6
@ -210,39 +202,39 @@ static uartDevice_t uart6 =
#endif #endif
static uartDevice_t* uartHardwareMap[] = { static uartDevice_t* uartHardwareMap[] = {
#ifdef USE_USART1 #ifdef USE_UART1
&uart1, &uart1,
#else #else
NULL, NULL,
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
&uart2, &uart2,
#else #else
NULL, NULL,
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
&uart3, &uart3,
#else #else
NULL, NULL,
#endif #endif
#ifdef USE_USART4 #ifdef USE_UART4
&uart4, &uart4,
#else #else
NULL, NULL,
#endif #endif
#ifdef USE_USART5 #ifdef USE_UART5
&uart5, &uart5,
#else #else
NULL, NULL,
#endif #endif
#ifdef USE_USART6 #ifdef USE_UART6
&uart6, &uart6,
#else #else
NULL, NULL,
#endif #endif
}; };
void usartIrqHandler(uartPort_t *s) void uartIrqHandler(uartPort_t *s)
{ {
if (!s->rxDMAStream && (USART_GetITStatus(s->USARTx, USART_IT_RXNE) == SET)) { if (!s->rxDMAStream && (USART_GetITStatus(s->USARTx, USART_IT_RXNE) == SET)) {
if (s->port.callback) { if (s->port.callback) {
@ -278,7 +270,30 @@ static void handleUsartTxDma(uartPort_t *s)
s->txDMAEmpty = true; s->txDMAEmpty = true;
} }
uartPort_t *serialUSART(UARTDevice device, uint32_t baudRate, portMode_t mode, portOptions_t options) void dmaIRQHandler(dmaChannelDescriptor_t* descriptor)
{
uartPort_t *s = &(((uartDevice_t*)(descriptor->userParam))->port);
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF))
{
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
DMA_CLEAR_FLAG(descriptor, DMA_IT_HTIF);
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_FEIF))
{
DMA_CLEAR_FLAG(descriptor, DMA_IT_FEIF);
}
handleUsartTxDma(s);
}
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TEIF))
{
DMA_CLEAR_FLAG(descriptor, DMA_IT_TEIF);
}
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_DMEIF))
{
DMA_CLEAR_FLAG(descriptor, DMA_IT_DMEIF);
}
}
uartPort_t *serialUART(UARTDevice device, uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
uartPort_t *s; uartPort_t *s;
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
@ -320,27 +335,23 @@ uartPort_t *serialUSART(UARTDevice device, uint32_t baudRate, portMode_t mode, p
RCC_AHB1PeriphClockCmd(uart->rcc_ahb1, ENABLE); RCC_AHB1PeriphClockCmd(uart->rcc_ahb1, ENABLE);
if (options & SERIAL_BIDIR) { if (options & SERIAL_BIDIR) {
IOInit(tx, OWNER_SERIAL_TX, RESOURCE_USART); IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TXRX, RESOURCE_INDEX(device));
IOConfigGPIOAF(tx, IOCFG_AF_OD, uart->af); IOConfigGPIOAF(tx, IOCFG_AF_OD, uart->af);
} }
else { else {
if (mode & MODE_TX) { if (mode & MODE_TX) {
IOInit(tx, OWNER_SERIAL_TX, RESOURCE_USART); IOInit(tx, OWNER_SERIAL, RESOURCE_UART_TX, RESOURCE_INDEX(device));
IOConfigGPIOAF(tx, IOCFG_AF_PP, uart->af); IOConfigGPIOAF(tx, IOCFG_AF_PP, uart->af);
} }
if (mode & MODE_RX) { if (mode & MODE_RX) {
IOInit(rx, OWNER_SERIAL_RX, RESOURCE_USART); IOInit(rx, OWNER_SERIAL, RESOURCE_UART_RX, RESOURCE_INDEX(device));
IOConfigGPIOAF(rx, IOCFG_AF_PP, uart->af); IOConfigGPIOAF(rx, IOCFG_AF_PP, uart->af);
} }
} }
// DMA TX Interrupt // DMA TX Interrupt
NVIC_InitStructure.NVIC_IRQChannel = uart->txIrq; dmaSetHandler(uart->txIrq, dmaIRQHandler, uart->txPriority, (uint32_t)uart);
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(uart->txPriority);
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(uart->txPriority);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
if (!(s->rxDMAChannel)) { if (!(s->rxDMAChannel)) {
NVIC_InitStructure.NVIC_IRQChannel = uart->rxIrq; NVIC_InitStructure.NVIC_IRQChannel = uart->rxIrq;
@ -353,230 +364,86 @@ uartPort_t *serialUSART(UARTDevice device, uint32_t baudRate, portMode_t mode, p
return s; return s;
} }
#ifdef USE_USART1 #ifdef USE_UART1
uartPort_t *serialUSART1(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART1(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
return serialUSART(UARTDEV_1, baudRate, mode, options); return serialUART(UARTDEV_1, baudRate, mode, options);
}
// USART1 Tx DMA Handler
void DMA2_Stream7_IRQHandler(void)
{
uartPort_t *s = &(uartHardwareMap[UARTDEV_1]->port);
if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF7))
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF7);
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF7);
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF7)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF7);
}
handleUsartTxDma(s);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF7)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF7);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF7)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF7);
}
} }
// USART1 Rx/Tx IRQ Handler // USART1 Rx/Tx IRQ Handler
void USART1_IRQHandler(void) void USART1_IRQHandler(void)
{ {
uartPort_t *s = &(uartHardwareMap[UARTDEV_1]->port); uartPort_t *s = &(uartHardwareMap[UARTDEV_1]->port);
usartIrqHandler(s); uartIrqHandler(s);
} }
#endif #endif
#ifdef USE_USART2 #ifdef USE_UART2
// USART2 - GPS or Spektrum or ?? (RX + TX by IRQ) // USART2 - GPS or Spektrum or ?? (RX + TX by IRQ)
uartPort_t *serialUSART2(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART2(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
return serialUSART(UARTDEV_2, baudRate, mode, options); return serialUART(UARTDEV_2, baudRate, mode, options);
}
// USART2 Tx DMA Handler
void DMA1_Stream6_IRQHandler(void)
{
uartPort_t *s = &(uartHardwareMap[UARTDEV_2]->port);
if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF6))
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF6);
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF6);
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF6)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF6);
}
handleUsartTxDma(s);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF6)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF6);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF6)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF6);
}
} }
void USART2_IRQHandler(void) void USART2_IRQHandler(void)
{ {
uartPort_t *s = &(uartHardwareMap[UARTDEV_2]->port); uartPort_t *s = &(uartHardwareMap[UARTDEV_2]->port);
usartIrqHandler(s); uartIrqHandler(s);
} }
#endif #endif
#ifdef USE_USART3 #ifdef USE_UART3
// USART3 // USART3
uartPort_t *serialUSART3(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART3(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
return serialUSART(UARTDEV_3, baudRate, mode, options); return serialUART(UARTDEV_3, baudRate, mode, options);
}
// USART3 Tx DMA Handler
void DMA1_Stream3_IRQHandler(void)
{
uartPort_t *s = &(uartHardwareMap[UARTDEV_3]->port);
if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF3))
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF3);
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF3);
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF3)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF3);
}
handleUsartTxDma(s);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF3)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF3);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF3)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF3);
}
} }
void USART3_IRQHandler(void) void USART3_IRQHandler(void)
{ {
uartPort_t *s = &(uartHardwareMap[UARTDEV_3]->port); uartPort_t *s = &(uartHardwareMap[UARTDEV_3]->port);
usartIrqHandler(s); uartIrqHandler(s);
} }
#endif #endif
#ifdef USE_USART4 #ifdef USE_UART4
// USART4 // USART4
uartPort_t *serialUSART4(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART4(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
return serialUSART(UARTDEV_4, baudRate, mode, options); return serialUART(UARTDEV_4, baudRate, mode, options);
}
// USART4 Tx DMA Handler
void DMA1_Stream4_IRQHandler(void)
{
uartPort_t *s = &(uartHardwareMap[UARTDEV_4]->port);
if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF4))
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF4);
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF4);
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF4)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF4);
}
handleUsartTxDma(s);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF4)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF4);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF4)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF4);
}
} }
void UART4_IRQHandler(void) void UART4_IRQHandler(void)
{ {
uartPort_t *s = &(uartHardwareMap[UARTDEV_4]->port); uartPort_t *s = &(uartHardwareMap[UARTDEV_4]->port);
usartIrqHandler(s); uartIrqHandler(s);
} }
#endif #endif
#ifdef USE_USART5 #ifdef USE_UART5
// USART5 // USART5
uartPort_t *serialUSART5(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART5(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
return serialUSART(UARTDEV_5, baudRate, mode, options); return serialUART(UARTDEV_5, baudRate, mode, options);
}
// USART5 Tx DMA Handler
void DMA1_Stream7_IRQHandler(void)
{
uartPort_t *s = &(uartHardwareMap[UARTDEV_5]->port);
if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF7))
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF7);
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF7);
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF7)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF7);
}
handleUsartTxDma(s);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF7)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF7);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF7)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF7);
}
} }
void UART5_IRQHandler(void) void UART5_IRQHandler(void)
{ {
uartPort_t *s = &(uartHardwareMap[UARTDEV_5]->port); uartPort_t *s = &(uartHardwareMap[UARTDEV_5]->port);
usartIrqHandler(s); uartIrqHandler(s);
} }
#endif #endif
#ifdef USE_USART6 #ifdef USE_UART6
// USART6 // USART6
uartPort_t *serialUSART6(uint32_t baudRate, portMode_t mode, portOptions_t options) uartPort_t *serialUART6(uint32_t baudRate, portMode_t mode, portOptions_t options)
{ {
return serialUSART(UARTDEV_6, baudRate, mode, options); return serialUART(UARTDEV_6, baudRate, mode, options);
}
// USART6 Tx DMA Handler
void DMA2_Stream6_IRQHandler(void)
{
uartPort_t *s = &(uartHardwareMap[UARTDEV_6]->port);
if(DMA_GetITStatus(s->txDMAStream,DMA_IT_TCIF6))
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TCIF6);
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_HTIF6);
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_FEIF6)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_FEIF6);
}
handleUsartTxDma(s);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_TEIF6)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_TEIF6);
}
if(DMA_GetFlagStatus(s->txDMAStream,DMA_IT_DMEIF6)==SET)
{
DMA_ClearITPendingBit(s->txDMAStream,DMA_IT_DMEIF6);
}
} }
void USART6_IRQHandler(void) void USART6_IRQHandler(void)
{ {
uartPort_t *s = &(uartHardwareMap[UARTDEV_6]->port); uartPort_t *s = &(uartHardwareMap[UARTDEV_6]->port);
usartIrqHandler(s); uartIrqHandler(s);
} }
#endif #endif

View file

@ -16,9 +16,7 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include "platform.h" #include "platform.h"
@ -181,14 +179,14 @@ serialPort_t *usbVcpOpen(void)
vcpPort_t *s; vcpPort_t *s;
#ifdef STM32F4 #ifdef STM32F4
IOInit(IOGetByTag(IO_TAG(PA11)), OWNER_USB, RESOURCE_IO); IOInit(IOGetByTag(IO_TAG(PA11)), OWNER_USB, RESOURCE_INPUT, 0);
IOInit(IOGetByTag(IO_TAG(PA12)), OWNER_USB, RESOURCE_IO); IOInit(IOGetByTag(IO_TAG(PA12)), OWNER_USB, RESOURCE_OUTPUT, 0);
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb); USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb);
#else #else
Set_System(); Set_System();
Set_USBClock(); Set_USBClock();
USB_Interrupts_Config(); USB_Interrupts_Config();
USB_Init(); USB_Init();
#endif #endif
s = &vcpPort; s = &vcpPort;

View file

@ -83,18 +83,18 @@ void hcsr04_init(sonarRange_t *sonarRange)
// trigger pin // trigger pin
triggerIO = IOGetByTag(sonarHardwareHCSR04.triggerTag); triggerIO = IOGetByTag(sonarHardwareHCSR04.triggerTag);
IOInit(triggerIO, OWNER_SONAR, RESOURCE_INPUT); IOInit(triggerIO, OWNER_SONAR, RESOURCE_OUTPUT, 0);
IOConfigGPIO(triggerIO, IOCFG_OUT_PP); IOConfigGPIO(triggerIO, IOCFG_OUT_PP);
// echo pin // echo pin
echoIO = IOGetByTag(sonarHardwareHCSR04.echoTag); echoIO = IOGetByTag(sonarHardwareHCSR04.echoTag);
IOInit(echoIO, OWNER_SONAR, RESOURCE_INPUT); IOInit(echoIO, OWNER_SONAR, RESOURCE_INPUT, 0);
IOConfigGPIO(echoIO, IOCFG_IN_FLOATING); IOConfigGPIO(echoIO, IOCFG_IN_FLOATING);
#ifdef USE_EXTI #ifdef USE_EXTI
EXTIHandlerInit(&hcsr04_extiCallbackRec, hcsr04_extiHandler); EXTIHandlerInit(&hcsr04_extiCallbackRec, hcsr04_extiHandler);
EXTIConfig(echoIO, &hcsr04_extiCallbackRec, NVIC_PRIO_SONAR_EXTI, EXTI_Trigger_Rising_Falling); // TODO - priority! EXTIConfig(echoIO, &hcsr04_extiCallbackRec, NVIC_PRIO_SONAR_EXTI, EXTI_Trigger_Rising_Falling); // TODO - priority!
EXTIEnable(echoIO, true); EXTIEnable(echoIO, true);
#endif #endif
lastMeasurementAt = millis() - 60; // force 1st measurement in hcsr04_get_distance() lastMeasurementAt = millis() - 60; // force 1st measurement in hcsr04_get_distance()

View file

@ -17,12 +17,9 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
#include "common/utils.h"
#include "system.h" #include "system.h"
#include "io.h" #include "io.h"
@ -39,31 +36,31 @@ static bool beeperInverted = false;
void systemBeep(bool onoff) void systemBeep(bool onoff)
{ {
#ifndef BEEPER #ifndef BEEPER
UNUSED(onoff); UNUSED(onoff);
#else #else
IOWrite(beeperIO, beeperInverted ? onoff : !onoff); IOWrite(beeperIO, beeperInverted ? onoff : !onoff);
#endif #endif
} }
void systemBeepToggle(void) void systemBeepToggle(void)
{ {
#ifdef BEEPER #ifdef BEEPER
IOToggle(beeperIO); IOToggle(beeperIO);
#endif #endif
} }
void beeperInit(const beeperConfig_t *config) void beeperInit(const beeperConfig_t *config)
{ {
#ifndef BEEPER #ifndef BEEPER
UNUSED(config); UNUSED(config);
#else #else
beeperIO = IOGetByTag(config->ioTag); beeperIO = IOGetByTag(config->ioTag);
beeperInverted = config->isInverted; beeperInverted = config->isInverted;
if (beeperIO) { if (beeperIO) {
IOInit(beeperIO, OWNER_BEEPER, RESOURCE_OUTPUT); IOInit(beeperIO, OWNER_BEEPER, RESOURCE_OUTPUT, 0);
IOConfigGPIO(beeperIO, config->isOD ? IOCFG_OUT_OD : IOCFG_OUT_PP); IOConfigGPIO(beeperIO, config->isOD ? IOCFG_OUT_OD : IOCFG_OUT_PP);
} }
systemBeep(false); systemBeep(false);
#endif #endif
} }

View file

@ -30,9 +30,9 @@
#endif #endif
typedef struct beeperConfig_s { typedef struct beeperConfig_s {
ioTag_t ioTag; ioTag_t ioTag;
unsigned isInverted : 1; unsigned isInverted : 1;
unsigned isOD : 1; unsigned isOD : 1;
} beeperConfig_t; } beeperConfig_t;
void systemBeep(bool on); void systemBeep(bool on);

View file

@ -15,15 +15,11 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "platform.h" #include "platform.h"
#include "build_config.h"
#include "gpio.h" #include "gpio.h"
#include "light_led.h" #include "light_led.h"
#include "sound_beeper.h" #include "sound_beeper.h"

View file

@ -25,13 +25,13 @@ uint32_t micros(void);
uint32_t millis(void); uint32_t millis(void);
typedef enum { typedef enum {
FAILURE_DEVELOPER = 0, FAILURE_DEVELOPER = 0,
FAILURE_MISSING_ACC, FAILURE_MISSING_ACC,
FAILURE_ACC_INIT, FAILURE_ACC_INIT,
FAILURE_ACC_INCOMPATIBLE, FAILURE_ACC_INCOMPATIBLE,
FAILURE_INVALID_EEPROM_CONTENTS, FAILURE_INVALID_EEPROM_CONTENTS,
FAILURE_FLASH_WRITE_FAILED, FAILURE_FLASH_WRITE_FAILED,
FAILURE_GYRO_INIT_FAILED FAILURE_GYRO_INIT_FAILED
} failureMode_e; } failureMode_e;
// failure // failure
@ -42,6 +42,7 @@ void systemReset(void);
void systemResetToBootloader(void); void systemResetToBootloader(void);
bool isMPUSoftReset(void); bool isMPUSoftReset(void);
void cycleCounterInit(void); void cycleCounterInit(void);
void checkForBootLoaderRequest(void);
void enableGPIOPowerUsageAndNoiseReductions(void); void enableGPIOPowerUsageAndNoiseReductions(void);
// current crystal frequency - 8 or 12MHz // current crystal frequency - 8 or 12MHz

View file

@ -15,10 +15,9 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <string.h>
#include "platform.h" #include "platform.h"
@ -37,7 +36,8 @@ void systemReset(void)
SCB->AIRCR = AIRCR_VECTKEY_MASK | (uint32_t)0x04; SCB->AIRCR = AIRCR_VECTKEY_MASK | (uint32_t)0x04;
} }
void systemResetToBootloader(void) { void systemResetToBootloader(void)
{
// 1FFFF000 -> 20000200 -> SP // 1FFFF000 -> 20000200 -> SP
// 1FFFF004 -> 1FFFF021 -> PC // 1FFFF004 -> 1FFFF021 -> PC
@ -68,6 +68,8 @@ bool isMPUSoftReset(void)
void systemInit(void) void systemInit(void)
{ {
checkForBootLoaderRequest();
SetSysClock(false); SetSysClock(false);
#ifdef CC3D #ifdef CC3D
@ -110,3 +112,6 @@ void systemInit(void)
SysTick_Config(SystemCoreClock / 1000); SysTick_Config(SystemCoreClock / 1000);
} }
void checkForBootLoaderRequest(void)
{
}

View file

@ -15,10 +15,9 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <string.h>
#include "platform.h" #include "platform.h"
@ -35,7 +34,8 @@ void systemReset(void)
SCB->AIRCR = AIRCR_VECTKEY_MASK | (uint32_t)0x04; SCB->AIRCR = AIRCR_VECTKEY_MASK | (uint32_t)0x04;
} }
void systemResetToBootloader(void) { void systemResetToBootloader(void)
{
// 1FFFF000 -> 20000200 -> SP // 1FFFF000 -> 20000200 -> SP
// 1FFFF004 -> 1FFFF021 -> PC // 1FFFF004 -> 1FFFF021 -> PC
@ -82,6 +82,8 @@ bool isMPUSoftReset(void)
void systemInit(void) void systemInit(void)
{ {
checkForBootLoaderRequest();
// Enable FPU // Enable FPU
SCB->CPACR = (0x3 << (10 * 2)) | (0x3 << (11 * 2)); SCB->CPACR = (0x3 << (10 * 2)) | (0x3 << (11 * 2));
SetSysClock(); SetSysClock();
@ -102,3 +104,7 @@ void systemInit(void)
// SysTick // SysTick
SysTick_Config(SystemCoreClock / 1000); SysTick_Config(SystemCoreClock / 1000);
} }
void checkForBootLoaderRequest(void)
{
}

View file

@ -15,26 +15,18 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <string.h>
#include "platform.h" #include "platform.h"
#include "accgyro_mpu.h"
#include "gpio.h" #include "gpio.h"
#include "nvic.h" #include "nvic.h"
#include "system.h" #include "system.h"
#include "exti.h" #include "exti.h"
#include "debug.h"
#include "sensor.h"
#include "accgyro.h"
#include "accgyro_mpu.h"
#include "accgyro_spi_mpu6000.h"
#include "accgyro_mpu6500.h"
#include "accgyro_spi_mpu9250.h"
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) #define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
@ -45,8 +37,8 @@ void systemReset(void)
if (mpuConfiguration.reset) if (mpuConfiguration.reset)
mpuConfiguration.reset(); mpuConfiguration.reset();
__disable_irq(); __disable_irq();
NVIC_SystemReset(); NVIC_SystemReset();
} }
void systemResetToBootloader(void) void systemResetToBootloader(void)
@ -54,10 +46,10 @@ void systemResetToBootloader(void)
if (mpuConfiguration.reset) if (mpuConfiguration.reset)
mpuConfiguration.reset(); mpuConfiguration.reset();
*((uint32_t *)0x2001FFFC) = 0xDEADBEEF; // 128KB SRAM STM32F4XX *((uint32_t *)0x2001FFFC) = 0xDEADBEEF; // 128KB SRAM STM32F4XX
__disable_irq(); __disable_irq();
NVIC_SystemReset(); NVIC_SystemReset();
} }
void enableGPIOPowerUsageAndNoiseReductions(void) void enableGPIOPowerUsageAndNoiseReductions(void)
@ -82,7 +74,7 @@ void enableGPIOPowerUsageAndNoiseReductions(void)
RCC_AHB1Periph_BKPSRAM | RCC_AHB1Periph_BKPSRAM |
RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_DMA1 |
RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_DMA2 |
0, ENABLE 0, ENABLE
); );
RCC_AHB2PeriphClockCmd(0, ENABLE); RCC_AHB2PeriphClockCmd(0, ENABLE);
@ -169,28 +161,45 @@ bool isMPUSoftReset(void)
void systemInit(void) void systemInit(void)
{ {
checkForBootLoaderRequest();
SetSysClock(); SetSysClock();
// Configure NVIC preempt/priority groups // Configure NVIC preempt/priority groups
NVIC_PriorityGroupConfig(NVIC_PRIORITY_GROUPING); NVIC_PriorityGroupConfig(NVIC_PRIORITY_GROUPING);
// cache RCC->CSR value to use it in isMPUSoftreset() and others // cache RCC->CSR value to use it in isMPUSoftreset() and others
cachedRccCsrValue = RCC->CSR; cachedRccCsrValue = RCC->CSR;
/* Accounts for OP Bootloader, set the Vector Table base address as specified in .ld file */ /* Accounts for OP Bootloader, set the Vector Table base address as specified in .ld file */
extern void *isr_vector_table_base; extern void *isr_vector_table_base;
NVIC_SetVectorTable((uint32_t)&isr_vector_table_base, 0x0); NVIC_SetVectorTable((uint32_t)&isr_vector_table_base, 0x0);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, DISABLE); RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, DISABLE);
RCC_ClearFlag(); RCC_ClearFlag();
enableGPIOPowerUsageAndNoiseReductions(); enableGPIOPowerUsageAndNoiseReductions();
// Init cycle counter // Init cycle counter
cycleCounterInit(); cycleCounterInit();
memset(extiHandlerConfigs, 0x00, sizeof(extiHandlerConfigs)); memset(extiHandlerConfigs, 0x00, sizeof(extiHandlerConfigs));
// SysTick // SysTick
SysTick_Config(SystemCoreClock / 1000); SysTick_Config(SystemCoreClock / 1000);
} }
void(*bootJump)(void);
void checkForBootLoaderRequest(void)
{
if (*((uint32_t *)0x2001FFFC) == 0xDEADBEEF) {
*((uint32_t *)0x2001FFFC) = 0x0;
__enable_irq();
__set_MSP(0x20001000);
bootJump = (void(*)(void))(*((uint32_t *) 0x1fff0004));
bootJump();
while (1);
}
}

View file

@ -17,7 +17,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "platform.h" #include "platform.h"
@ -26,7 +25,6 @@
#include "nvic.h" #include "nvic.h"
#include "gpio.h"
#include "gpio.h" #include "gpio.h"
#include "rcc.h" #include "rcc.h"
#include "system.h" #include "system.h"
@ -90,9 +88,36 @@ static uint8_t lookupTimerIndex(const TIM_TypeDef *tim)
#if USED_TIMERS & TIM_N(4) #if USED_TIMERS & TIM_N(4)
_CASE(4); _CASE(4);
#endif #endif
#if USED_TIMERS & TIM_N(5)
_CASE(5);
#endif
#if USED_TIMERS & TIM_N(6)
_CASE(6);
#endif
#if USED_TIMERS & TIM_N(7)
_CASE(7);
#endif
#if USED_TIMERS & TIM_N(8) #if USED_TIMERS & TIM_N(8)
_CASE(8); _CASE(8);
#endif #endif
#if USED_TIMERS & TIM_N(9)
_CASE(9);
#endif
#if USED_TIMERS & TIM_N(10)
_CASE(10);
#endif
#if USED_TIMERS & TIM_N(11)
_CASE(11);
#endif
#if USED_TIMERS & TIM_N(12)
_CASE(12);
#endif
#if USED_TIMERS & TIM_N(13)
_CASE(13);
#endif
#if USED_TIMERS & TIM_N(14)
_CASE(14);
#endif
#if USED_TIMERS & TIM_N(15) #if USED_TIMERS & TIM_N(15)
_CASE(15); _CASE(15);
#endif #endif
@ -123,9 +148,36 @@ TIM_TypeDef * const usedTimers[USED_TIMER_COUNT] = {
#if USED_TIMERS & TIM_N(4) #if USED_TIMERS & TIM_N(4)
_DEF(4), _DEF(4),
#endif #endif
#if USED_TIMERS & TIM_N(5)
_DEF(5),
#endif
#if USED_TIMERS & TIM_N(6)
_DEF(6),
#endif
#if USED_TIMERS & TIM_N(7)
_DEF(7),
#endif
#if USED_TIMERS & TIM_N(8) #if USED_TIMERS & TIM_N(8)
_DEF(8), _DEF(8),
#endif #endif
#if USED_TIMERS & TIM_N(9)
_DEF(9),
#endif
#if USED_TIMERS & TIM_N(10)
_DEF(10),
#endif
#if USED_TIMERS & TIM_N(11)
_DEF(11),
#endif
#if USED_TIMERS & TIM_N(12)
_DEF(12),
#endif
#if USED_TIMERS & TIM_N(13)
_DEF(13),
#endif
#if USED_TIMERS & TIM_N(14)
_DEF(14),
#endif
#if USED_TIMERS & TIM_N(15) #if USED_TIMERS & TIM_N(15)
_DEF(15), _DEF(15),
#endif #endif
@ -153,6 +205,18 @@ rccPeriphTag_t timerRCC(TIM_TypeDef *tim)
return 0; return 0;
} }
#if defined(STM32F3) || defined(STM32F4)
uint8_t timerGPIOAF(TIM_TypeDef *tim)
{
for (uint8_t i = 0; i < HARDWARE_TIMER_DEFINITION_COUNT; i++) {
if (timerDefinitions[i].TIMx == tim) {
return timerDefinitions[i].alternateFunction;
}
}
return 0;
}
#endif
void timerNVICConfigure(uint8_t irq) void timerNVICConfigure(uint8_t irq)
{ {
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
@ -364,7 +428,7 @@ void timerChClearCCFlag(const timerHardware_t *timHw)
// configure timer channel GPIO mode // configure timer channel GPIO mode
void timerChConfigGPIO(const timerHardware_t* timHw, ioConfig_t mode) void timerChConfigGPIO(const timerHardware_t* timHw, ioConfig_t mode)
{ {
IOInit(IOGetByTag(timHw->tag), OWNER_TIMER, RESOURCE_TIMER); IOInit(IOGetByTag(timHw->tag), OWNER_TIMER, RESOURCE_TIMER, 0);
IOConfigGPIO(IOGetByTag(timHw->tag), mode); IOConfigGPIO(IOGetByTag(timHw->tag), mode);
} }
@ -458,7 +522,7 @@ void timerChConfigOC(const timerHardware_t* timHw, bool outEnable, bool stateHig
if(outEnable) { if(outEnable) {
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
if (timHw->outputInverted) { if (timHw->output & TIMER_OUTPUT_INVERTED) {
stateHigh = !stateHigh; stateHigh = !stateHigh;
} }
TIM_OCInitStructure.TIM_OCPolarity = stateHigh ? TIM_OCPolarity_High : TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_OCPolarity = stateHigh ? TIM_OCPolarity_High : TIM_OCPolarity_Low;

View file

@ -69,6 +69,9 @@ typedef struct timerOvrHandlerRec_s {
typedef struct timerDef_s { typedef struct timerDef_s {
TIM_TypeDef *TIMx; TIM_TypeDef *TIMx;
rccPeriphTag_t rcc; rccPeriphTag_t rcc;
#if defined(STM32F3) || defined(STM32F4)
uint8_t alternateFunction;
#endif
} timerDef_t; } timerDef_t;
typedef struct timerHardware_s { typedef struct timerHardware_s {
@ -76,14 +79,18 @@ typedef struct timerHardware_s {
ioTag_t tag; ioTag_t tag;
uint8_t channel; uint8_t channel;
uint8_t irq; uint8_t irq;
uint8_t outputEnable; uint8_t output;
ioConfig_t ioMode; ioConfig_t ioMode;
#if defined(STM32F3) || defined(STM32F4) #if defined(STM32F3) || defined(STM32F4)
uint8_t alternateFunction; uint8_t alternateFunction;
#endif #endif
uint8_t outputInverted;
} timerHardware_t; } timerHardware_t;
enum {
TIMER_OUTPUT_ENABLED = 0x01,
TIMER_OUTPUT_INVERTED = 0x02
};
#ifdef STM32F1 #ifdef STM32F1
#if defined(STM32F10X_XL) || defined(STM32F10X_HD_VL) #if defined(STM32F10X_XL) || defined(STM32F10X_HD_VL)
#define HARDWARE_TIMER_DEFINITION_COUNT 14 #define HARDWARE_TIMER_DEFINITION_COUNT 14
@ -148,3 +155,7 @@ void timerForceOverflow(TIM_TypeDef *tim);
void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz); // TODO - just for migration void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz); // TODO - just for migration
rccPeriphTag_t timerRCC(TIM_TypeDef *tim); rccPeriphTag_t timerRCC(TIM_TypeDef *tim);
#if defined(STM32F3) || defined(STM32F4)
uint8_t timerGPIOAF(TIM_TypeDef *tim);
#endif

View file

@ -57,34 +57,31 @@ const timerDef_t timerDefinitions[HARDWARE_TIMER_DEFINITION_COUNT] = {
void TIM_SelectOCxM_NoDisable(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode) void TIM_SelectOCxM_NoDisable(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode)
{ {
uint32_t tmp = 0; uint32_t tmp = 0;
/* Check the parameters */ /* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx)); assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_CHANNEL(TIM_Channel)); assert_param(IS_TIM_CHANNEL(TIM_Channel));
assert_param(IS_TIM_OCM(TIM_OCMode)); assert_param(IS_TIM_OCM(TIM_OCMode));
tmp = (uint32_t) TIMx; tmp = (uint32_t) TIMx;
tmp += CCMR_Offset; tmp += CCMR_Offset;
if((TIM_Channel == TIM_Channel_1) ||(TIM_Channel == TIM_Channel_3)) if((TIM_Channel == TIM_Channel_1) ||(TIM_Channel == TIM_Channel_3)) {
{ tmp += (TIM_Channel>>1);
tmp += (TIM_Channel>>1);
/* Reset the OCxM bits in the CCMRx register */ /* Reset the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC1M); *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC1M);
/* Configure the OCxM bits in the CCMRx register */ /* Configure the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp |= TIM_OCMode; *(__IO uint32_t *) tmp |= TIM_OCMode;
} } else {
else tmp += (uint16_t)(TIM_Channel - (uint16_t)4) >> (uint16_t)1;
{
tmp += (uint16_t)(TIM_Channel - (uint16_t)4)>> (uint16_t)1;
/* Reset the OCxM bits in the CCMRx register */ /* Reset the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC2M); *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC2M);
/* Configure the OCxM bits in the CCMRx register */ /* Configure the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp |= (uint16_t)(TIM_OCMode << 8); *(__IO uint32_t *) tmp |= (uint16_t)(TIM_OCMode << 8);
} }
} }

Some files were not shown because too many files have changed in this diff Show more