comp.lang.ada
 help / color / mirror / Atom feed
From: Simon Wright <simon@pushface.org>
Subject: Re: GNAT stm34f4 zfp question.
Date: Wed, 18 Mar 2015 17:58:10 +0000
Date: 2015-03-18T17:58:10+00:00	[thread overview]
Message-ID: <ly1tkmw5l9.fsf@pushface.org> (raw)
In-Reply-To: lytwy01ute.fsf@pushface.org

Simon Wright <simon@pushface.org> writes:

> And even then I'm concerned about multiplexed GPIO interrupts; as I
> understand it, there is only one EXTI0 interrupt, corresponding to pin
> 0 on any GPIO, so if you need more than one pin 0 interrupt you'll
> need to manage all of them in one super-handler, or arrange to chain
> handlers (which I don't think AdaCore's RTS supports??)

Somewhat clearer about this now!

There are 16 GPIO-related interrupt lines, corresponding to the 16 bits
in a GPIO register.

Each line is associated with one GPIO (the default is GPIOA).

Each line can have interrupts enabled (and/or events???)

Lines 0..4 have their own interrupts, EXTI0_IRQ to EXTI4_IRQ.

Lines 5..9 are multiplexed to one interrupt, EXTI9_5_IRQ.

Lines 10..15 are multiplexed to one interrupt, EXTI15_10_IRQ.

So pin PC11 (GPIOC, bit 11), which is one of the unassigned pins on the
STM32F429I Disco, can be interrupt-enabled (in which case no other
GPIO's pin 11 can be interrupt-enabled) and will generate
EXTI15_10_IRQ. If interrupts are required on lines 10, 12, 13, 14, or 15
(which can each be associated with different GPIOs) then the handler for
EXTI15_10_IRQ will have to determine which is which.

At the moment I'm toying with mechanical translation of the STMCube
stm32f429xx.h (using -fdump-ada-spec and a sed script), and have the
code below, which is fairly ugly, rather like the C equivalent. I could
copy AdaCore's design (not the code, of course!) which handles multi-bit
fields much better, but I'm looking for a mechanical translation at this
stage.

with Ada.Interrupts.Names;
with Interfaces;
with System;
with stm32f429xx_h; use stm32f429xx_h;
package body Button is

   --  We're going to use a pin on the left-hand side of the board:
   --  P1/44 is PC11.

   protected B
   with
     Interrupt_Priority => System.Interrupt_Priority'First is
      entry Wait_For_Trigger;
   private
      Triggered : Boolean := False;
      procedure Handler;
      pragma Attach_Handler (Handler, Ada.Interrupts.Names.EXTI15_10_IRQ);
   end B;

   procedure Wait_For_Button_Release is
   begin
      B.Wait_For_Trigger;
   end Wait_For_Button_Release;

   protected body B is
      entry Wait_For_Trigger when Triggered is
      begin
         Triggered := False;
      end Wait_For_Trigger;

      procedure Handler is
         use type Interfaces.Unsigned_32;
      begin
         if (EXTI.PR and EXTI_PR_PR11) /= 0 then
            Triggered := True;
            EXTI.PR := EXTI_PR_PR11;  -- clear the interrupt by *writing* 1
         else
            raise Program_Error with "unexpected interrupt";
         end if;
      end Handler;
   end B;

   procedure Initialize is
      use type Interfaces.Unsigned_32;
   begin
      --  First, we need to enable GPIOC's clock.
      RCC.AHB1ENR := RCC.AHB1ENR or RCC_AHB1ENR_GPIOCEN;

      --  Don't need to configure bit 11 as an input, because that's
      --  the default.

      --  Don't need to configure OTYPER, because the pin is an input.

      --  Don't need to configure OSPEEDR, because the pin is an input.

      --  Configure PUPDR for pull-up (AdaCore have no-pull?)
      declare
         Pull_Register : Interfaces.Unsigned_32;
      begin
         Pull_Register := GPIOC.PUPDR;
         Pull_Register := Pull_Register and not GPIO_PUPDR_PUPDR11;
         Pull_Register := Pull_Register or GPIO_PUPDR_PUPDR11_0;
         GPIOC.PUPDR := Pull_Register;
      end;

      --  Enable SYSCFG's clock.
      RCC.APB2ENR := RCC.APB2ENR or RCC_APB2ENR_SYSCFGEN;

      --  Then, configure SYSCFG_EXTICR3[12:15] (pin 11) for GPIOC.
      declare
         Exti_Register : Interfaces.Unsigned_32;
      begin
         Exti_Register := SYSCFG.EXTICR (2);  -- C indexing!
         Exti_Register := Exti_Register and not SYSCFG_EXTICR3_EXTI11;
         Exti_Register := Exti_Register or SYSCFG_EXTICR3_EXTI11_PC;
         SYSCFG.EXTICR (2) := Exti_Register;
      end;

      --  Then, configure EXTI on pin 11 for rising-edge (button-release)
      EXTI.RTSR := EXTI.RTSR or EXTI_RTSR_TR11;
      --  and enable interrupts on pin 11.
      EXTI.IMR := EXTI.IMR or EXTI_IMR_MR11;
   end Initialize;

begin
   Initialize;
end Button;


      parent reply	other threads:[~2015-03-18 17:58 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-03  7:45 GNAT stm34f4 zfp question jan.de.kruyf
2015-03-03  9:20 ` jan.de.kruyf
2015-03-03 17:15   ` Patrick Noffke
2015-03-03 20:13     ` jan.de.kruyf
2015-03-04 15:22     ` jan.de.kruyf
2015-03-04 18:28       ` Simon Wright
2015-03-04 20:03         ` jan.de.kruyf
2015-03-18 17:58         ` Simon Wright [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox