AdaCore / Ada_Drivers_Library

Ada source code and complete sample GNAT projects for selected bare-board platforms supported by GNAT.
BSD 3-Clause "New" or "Revised" License
239 stars 141 forks source link

STM32F7 : Quad-SPI byte access to CCR #147

Closed ghost closed 7 years ago

ghost commented 7 years ago

Hello,

First of all I am kind of new with Ada so if my issue is not a real issue but a miss-use of your SVD files, sorry for that.

I am trying to use the QUAD-SPI of my STM32F767 using your STM32F7 SVD files.

I currently use directly the "QUADSPI_Periph" object from the file _Ada_Drivers_Library/arch/ARM/STM32/svd/stm32f7x9/stm32svd-quadspi.ads.

From the STM32F7 Reference Manual, the Quad-SPI communication starts as soon as we wrote into the QuadSPI_CCR.INSTRUCTION register (which has a size of 8 bits).

For example, I am using your object like this :

STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.DDRM :=  ...   ;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.DHHC := ...   ;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.SIOO := ...   ;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.DMODE :=  ...   ;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.DCYC := ...   ;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.ADMODE :=  ...   ;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.IMODE := ..;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.FMODE := ... ;
STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.ABMODE := ...  ;

Once I setup my communication frame format, trigger the communication by writing into INSTRUCTION

STM32_SVD.QUADSPI.QUADSPI_Periph.CCR.INSTRUCTION :=  ... ;

The problem is that the CCR register is defined as a "Volatile_Full_Access" like this :

type CCR_Register is record
      --  Instruction
      INSTRUCTION    : CCR_INSTRUCTION_Field := 16#0#;
      --  Instruction mode
      IMODE          : CCR_IMODE_Field := 16#0#;
      --  Address mode
      ADMODE         : CCR_ADMODE_Field := 16#0#;
      --  Address size
      ADSIZE         : CCR_ADSIZE_Field := 16#0#;
      --  Alternate bytes mode
      ABMODE         : CCR_ABMODE_Field := 16#0#;
      --  Alternate bytes size
      ABSIZE         : CCR_ABSIZE_Field := 16#0#;
      --  Number of dummy cycles
      DCYC           : CCR_DCYC_Field := 16#0#;
      --  unspecified
      Reserved_23_23 : HAL.Bit := 16#0#;
      --  Data mode
      DMODE          : CCR_DMODE_Field := 16#0#;
      --  Functional mode
      FMODE          : CCR_FMODE_Field := 16#0#;
      --  Send instruction only once mode
      SIOO           : Boolean := False;
      --  unspecified
      Reserved_29_29 : HAL.Bit := 16#0#;
      --  DDR hold half cycle
      DHHC           : Boolean := False;
      --  Double data rate mode
      DDRM           : Boolean := False;
   end record
     with Volatile_Full_Access, Size => 32,
Bit_Order => 
System.Low_Order_First;

With this pragma, I suspect that my instructions above, when configuring the CCR modes independently, wrote several times inside CCR.INSTRUCTION and then, the Quad-SPI peripheral tries to start several communications.

I currently don't have a solution to propose (exepecting creating manually several pointers to the right locations... but I would prefer a way to fix the SVD descriptions, these descriptions are so helpful !)

So, let me know what do you think.

Best regards, FG

Fabien-Chouteau commented 7 years ago

Hi,

No problem, thanks for contributing :)

This is one instance where Volatile_Full_Access is not the best option, it's also the case with shadow registers.

Here's a workaround:

   --  Store a copy of the entire register in a variable 
   CCR : CCR_Register := STM32_SVD.QUADSPI.QUADSPI_Periph.CCR;
begin 

   --  Configure communication in the CCR variable
   CCR.DDRM := ...;
   CCR.DHHC := ...;
   ...
   CCR.INSTRUCTION := ...;

   --  Write the entire register at once:
   STM32_SVD.QUADSPI.QUADSPI_Periph.CCR := CCR:

Regards,

ghost commented 7 years ago

Hi,

Thanks for your reply and your workaround ! It's working like a charm :-)

Best regards,

Fabien-Chouteau commented 7 years ago

You are welcome :)