Board Support Package for the Adafruit Feather STM32F405 Board
Intro
The board support package for the Adafruit Feather STM32F405 Board is restricted to the J1 and J3 pin header and the onboard LEDs and switches (buttons). The STM32F405 has much more capabilities then 11 digital I/O pins, 6 analog input pins, UART, SPI, and I2C interfaces. But if you want to use the more advanced features you can use the CubeMX to create source code for the internal peripherals. This project wants to show how to use the Cube Ecosystem for a Forth system (or vice versa) and can't implement all features and possibilities the STM32F405 has. It is a good starting point for your project.

Overview

  • microSD and internal Flash mass storage for blocks and FAT filesystem.
  • Digital and analog pins
    • LEDs: LED1 (red), NeoPixel (RGB)
    • Digital port pins: D0 to D15 (D8 NeoPixel, internal)
    • Analog port pins: A0 to A6 (A6 battery voltage, internal)
    • PWM:
      • TIM3: D5, D6
      • TIM4: D9, D10, D14, D15
    • Input capture TIM2: A1, D0, D1
    • Output compare TIM1: D2, D3, D4
    • EXTI: D11, D12, D13
  • UART: D0 RX, D1 TX
  • SPI: J1.4 MOSI, J1.5 MISO, J1.6 SCK (e.g. for display, memory)
  • I2C: D14 SDA, D15 SCL (external peripherals e.g. pressure)

  • OLED Feather Wing
    • Switches: SW1 (button A, D5), SW2 (button B, D6), SW3 (button C, D9)
    • I2C: D14 SDA, D15 SCL

Defaults: Digital port pins D1, D5, D6, D9 to D13 are inputs; D0 (UART_RX) is input with 100 kOhm pull-up resistor; D14 (SDA) and D15 (SCL) are open drain outputs with 10 kOhm pull-up resistors; D5, D6, and D9 with internal pull-ups.

Board Support Words

led1!        ( n -- )    sets LED1 (red)
led1@        ( -- n )    gets LED1 (red)

switch1?     ( -- n )    gets switch1, closed=TRUE
switch2?     ( -- n )    gets switch2, closed=TRUE
switch3?     ( -- n )    gets switch3, closed=TRUE

dport!       ( n -- )    sets the digital output port (D0=bit0 .. D15=bit15).
dport@       ( -- n )    gets the digital input/output port (D0=bit0 .. D15=bit15).
dpin!        ( n a -- )  sets the digital output port pin (D0=0 .. D15=15)
dpin@        ( a -- n )  gets the digital input/output port pin 
dmod         ( u a -- )  sets the pin mode: 0 in, 1 in pull-up, 2 in pull-down, 3 out push pull, 4 out open drain, 
                                            5 out push pull PWM, 6 input capture, 7 output compare, 8 I2C

EXTImod      ( u a -- )  Sets for pin a (D2, D4, D7, D10) the EXTI mode u: 0 rising, 1 falling, 2 both edges, 3 none
EXTIwait     ( u a -- )  Wait for EXTI interrupt on pin a (D2, D4, D7, D10), timeout u in [ms]

pwmpin!      ( u a -- )  sets the digital output port pin a (D3=3, D6=6, D9=9) to a PWM value u (0..1000). Default frequency is 1 kHz, TIMER1
pwmprescale  ( u --  )   Sets the PWM prescale for TIMER1. 32 kHz / prescale, default 32 -> PWM frequency 1 kHz

ICOCprescale ( u -- )    Sets the input capture / output compare prescale for TIMER2. default 32 -> 32 MHz / 32 = 1 MHz, timer resolution 1 us
ICOCperiod!  ( u -- )    Sets the input capture / output compare (TIMER2) period. default $FFFFFFFF (4'294'967'295). 
                         When the up counter reaches the period, the counter is set to 0. 
                         For prescale 32 the maximum time is about 1 h 11 m
ICOCcount!   ( -- u )    Sets the input capture / output compare counter for TIMER2
ICOCcount@   ( u -- )    Gets the input capture / output compare counter for TIMER2
ICOCstart    ( -- )      Starts the ICOC period
ICOCstop     ( -- )      Stops the ICOC period
OCmod        ( u a -- )  Sets for pin a (D0, D1, D5) the Output Compare mode u: 0 frozen, 1 active level on match, 2 inactive level on match, 
                            3 toggle on match, 4 forced active, 5 forced inactive
    
OCstart      ( u a -- )  Starts the output compare mode for pin a with pulse u
OCstop       ( a -- )    Stops output compare for pin a
ICstart      ( u -- )    Starts input capture u: 0 rising edge, 1 falling edge, 2 both edges
ICstop       ( -- )      Stops input capture

waitperiod   ( -- )      wait for the end of the TIMER2 period
OCwait       ( a -- )    wait for the end of output capture on pin a
ICwait       ( u -- u )  wait for the end of input capture with timeout u, returns counter u

apin@        ( a -- u )  gets the analog input port pin (A0 .. A5). Returns a 12 bit value (0..4095) 

Using the Digital Port Pins (Input and Output)

This example is very similar to the McForth#Knight_Rider program. dport! and dport@ set and get all 16 digital pins (D0 to D15) at once. You have to press the SW1 push button til D0 is set to cancel the operation.

3 0 dmod   \ set D0 to Output
3 1 dmod   \ set D1 to Output
3 3 dmod   \ set D3 to Output
3 5 dmod   \ set D5 to Output
3 6 dmod   \ set D6 to Output

: left ( -- ) 
  7 0 do  
    dport@ shl dport!  
    100 osDelay drop  
  loop 
;
: right ( -- )
  7 0 do  
    dport@ shr dport!
    100 osDelay drop  
  loop 
;
: knightrider ( -- )
  1 dport! 
  begin 
    left right 
    switch1? \ or key?
  until 
  0 dport!
;

Single port pin variant (no side effects on port pins D8 to D15):

: left ( -- ) 
  7 0 do
    1 i dpin! 
    100 osDelay drop  
    0 i dpin!
  loop 
;
: right ( -- )
  8 1 do  
    1 8 i - dpin! 
    100 osDelay drop  
    0 8 i - dpin!
  loop 
;
: knigthrider ( -- )
  begin 
    left right 
    switch1? 
  until 
  0 0 dpin!
;

Using the ADC (Analog Input Pins)

apin@ ( a -- u ) returns the ADC value (12 bit, 0 .. 4095) from one of the analog pins A0 to A5 (0 .. 5). Here I use the A0 to control the delay.

: left ( -- ) 
  7 0 do
    1 i dpin! 
    0 apin@ 10 / osDelay drop  \ delay depends on A0
    0 i dpin!
  loop 
;
: right ( -- )
  8 1 do  
    1 8 i - dpin! 
    0 apin@ 10 / osDelay drop  \ delay depends on A0
    0 8 i - dpin!
  loop 
;

To get an idea how fast the ADC, RTOS, and the Forth program are. The left or right word takes about 125 us, the knightrider loop about 50 us (no osDelay). Pretty fast for my opinion.

CH1 yellow: D0 pin
CH2 blue: D1 pin
TEK0012.png

Using the PWM (Analog Output Pins)

Only three port pins are supported so far. The 16 bit TIMER1 is used for the timebase, time resolution is 1 us (32 MHz SysClk divided by 32). The PWM scale is from 0 (0 % duty cycle) to 1000 (100 % duty cycle), this results in a PWM frequency of 1 kHz. If you need higher PWM frequencies, decrease the divider and/or the scale.

PWM port pins: D6 (TIM1CH1), D9 (TIM1CH2), D3 (TIM1CH3)

Simple test program to set brightness of a LED on pin D3 with a potentiometer on A0. Default PWM frequency is 1 kHz (prescaler set to 32). You can set the prescale with the word pwmprescale from 32 kHz (value 1) down to 0.5 Hz (64000).

5 3 dmod   \ set D3 to PWM

: pwm ( -- )
  begin 
    0 apin@  4 /  3 pwmpin!
    10 osDelay drop
    switch1? 
  until 
;

Using Input Capture and Output Compare

Time Base

Default timer resolution is 1 us. The 32 bit TIMER2 is used as time base for Input Capture / Output Compare. For a 5 s period 5'000'000 cycles are needed. All channels (input capture / output compare) use the same time base.

: period ( -- )
  5000000 ICOCperiod! \ 5 s period
  ICOCstart
  begin
     waitperiod
     cr .time
  key? until
  key drop 
;

Output Compare

: oc-toggle ( -- )
  5000000 ICOCperiod! \ 5 s period
  ICOCstart
  3 0 OCmod  1000000 0 OCstart \ toggle D0 after 1 s
  3 1 OCmod  2000000 1 OCstart \ toggle D1 after 2 s
  3 5 OCmod  3000000 5 OCstart \ toggle D5 after 3 s 
  begin
     waitperiod
     cr .time
  key? until
  key drop 
;

When you abort (hit any key) the program, the timer still runs and controls the port pins. To stop the port pins:

0 OCstop  1 OCstop  5 OCstop

Or change the prescale to make it faster or slower:

1 ICOCprescale

Input Capture

This sample program measures the time between the edges on port A2. if no event occurs within 2 seconds, "timeout" is issued. Hit any key to abort program.

: ic-test ( -- )
  6 2 dmod \ input capture on A2
  ICOCstart
  2 ICstart  \ both edges
  ICOCcount@ ( -- count )
  begin
    2000 \ 2 s timeout
    ICwait ( -- old-capture capture ) 
    cr
    dup 0= if
      ." timeout" drop
    else 
      dup rot ( -- capture capture old-capture )
      - 1000 / . ." ms"
    then
  key? until
  key drop
  drop
  ICstop
;

Using EXTI line

: exti-test ( -- )
  2 2 EXTImod \ both edges on D2
  begin
    2000 2 EXTIwait \ wait for edge on D2 with 2 s timeout
    cr
    0= if
      2 dpin@ if
        ." rising edge"
      else
        ." falling edge"
      then 
    else
      ." timeout"
    then
  key? until
  key drop
;

Using the Digital Port Pins (Input and Output)

Digital Pins

BOOT0 / JP1.1

RESET/ JP1.16

UART_RX / GPIO D0 / PB11 / JP1.3

  • Receive (input) pin for Serial3. Hardware USART3
  • PWM out on TIM2_CH4
  • Alternate uses: I2C2 SDA

UART_TX / GPIO D1 / PB10 / JP1.2

  • Transmit (output) pin for Serial3. Hardware USART3
  • PWM out on TIM2_CH3
  • Alternate uses: I2C2 SCL

SCK / GPIO23 D2 / PB13 / JP1.6

  • The SPI bus clock pin. Hardware SPI2
  • PWM out on TIM1_CH1N
  • Alternate uses: I2S2 Clock, CAN2 TX

MISO / GPIO24 D3 / PB14 / JP1.4

  • The SPI bus clock pin. Hardware SPI2
  • PWM out on TIM1_CH2N
  • Alternate uses: I2S2ext SD

MOSI / GPIO25 D4 / PB15 / JP1.5

  • The SPI bus clock pin. Hardware SPI2
  • PWM out on TIM1_CH3N
  • Alternate uses: I2S2 SD

GPIO D5 / Button C / PC7 / JP3.10

  • PWM out on TIM3_CH2
  • Alternate uses: USART6 RX, I2S3 MCK

GPIO D6 / Button B / PC6 / JP3.9

  • PWM out on TIM3_CH1
  • Alternate uses: USART6 TX, I2S2 MCK

NeoPixel / GPIO D8 / PC0 (internal)

GPIO D9 / Button A / PB8 / JP3.8

  • PWM out on TIM4_CH3
  • Alternate uses: CAN1 RX, I2C1 SCL

GPIO D10 / PB9 / JP3.7

  • PWM out on TIM4_CH4
  • Alternate uses: CAN1 TX, I2C1 SDA

GPIO D11 / PC3 / JP3.6

  • No PWM
  • Alternate uses: I2S2 SD, SPI2 MOSI

GPIO D12 / PC2 / JP3.5

  • No PWM
  • Alternate uses: I2S2ext SD, SPI2 MISO

GPIO D13 / red LED / PC1 / JP3.4

  • Connected to the red LED next to the USB jack
  • No PWM or alternate uses

SDA / GPIO D14 / PB7 / JP3.12

  • The I2C (Wire) data pin, this has a 10K pullup to 3.3V. Hardware I2C1
  • PWM out on TIM4_CH2
  • Alternate uses: USART1 RX

SCL / GPIO D15 / PB6 / JP3.11

  • the I2C (Wire) clock pin, this has a 10K pullup to 3.3V. Hardware I2C1
  • PWM out on TIM4_CH1
  • Alternate uses: USART1 TX, CAN2 TX

Analog Pins

A0 / GPIO 16 / PA4 / JP1.12

  • This pin is analog input A0 (ADC12 IN4)
  • Analog output (DAC OUT1) due to having a DAC (digital-to-analog converter). You can set the raw voltage to anything from 0 to 3.3V, unlike PWM outputs this is a true analog output
  • No PWM or alternate uses

A1 / GPIO 17 / PA5 / JP1.11

  • This pin is analog input A1 (ADC12 IN5)
  • Analog output (DAC OUT2) due to having a DAC (digital-to-analog converter). This is the second DAC, and is 'independent' of A0. You can set the raw voltage to anything from 0 to 3.3V, unlike PWM outputs this is a true analog output.
  • Alternative uses: SPI1 SCK

A2 / GPIO18 / PA6 / JP1.10

  • This pin is analog input A2 (ADC12 IN6)
  • Alternative uses: SPI1 MISO
  • PWM out on TIM3_CH1

A3 / GPIO19 / PA7 / JP1.9

  • This pin is analog input A3 (ADC12 IN7)
  • Alternative uses: SPI1 MOSI
  • PWM out on TIM3_CH2

A4 / GPIO20 / PC4 / JP1.8

  • This pin is analog input A4 (ADC12 IN14)

A5 / GPIO21 / PC5 / JP1.7

  • This pin is analog input A5 (ADC12 IN15)

A6 / PA3 (internal)

  • is also available for reading the battery voltage, see the Power Management page for instructions how

SD Card / SDIO Pins

SDIO_D0 / SD_MISO / PC8 (internal)

SDIO_D1 / PC9 (internal)

SDIO_D2 / PC10 (internal)

SDIO_D3 / SD_CS / PC11 (internal)

SDIO_CLK / SD_CLK / PC12 (internal)

SDIO_CMD / SD_MOSI / PD2 (internal)

SD_DETECT / PB12 (internal)

SPI Flash

FLASH_SCK / PB3 (internal)

FLASH_MISO / PB4 (internal)

FLASH_MOSI / PB5 (internal)

Qwiic / STEMMA QT port

USB

USB_DP / PA12

USB_DM / PA11

-- Peter Schmid - 2020-04-11

Creative Commons License
This work by Peter Schmid is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Topic attachments
I Attachment History Action Size Date Who Comment
PNGpng TEK0012.png r1 manage 3.6 K 2020-04-16 - 14:22 PeterSchmid  
JPEGjpg feather-stm32f405-head.jpg r1 manage 293.3 K 2021-03-02 - 11:11 PeterSchmid  
Edit | Attach | Watch | Print version | History: r32 < r31 < r30 < r29 < r28 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r32 - 2021-03-08 - PeterSchmid
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback