Message ID | c3bfb7b3bcf4cb6e4bb7a2fad6c3979692505c3b.1453187657.git.alistair@alistair23.me (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 19 January 2016 at 07:23, Alistair Francis <alistair23@gmail.com> wrote: > Connect the ADC devices to the STM32F205 SoC. > > Signed-off-by: Alistair Francis <alistair@alistair23.me> > --- > V2: > - Fix up the device/devices commit message > > hw/arm/stm32f205_soc.c | 22 ++++++++++++++++++++++ > include/hw/arm/stm32f205_soc.h | 3 +++ > 2 files changed, 25 insertions(+) > > diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c > index a2bd970..28d4301 100644 > --- a/hw/arm/stm32f205_soc.c > +++ b/hw/arm/stm32f205_soc.c > @@ -32,9 +32,12 @@ static const uint32_t timer_addr[STM_NUM_TIMERS] = { 0x40000000, 0x40000400, > 0x40000800, 0x40000C00 }; > static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40011000, 0x40004400, > 0x40004800, 0x40004C00, 0x40005000, 0x40011400 }; > +static const uint32_t adc_addr[STM_NUM_ADCS] = { 0x40012000, 0x40012100, > + 0x40012200 }; > > static const int timer_irq[STM_NUM_TIMERS] = {28, 29, 30, 50}; > static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39, 52, 53, 71}; > +#define ADC_IRQ 18 Really three devices but only one IRQ ? > + /* ADC 1 to 3 */ > + for (i = 0; i < STM_NUM_ADCS; i++) { > + dev = DEVICE(&(s->adc[i])); > + object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err); > + if (err != NULL) { > + error_propagate(errp, err); > + return; > + } > + busdev = SYS_BUS_DEVICE(dev); > + sysbus_mmio_map(busdev, 0, adc_addr[i]); > + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, ADC_IRQ)); You can't just wire multiple irq lines up like this; I think if you do then if devices A and B both assert the IRQ and then A deasserts it, then the receiving device will see an IRQ deassert when it should not (since B still holds it high). thanks -- PMM
On Tue, Feb 2, 2016 at 7:27 AM, Peter Maydell <peter.maydell@linaro.org> wrote: > On 19 January 2016 at 07:23, Alistair Francis <alistair23@gmail.com> wrote: >> Connect the ADC devices to the STM32F205 SoC. >> >> Signed-off-by: Alistair Francis <alistair@alistair23.me> >> --- >> V2: >> - Fix up the device/devices commit message >> >> hw/arm/stm32f205_soc.c | 22 ++++++++++++++++++++++ >> include/hw/arm/stm32f205_soc.h | 3 +++ >> 2 files changed, 25 insertions(+) >> >> diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c >> index a2bd970..28d4301 100644 >> --- a/hw/arm/stm32f205_soc.c >> +++ b/hw/arm/stm32f205_soc.c >> @@ -32,9 +32,12 @@ static const uint32_t timer_addr[STM_NUM_TIMERS] = { 0x40000000, 0x40000400, >> 0x40000800, 0x40000C00 }; >> static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40011000, 0x40004400, >> 0x40004800, 0x40004C00, 0x40005000, 0x40011400 }; >> +static const uint32_t adc_addr[STM_NUM_ADCS] = { 0x40012000, 0x40012100, >> + 0x40012200 }; >> >> static const int timer_irq[STM_NUM_TIMERS] = {28, 29, 30, 50}; >> static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39, 52, 53, 71}; >> +#define ADC_IRQ 18 > > Really three devices but only one IRQ ? Yep, that's how HW does it. At least according to the reference manual. > >> + /* ADC 1 to 3 */ >> + for (i = 0; i < STM_NUM_ADCS; i++) { >> + dev = DEVICE(&(s->adc[i])); >> + object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err); >> + if (err != NULL) { >> + error_propagate(errp, err); >> + return; >> + } >> + busdev = SYS_BUS_DEVICE(dev); >> + sysbus_mmio_map(busdev, 0, adc_addr[i]); >> + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, ADC_IRQ)); > > You can't just wire multiple irq lines up like this; I think if > you do then if devices A and B both assert the IRQ and then A > deasserts it, then the receiving device will see an IRQ deassert > when it should not (since B still holds it high). I can't figure out if that is how HW actually does it. I can't find too much in the data sheet on how these interrupts behave. In saying that, I am fine with what you described being the behaviour. I don't know any better way to connect the 3 devices to one interrupt line. Do you have any suggestions? Thanks, Alistair > > thanks > -- PMM
On 21 February 2016 at 23:35, Alistair Francis <alistair23@gmail.com> wrote: > On Tue, Feb 2, 2016 at 7:27 AM, Peter Maydell <peter.maydell@linaro.org> wrote: >> On 19 January 2016 at 07:23, Alistair Francis <alistair23@gmail.com> wrote: >> You can't just wire multiple irq lines up like this; I think if >> you do then if devices A and B both assert the IRQ and then A >> deasserts it, then the receiving device will see an IRQ deassert >> when it should not (since B still holds it high). > > I can't figure out if that is how HW actually does it. I can't find > too much in the data sheet on how these interrupts behave. > > In saying that, I am fine with what you described being the behaviour. > I don't know any better way to connect the 3 devices to one interrupt > line. Do you have any suggestions? You're right that the data sheet is unclear, but I think the only vaguely plausible setup is that the three lines are ORed together. That way if any ADC asserts the line then the guest presumably looks at all of them to find which one has asserted it, and then writes to the register to acknowledge the interrupt. So if two ADCs assert at the same time, the guest will still (correctly) see an interrupt until it acks the second ADC. Unfortunately we don't have a qemu_irq OR gate at the moment I think, but it's a pretty simple thing to write. thanks -- PMM
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index a2bd970..28d4301 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -32,9 +32,12 @@ static const uint32_t timer_addr[STM_NUM_TIMERS] = { 0x40000000, 0x40000400, 0x40000800, 0x40000C00 }; static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40011000, 0x40004400, 0x40004800, 0x40004C00, 0x40005000, 0x40011400 }; +static const uint32_t adc_addr[STM_NUM_ADCS] = { 0x40012000, 0x40012100, + 0x40012200 }; static const int timer_irq[STM_NUM_TIMERS] = {28, 29, 30, 50}; static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39, 52, 53, 71}; +#define ADC_IRQ 18 static void stm32f205_soc_initfn(Object *obj) { @@ -55,6 +58,12 @@ static void stm32f205_soc_initfn(Object *obj) TYPE_STM32F2XX_TIMER); qdev_set_parent_bus(DEVICE(&s->timer[i]), sysbus_get_default()); } + + for (i = 0; i < STM_NUM_ADCS; i++) { + object_initialize(&s->adc[i], sizeof(s->adc[i]), + TYPE_STM32F2XX_ADC); + qdev_set_parent_bus(DEVICE(&s->adc[i]), sysbus_get_default()); + } } static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) @@ -128,6 +137,19 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) sysbus_mmio_map(busdev, 0, timer_addr[i]); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, timer_irq[i])); } + + /* ADC 1 to 3 */ + for (i = 0; i < STM_NUM_ADCS; i++) { + dev = DEVICE(&(s->adc[i])); + object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, adc_addr[i]); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, ADC_IRQ)); + } } static Property stm32f205_soc_properties[] = { diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h index 0390eff..091e4be 100644 --- a/include/hw/arm/stm32f205_soc.h +++ b/include/hw/arm/stm32f205_soc.h @@ -28,6 +28,7 @@ #include "hw/misc/stm32f2xx_syscfg.h" #include "hw/timer/stm32f2xx_timer.h" #include "hw/char/stm32f2xx_usart.h" +#include "hw/adc/stm32f2xx_adc.h" #define TYPE_STM32F205_SOC "stm32f205-soc" #define STM32F205_SOC(obj) \ @@ -35,6 +36,7 @@ #define STM_NUM_USARTS 6 #define STM_NUM_TIMERS 4 +#define STM_NUM_ADCS 3 #define FLASH_BASE_ADDRESS 0x08000000 #define FLASH_SIZE (1024 * 1024) @@ -52,6 +54,7 @@ typedef struct STM32F205State { STM32F2XXSyscfgState syscfg; STM32F2XXUsartState usart[STM_NUM_USARTS]; STM32F2XXTimerState timer[STM_NUM_TIMERS]; + STM32F2XXADCState adc[STM_NUM_ADCS]; } STM32F205State; #endif
Connect the ADC devices to the STM32F205 SoC. Signed-off-by: Alistair Francis <alistair@alistair23.me> --- V2: - Fix up the device/devices commit message hw/arm/stm32f205_soc.c | 22 ++++++++++++++++++++++ include/hw/arm/stm32f205_soc.h | 3 +++ 2 files changed, 25 insertions(+)