-
Notifications
You must be signed in to change notification settings - Fork 159
Enable qemu target for STM32 emulation #562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| FILESYSTEMS := common base_fonts 320x240x16 | ||
|
|
||
| SCREENSIZE := 320x240x16 | ||
| FONTS = filesystem/$(FILESYSTEM)/media/15ascii.fon \ | ||
| filesystem/$(FILESYSTEM)/media/23bold.fon | ||
|
|
||
| ifndef BUILD_TARGET | ||
| CROSS = arm-none-eabi- | ||
|
|
||
| ALL = $(LIBOPENCM3) $(TARGET).bin | ||
|
|
||
| NUM_MODELS ?= 10 | ||
|
|
||
| LINKFILE = $(SDIR)/target/$(TARGET)/$(TARGET).ld | ||
| LIBOPENCM3 = $(SDIR)/libopencm3/lib/libopencm3_stm32f1.a | ||
|
|
||
| SRC_C := $(wildcard $(SDIR)/target/$(TARGET)/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/stm32/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/filesystems/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/filesystems/devofs/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/filesystems/petit_fat/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/devo/msc2/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/devo/msc2/lib/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/devo/hid/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/devo/protocol/*.c) \ | ||
| $(wildcard $(SDIR)/target/common/devo/uart.c) | ||
|
|
||
| SRC_C := $(filter-out $(SDIR)/target/common/stm32/spi_flash.c, $(SRC_C)) | ||
|
|
||
| CFLAGS = -DPROFILE -D"assert_param(x)=" -DSTM32F10X_HD -DSTM32F1 -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fdata-sections -ffunction-sections -I$(SDIR)/target/common/devo/msc2/lib -I$(SDIR)/target/common/devo/msc2 -I$(SDIR)/libopencm3/include -I$(SDIR)/target/common/filesystems -fno-builtin-printf -Os --specs=nano.specs | ||
| MODULE_FLAGS = -fno-builtin | ||
|
|
||
| LFLAGS = -nostartfiles -Wl,-gc-sections -Wl,-Map=$(TARGET).map,--cref -lc -lnosys -L$(SDIR) -Lobjs/$(TARGET) | ||
| LFLAGS2 = -Wl,-T$(LINKFILE) | ||
|
|
||
|
|
||
| else #BUILD_TARGET | ||
|
|
||
| $(TARGET).bin: $(TARGET).elf | ||
| $(CP) -O binary $< $@ | ||
| $(DUMP) -S $< > $(TARGET).list | ||
|
|
||
| $(LIBOPENCM3): | ||
| +$(MAKE) -C $(SDIR)/libopencm3 TARGETS=stm32/f1 lib | ||
|
|
||
|
|
||
| endif #BUILD_TARGET | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| /* | ||
| This project is free software: you can redistribute it and/or modify | ||
| it under the terms of the GNU General Public License as published by | ||
| the Free Software Foundation, either version 3 of the License, or | ||
| (at your option) any later version. | ||
|
|
||
| Deviation is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU General Public License for more details. | ||
|
|
||
| You should have received a copy of the GNU General Public License | ||
| along with Deviation. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #include <libopencm3/stm32/gpio.h> | ||
| #include <libopencm3/stm32/rcc.h> | ||
| #include <libopencm3/stm32/timer.h> | ||
| #include "common.h" | ||
|
|
||
| // FIXME introduce constants for Timer (TIM4), compare (TIM_Oc4) | ||
| // timer clock (RCC_APB1ENR_TIM4EN), Port (GPIOB), Pin (GPIO9) | ||
| // Port clock RCC_APB2ENR_IOPBEN | ||
|
|
||
| void BACKLIGHT_Init() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cna u just include another real implementation?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. some of these may be able to use a real implementation, but the qemu target does not have all STM32 features, and without proper SPI or clock support a lot of things won't work. Before I merge this, I'll clean up what can be done though. |
||
| { | ||
| // Pin PB9, Timer 4 channel 4 | ||
| rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); | ||
| //Turn off backlight | ||
| gpio_set_mode(GPIOB, GPIO_MODE_INPUT, | ||
| GPIO_CNF_INPUT_FLOAT, GPIO9); | ||
|
|
||
| //Configure Backlight PWM | ||
| rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN); | ||
| timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, | ||
| TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); | ||
| timer_set_period(TIM4, 0x2CF); | ||
| timer_set_prescaler(TIM4, 0); | ||
| timer_generate_event(TIM4, TIM_EGR_UG); | ||
| //timer_set_repetition_counter(TIM3, 0); | ||
| timer_set_oc_mode(TIM4, TIM_OC4, TIM_OCM_PWM1); | ||
| timer_enable_oc_preload(TIM4, TIM_OC4); | ||
|
|
||
| timer_set_oc_polarity_high(TIM4, TIM_OC4); | ||
| timer_enable_oc_output(TIM4, TIM_OC4); | ||
|
|
||
| timer_enable_preload(TIM4); | ||
| } | ||
|
|
||
| void BACKLIGHT_Brightness(unsigned brightness) | ||
| { | ||
| timer_disable_counter(TIM4); | ||
| if (brightness == 0) { | ||
| // Turn off Backlight | ||
| gpio_set_mode(GPIOB, GPIO_MODE_INPUT, | ||
| GPIO_CNF_INPUT_FLOAT, GPIO9); | ||
| } else if(brightness > 9) { | ||
| // Turn on Backlight full | ||
| gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, | ||
| GPIO_CNF_OUTPUT_PUSHPULL, GPIO9); | ||
| gpio_set(GPIOB, GPIO9); | ||
| } else { | ||
| gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, | ||
| GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9); | ||
| u32 duty_cycle = 720 * brightness / 10 ; | ||
| timer_set_oc_value(TIM4, TIM_OC4, duty_cycle); | ||
| timer_enable_counter(TIM4); | ||
| } | ||
| } | ||
|
|
||
| void LCD_Contrast(unsigned contrast) | ||
| { | ||
| (void)contrast; // dummy method for devo8. Only valid in devo10 now | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #ifdef CHANDEF | ||
| CHANDEF(AILERON) | ||
| CHANDEF(ELEVATOR) | ||
| CHANDEF(THROTTLE) | ||
| CHANDEF(RUDDER) | ||
| CHANDEF(AUX4) | ||
| CHANDEF(AUX5) | ||
| CHANDEF(AUX6) | ||
| CHANDEF(AUX7) | ||
| CHANDEF(SWA0) | ||
| CHANDEF(SWA1) | ||
| CHANDEF(SWB0) | ||
| CHANDEF(SWB1) | ||
| CHANDEF(SWC0) | ||
| CHANDEF(SWC1) | ||
| CHANDEF(SWC2) | ||
| CHANDEF(SWD0) | ||
| CHANDEF(SWD1) | ||
| CHANDEF(SWE0) | ||
| CHANDEF(SWE1) | ||
| CHANDEF(SWE2) | ||
| CHANDEF(SWF0) | ||
| CHANDEF(SWF1) | ||
| CHANDEF(SWG0) | ||
| CHANDEF(SWG1) | ||
| CHANDEF(SWG2) | ||
| CHANDEF(SWH0) | ||
| CHANDEF(SWH1) | ||
| #endif | ||
|
|
||
| #ifdef UNDEF_INP | ||
| #define INP_RUD_DR0 INP_SWA0 | ||
| #define INP_RUD_DR1 INP_SWA1 | ||
| #define INP_ELE_DR0 INP_SWB0 | ||
| #define INP_ELE_DR1 INP_SWB1 | ||
| #define INP_AIL_DR0 INP_SWC0 | ||
| #define INP_AIL_DR1 INP_SWC1 | ||
| #define INP_FMOD0 INP_SWD0 | ||
| #define INP_MIX0 INP_SWE0 | ||
| #define INP_MIX1 INP_SWE1 | ||
| #define INP_MIX2 INP_SWE2 | ||
| #define INP_GEAR0 INP_SWF0 | ||
| #define INP_GEAR1 INP_SWF1 | ||
| #endif | ||
|
|
||
|
|
||
| #ifdef BUTTONDEF | ||
| BUTTONDEF(TRIM_LV_NEG) /* LEFT-VERTICAL */ | ||
| BUTTONDEF(TRIM_LV_POS) | ||
| BUTTONDEF(TRIM_RV_NEG) /* RIGHT-VERTICAL */ | ||
| BUTTONDEF(TRIM_RV_POS) | ||
| BUTTONDEF(TRIM_LH_NEG) /* LEFT-HORIZONTAL */ | ||
| BUTTONDEF(TRIM_LH_POS) | ||
| BUTTONDEF(TRIM_RH_NEG) /* RIGHT-HORIZONTAL */ | ||
| BUTTONDEF(TRIM_RH_POS) | ||
| BUTTONDEF(LEFT) | ||
| BUTTONDEF(RIGHT) | ||
| BUTTONDEF(DOWN) | ||
| BUTTONDEF(UP) | ||
| BUTTONDEF(ENTER) | ||
| BUTTONDEF(EXIT) | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| /* | ||
| This project is free software: you can redistribute it and/or modify | ||
| it under the terms of the GNU General Public License as published by | ||
| the Free Software Foundation, either version 3 of the License, or | ||
| (at your option) any later version. | ||
|
|
||
| Deviation is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU General Public License for more details. | ||
|
|
||
| You should have received a copy of the GNU General Public License | ||
| along with Deviation. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
| #include <libopencm3/stm32/rcc.h> | ||
| #include <libopencm3/stm32/gpio.h> | ||
| #include "common.h" | ||
| #include "mixer.h" | ||
| #include "config/tx.h" | ||
| #include "../common/devo/devo.h" | ||
|
|
||
| //Order is MODE1: AIL, ELE, THR, RUD, LeftDial, Right Dial, Left Shoulder, Right Shoulder, Vdd, Voltage | ||
| // PA0 PA1, PA2, PA3, PA5, PA6, PB0 PA4, PB1 | ||
| const u8 adc_chan_sel[NUM_ADC_CHANNELS] = | ||
| {0, 1, 2, 3, 5, 6, 8, 4, 16, 9}; | ||
|
|
||
| void CHAN_Init() | ||
| { | ||
| rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); | ||
| rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); | ||
| rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); | ||
| ADC_Init(); | ||
|
|
||
| /* configure channels for analog */ | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0); | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1); | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO2); | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO3); | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO4); | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO5); | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO6); | ||
| /* Enable Voltage measurement */ | ||
| gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0); | ||
| gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1); | ||
|
|
||
| /* configure switches for digital I/O */ | ||
| gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, | ||
| GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | | ||
| GPIO5 | GPIO6 | GPIO7 | GPIO8 | GPIO9); | ||
| gpio_set(GPIOC, | ||
| GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | | ||
| GPIO5 | GPIO6 | GPIO7 | GPIO8 | GPIO9); | ||
| gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO8); | ||
| gpio_set(GPIOA, GPIO8); | ||
| } | ||
|
|
||
| s32 CHAN_ReadRawInput(int channel) | ||
| { | ||
| s32 value = 0; | ||
| switch(channel) { | ||
| case INP_AILERON: value = adc_array_raw[0]; break; // bug fix: right vertical | ||
| case INP_ELEVATOR: value = adc_array_raw[1]; break; // bug fix: right horizon | ||
| case INP_THROTTLE: value = adc_array_raw[2]; break; // bug fix: left horizon | ||
| case INP_RUDDER: value = adc_array_raw[3]; break; // bug fix: left vertical | ||
| case INP_AUX4: value = adc_array_raw[4]; break; | ||
| case INP_AUX5: value = adc_array_raw[5]; break; | ||
| case INP_AUX6: value = adc_array_raw[6]; break; | ||
| case INP_AUX7: value = adc_array_raw[7]; break; | ||
| case INP_SWA0: value = gpio_get(GPIOC, GPIO0); break; | ||
| case INP_SWA1: value = ! gpio_get(GPIOC, GPIO0); break; | ||
| case INP_SWB0: value = gpio_get(GPIOC, GPIO1); break; | ||
| case INP_SWB1: value = ! gpio_get(GPIOC, GPIO1); break; | ||
| case INP_SWC0: value = ! gpio_get(GPIOC, GPIO2); break; | ||
| case INP_SWC1: value = (gpio_get(GPIOC, GPIO2) && gpio_get(GPIOC, GPIO3)); break; | ||
| case INP_SWC2: value = ! gpio_get(GPIOC, GPIO3); break; | ||
| case INP_SWD0: value = gpio_get(GPIOC, GPIO6); break; | ||
| case INP_SWD1: value = ! gpio_get(GPIOC, GPIO6); break; | ||
| case INP_SWE0: value = ! gpio_get(GPIOC, GPIO4); break; | ||
| case INP_SWE1: value = (gpio_get(GPIOC, GPIO4) && gpio_get(GPIOC, GPIO5)); break; | ||
| case INP_SWE2: value = ! gpio_get(GPIOC, GPIO5); break; | ||
| case INP_SWF0: value = gpio_get(GPIOC, GPIO7); break; | ||
| case INP_SWF1: value = ! gpio_get(GPIOC, GPIO7); break; | ||
| case INP_SWG0: value = ! gpio_get(GPIOC, GPIO8); break; | ||
| case INP_SWG1: value = (gpio_get(GPIOC, GPIO8) && gpio_get(GPIOC, GPIO9)); break; | ||
| case INP_SWG2: value = ! gpio_get(GPIOC, GPIO9); break; | ||
| case INP_SWH0: value = gpio_get(GPIOA, GPIO8); break; | ||
| case INP_SWH1: value = ! gpio_get(GPIOA, GPIO8); break; | ||
| } | ||
| return value; | ||
| } | ||
| s32 CHAN_ReadInput(int channel) | ||
| { | ||
| s32 value = CHAN_ReadRawInput(channel); | ||
| if(channel <= INP_HAS_CALIBRATION) { | ||
| s32 max = Transmitter.calibration[channel - 1].max; | ||
| s32 min = Transmitter.calibration[channel - 1].min; | ||
| s32 zero = Transmitter.calibration[channel - 1].zero; | ||
| if(! zero) { | ||
| //If this input doesn't have a zero, calculate from max/min | ||
| zero = ((u32)max + min) / 2; | ||
| } | ||
| // Derate min and max by 1% to ensure we can get all the way to 100% | ||
| max = (max - zero) * 99 / 100; | ||
| min = (min - zero) * 99 / 100; | ||
| if(value >= zero) { | ||
| value = (value - zero) * CHAN_MAX_VALUE / max; | ||
| } else { | ||
| value = (value - zero) * CHAN_MIN_VALUE / min; | ||
| } | ||
| //Bound output | ||
| if (value > CHAN_MAX_VALUE) | ||
| value = CHAN_MAX_VALUE; | ||
| if (value < CHAN_MIN_VALUE) | ||
| value = CHAN_MIN_VALUE; | ||
| } else { | ||
| value = value ? CHAN_MAX_VALUE : CHAN_MIN_VALUE; | ||
| } | ||
| if (channel == INP_AILERON || channel == INP_ELEVATOR || | ||
| channel == INP_THROTTLE || channel == INP_RUDDER) | ||
| { | ||
| value = -value; | ||
| } | ||
| return value; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* | ||
| This project is free software: you can redistribute it and/or modify | ||
| it under the terms of the GNU General Public License as published by | ||
| the Free Software Foundation, either version 3 of the License, or | ||
| (at your option) any later version. | ||
|
|
||
| Deviation is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU General Public License for more details. | ||
|
|
||
| You should have received a copy of the GNU General Public License | ||
| along with Deviation. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
| #include <libopencm3/stm32/gpio.h> | ||
| #include <libopencm3/stm32/rcc.h> | ||
| #include <libopencm3/stm32/fsmc.h> | ||
| #include "common.h" | ||
| #include "lcd.h" | ||
|
|
||
| u8 screen_flip; | ||
| const struct lcdtype *disp_type; | ||
|
|
||
| void lcd_cmd(uint8_t addr, uint8_t data) | ||
| { | ||
| } | ||
|
|
||
| void lcd_set_pos(unsigned int x0, unsigned int y0) | ||
| { | ||
| } | ||
|
|
||
| void LCD_DrawPixel(unsigned int color) | ||
| { | ||
| } | ||
|
|
||
| void LCD_DrawPixelXY(unsigned int x, unsigned int y, unsigned int color) | ||
| { | ||
| } | ||
|
|
||
| void LCD_DrawStart(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, enum DrawDir dir) | ||
| { | ||
| } | ||
|
|
||
| void LCD_DrawStop(void) | ||
| { | ||
| } | ||
|
|
||
| void LCD_Sleep() | ||
| { | ||
| } | ||
|
|
||
| void LCD_Init() | ||
| { | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should create a Makefile.inc for all STM32 related parts. this makefile, the one under devo/common, and the one under at9 are largely duplicatd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes probably. This was only meant to be a proof-of-concept. certainly not ready for inclusion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we also need an instruction on qemu as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some documentation now.