A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/reznikmm/aa_stm32_drivers below:

reznikmm/aa_stm32_drivers: Another Ada STM32 drivers library

Another Ada STM32 MCU Drivers Library

A lightweight, generic-based driver library for STM32 microcontrollers. This library provides low-level drivers for common peripherals while prioritizing simplicity and efficiency.

This library avoids using tagged types (object-oriented programming, as used in the Ada Drivers Library and HAL) in favor of Ada generics. The rationale for this decision includes:

Add this library to your project using Alire:

alr with aa_stm32_drivers --use=https://github.com/reznikmm/aa_stm32_drivers

STM32 devices use pins grouped into ports. To specify a pin, provide a port name (enumeration literals PA, PB, etc) and a pin number (0 to 15).

To configure a GPIO pin for output, use the Configure_Output procedure:

STM32.GPIO.Configure_Output (Pin => (STM32.PA, 1));

Set the pin state using:

STM32.GPIO.Set_Output (Pin => (STM32.PA, 1), Value => 0);  -- Clear pin
STM32.GPIO.Set_Output (Pin => (STM32.PA, 1), Value => 1);  -- Set pin

For input pins, configure them as interrupt sources and optionally enable pull-up or pull-down resistors:

STM32.GPIO.Configure_Interrupt (Pin => (STM32.PA, 1));  -- No pull-up/down resistors
STM32.GPIO.Configure_Interrupt (Pin => (STM32.PA, 1), Pull_Up => True);
STM32.GPIO.Configure_Interrupt (Pin => (STM32.PA, 1), Pull_Down => True);

Don't forget to clear the interrupt flag when handling an interrupt:

STM32.GPIO.Clear_Interrupt (Pin => (STM32.PA, 1));

The library supports USART 1, 2, 3, 6, and UART 4, 5. To use UART/USART, with the corresponding package, declare a device object, and configure it with TX/RX pins and a baud rate. Define an interrupt priority for the protected object.

with STM32.UART.USART_1;

procedure Main is
   package USART_1 is new STM32.UART.USART_1 (Priority => 241);
begin
   USART_1.Configure
     (TX    => (STM32.PA, 9),
      RX    => (STM32.PA, 10),
      Speed => 115_200);
end Main;

Use Start_Reading to initiate reading and Start_Writing for writing. The library leverages the A0B.Callbacks crate for callbacks.

with Ada.Synchronous_Task_Control;
with A0B.Callbacks.Generic_Subprogram;
with STM32.UART.USART_1;

procedure Main is
   package Suspension_Object_Callbacks is new
     A0B.Callbacks.Generic_Subprogram
       (Ada.Synchronous_Task_Control.Suspension_Object,
        Ada.Synchronous_Task_Control.Set_True);

   package USART_1 is new STM32.UART.USART_1 (Priority => 241);

   Buffer  : String (1 .. 8);
   Signal  : aliased Ada.Synchronous_Task_Control.Suspension_Object;
   Done    : constant A0B.Callbacks.Callback :=
     Suspension_Object_Callbacks.Create_Callback (Signal);
begin
   USART_1.Configure
     (TX    => (STM32.PA, 9),
      RX    => (STM32.PA, 10),
      Speed => 115_200);

   loop
      USART_1.Start_Reading
        (Buffer'Address, Buffer'Length, Done);

      Ada.Synchronous_Task_Control.Suspend_Until_True (Signal);

      -- Process Buffer here
   end loop;
end Main;

Configure an I2C device by providing SDA, SCL pins, and the speed:

with STM32.I2C.I2C_1;

procedure Main is
   package I2C_1 is new STM32.I2C.I2C_1 (Priority => 241);
begin
   I2C_1.Configure
     (SDA => (STM32.PB, 7),
      SCL => (STM32.PB, 8),
      Speed => 400_000);
end Main;

Use Start_Data_Exchange to initiate transfers. The transfer can read data from the slave, write data to the slave or write some data and then read as a single transaction enclosed in start/stop condition signals.

I2C_1.Start_Data_Exchange
  (Slave    => 16#1E#,         --  Slave address 0 .. 0x7F
   Buffer   => Buffer'Address, --  Buffer to read/write
   Write    => 1,              --  Number of bytes to write
   Read     => Buffer'Length,  --  Number of bytes to read
   Callback => Done);

The callback is called when the transfer is complete.

Configure an SPI device by specifying SCK, MISO, MOSI pins, and the speed:

SPI_1.Configure
  (SCK   => (STM32.PB, 3),
   MISO  => (STM32.PB, 4),
   MOSI  => (STM32.PB, 5),
   Speed => 2_800_000);  --  2.8 MHz

Several SPI devices can be connected to the same SPI bus. A specific device is activated by a dedicated pin usually called CS (Chip Select). SPI transfers are bidirectional. The user provides data to write in the buffer. When the transfer is complete the buffer is filled with read data.

Initiate transfers using Start_Data_Exchange:

SPI_1.Start_Data_Exchange
  (CS       => (STM32.PB, 6),
   Buffer   => Buffer'Address,
   Size     => Buffer'Length,
   Callback => Done);

The callback is called when the transfer is complete.

A timer can be configured to generate a PWM (pulse width modulation) signal. To configure a timer provide a pin to which the PWM signal will be output and a base frequency.

TIM_3.Configure_PWM
  (Pin   => (STM32.PC, 8),
   Speed => 1_000_000);  -- 1 MHz (1µs per tick)

Start PWM signal generation with Start_PWM providing

TIM_3.Start_PWM
  (Period => 30_000,  -- 30 ms = 30_000 * 1µs
   Duty   => 600,     -- 600 µs = 600 * 1µs
   Done   => Done);

The timer with DMA support can be configured by passing it a pin for each active channel, the base frequency, and the period and duty values in pulses of this base frequency. For example

TIM_3.Configure_PWM
  (Pins   =>
    (1 => (STM32.PA, 6),  --  Channel 1
     2 => (STM32.PC, 7)), --  Channel 2
   Speed  => 1_000_000,   -- 1 MHz (1µs per tick)
   Period => 30_000,      -- 30 ms
   Duty   => 600);        -- 600 µs

Now you can start continuous generation of the PWM signal in three different ways.

To stop generation call Stop.

You can get unique identifier of the device using UID and UID_Image functions. They return the same value, but use different types (Unsigned_64 and String (1 .. 8)).

Put_Line (STM32.UIDs.UID_Image);

Procedures for flash memory include:

Note. On STM32F407 the code can't be executed from flash memory while flash is being written/erased. On STM32F429 the code can be executed from one flash memory bank while another is being written/erased.

STM32.Flash.Unlock;

STM32.Flash.Erase_Sector
  (Address => System'To_Address (16#0800_0000#),
   Size    => Sector_Size,
   Done    => Done);

-- Wait for the sector to erase, then write:
for J in 1 .. Sector_Size loop
   STM32.Flash.Programming;
   -- Write a word to 0x800_0000 + J - 1
end loop;

STM32.Flash.Lock;
Flexible static memory controller (FSMC)

This component of STM32F40x/41x processors allows for the management of static memory, flash memory, and PC Cards. Unlike the FMC in more advanced MCU models, dynamic memory is not supported. Each type of memory has its address bank. The controller offers flexible settings for various operating modes. For instance, extended modes can have different delays set for read and write operations. It is recommended to refer to the STM32 Reference Manual (RM0090) for a detailed description of possible modes and corresponding settings.

Example: Configuring Bank_1 for ILI9341 LCD controller:

STM32.FSMC.Configure
  (Bank_1 =>
     (1 =>  --  ILI9341 is connected to sub-bank 1
        (Is_Set => True,
         Value  =>
           (Write_Enable  => True,
            Bus_Width     => STM32.FSMC.Half_Word,
            Memory_Type   => STM32.FSMC.SRAM,
            Bus_Turn      => 15,  --  90ns
            Data_Setup    => 57, --  342ns
            Address_Setup => 0,
            Extended      =>
              (STM32.FSMC.Mode_A,
               Write_Bus_Turn      => 3,  --  18ns
               Write_Data_Setup    => 2,  --  12ns
               Write_Address_Setup => 0),
            others        => <>)),
      others => <>));

@MaximReznik

Contributions are welcome! Feel free to submit a pull request.

This project is licensed under the Apache 2.0 License with LLVM Exceptions. See the LICENSES files for details.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4