esp8266_deauther: Installation
CH340/340 Treiber für Arduino Boards installieren
STM32duino SysTick
STM32G474RE
SysTick_Config
STM32G071RB
Twice initialization
Code
HAL_Init():SystemCoreClock = 16'000'000 Hz = 16 MHzSystemClock_Config():SystemCoreClock = 64'000'000 Hz = 64 MHz
#ifndef F_CPU #define F_CPU SystemCoreClock #endif
void hw_config_init(void)
{
/* Initialize the HAL */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
}
/* The SystemCoreClock variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 16000000UL;
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
{
[...]
/* Update the SystemCoreClock global variable */
SystemCoreClock = (HAL_RCC_GetSysClockFreq() >> ((AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]) & 0x1FU));
/* Configure the source of time base considering new system clocks settings*/
return HAL_InitTick(uwTickPrio);
}
void noOsSystickHandler() { } // empty
void osSystickHandler() __attribute__((weak, alias("noOsSystickHandler")));
void SysTick_Handler(void)
{
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
osSystickHandler();
}
STM32Cube / STM32duino FreeRTOS
STM32Cube
MOOC – FreeRTOS on STM32 (Playlist)
STM32CubeMX – With Example Work-flow
STM32Cube – Drivers and Middleware for STM32 ARM Cortex-M MCUs
STM32duino
STM32duino FreeRTOS
github.com/stm32duino/STM32FreeRTOS, Real Time Operating System implemented for STM32
Timer
Black Pill: STM32F401CC / STM32F411CE
ST
STM32F401CC, High-performance access line, Arm Cortex-M4 core with DSP and FPU, 256 Kbytes of Flash memory, 84 MHz CPU, ART Accelerator
STM32F411CC, High-performance access line, Arm Cortex-M4 core with DSP and FPU, 256 Kbytes of Flash memory, 100 MHz CPU, ART Accelerator
STM32F411CE, High-performance access line, Arm Cortex-M4 core with DSP and FPU, 512 Kbytes of Flash memory, 100 MHz CPU, ART Accelerator
Schematics
WeAct Black Pill V2.0, STM32F411CEU6
WeAct Black Pill V3.0, STM32F401CEU6
Reference
STM32F103C8, Mainstream Performance line, Arm Cortex-M3 MCU with 64 Kbytes of Flash memory, 72 MHz CPU, motor control, USB and CAN
AliExpress
STM32F103C8T6 ARM STM32 Minimum System Development Board STM32F401 STM32F411 STM32F4 + ST-LINK V2 Simulator Download Programmer
STM32F401CCU6 411CEU6 256KB ROM Development Board V1.2 STM32F4 Learning Board For Arduino ST-Link V2 Simulator Download
STM32duino G0 USART IRQ handler
David Ledger’s uSupply (STM32, C++17)
EEVblog
C++ for the Embedded Programmer
uSupply Firmware Released
Offtopic
STM32 macro for port and pin read and write
Peripheral register access using C Struct’s – part 1
YouTube
C++ for the Embedded Programmer
C/C++ Interrupt Undefined Behavior
GitHub
GitLab
gitlab.com/eevblog/usupply-firmware
gitlab.com/eevblog/usupply-library
gitlab.com/eevblog/usupply-usb
Other Libraries
Digikey Electronics – Getting Started with STM32 and Nucleo
Getting Started with STM32 and Nucleo
Getting Started with STM32 and Nucleo Part 1: Introduction to STM32CubeIDE and Blinky – Digi-Key
Getting Started With STM32 and Nucleo Part 2: How to Use I2C to Read Temperature Sensor TMP102
Getting Started With STM32 and Nucleo Part 3: FreeRTOS – How To Run Multiple Threads w/ CMSIS-RTOS
Getting Started With STM32 and Nucleo Part 4: Working with ADC and DMA – Maker.io
Getting Started with STM32 and Nucleo Part 5: How to Use SPI | Digi-Key Electronics
Getting Started with STM32 and Nucleo Part 6: Timers and Timer Interrupts | Digi-Key Electronics
Programming the Adafruit Feather STM32F405 Express with STM32CubeIDE – Maker.io
STM32duino SPI
STM32duino UART / Serial
STM32duino III. – How to use Serial (USART)
STM32duino Wiki
Welcome to the stm32duino wiki!
API HardwareSerial
PlatformIO
How to use stm32duino build_opt.h in PlatformIO?
How to use stm32duino (official STM32 core) build_opt.h in PlatformIO
Include header files using command line option?
build_flags =
-DENABLE_HWSERIAL3
-DPIN_SERIAL3_RX=PB11
-DPIN_SERIAL3_TX=PB10
or
build_flags =
-include build_opt.h
Variant
ldscript.ld PeripheralPins.c PinNamesVar.h variant.cpp variant.h
#define PC5 0 #define PC4 1 #define PA10 2 [...]
HAL_ADC_MODULE_ENABLED HAL_DAC_MODULE_ENABLED HAL_I2C_MODULE_ENABLED HAL_TIM_MODULE_ENABLED HAL_UART_MODULE_ENABLED HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_UART_TX[] = {
[...]
{PA_5, USART3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART3)},
{PB_2, USART3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART3)},
[...]
^ ^
| |
STM_MODE_INPUT GPIO_NOPULL
STM_MODE_OUTPUT_PP GPIO_PULLUP
STM_MODE_OUTPUT_OD GPIO_PULLDOWN
STM_MODE_ANALOG
STM_MODE_AF_OD => Alternate Function, Open-Drain
STM_MODE_AF_PP => Alternate Function, Push-Pull
#define STM_PIN_DATA(FUNC_OD, PUPD, AFNUM) \
STM_PIN_DEFINE(FUNC_OD, PUPD, AFNUM)
#define STM_PIN_DATA_EXT(FUNC_OD, PUPD, AFNUM, CHANNEL, INVERTED) \
STM_PIN_DEFINE_EXT(FUNC_OD, PUPD, AFNUM, CHANNEL, INVERTED)
Digital
Arduino_Core_STM32—pinMode() implementation analysis
void pinMode(uint32_t ulPin, uint32_t ulMode)
{
PinName p = digitalPinToPinName(ulPin);
if (p != NC) {
[...]
switch (ulMode) {
case INPUT: /* INPUT_FLOATING */
pin_function(p, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
break;
case INPUT_PULLUP:
pin_function(p, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, 0));
break;
case INPUT_PULLDOWN:
pin_function(p, STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLDOWN, 0));
break;
[...]
}
}
}
PinMap_UART_TX
typedef struct {
PinName pin;
void *peripheral;
int function;
} PinMap;
typedef enum {
// Not connected
NC = (int)0xFFFFFFFF,
// Pin name definition
PA_0 = (PortA << 4) + 0x00,
[...]
// Specific pin name define in the variant
#include "PinNamesVar.h"
P_END = NC
} PinName;
extern GPIO_TypeDef *GPIOPort[];
typedef enum {
FirstPort = 0x00,
PortA = FirstPort,
PortB,
#if defined GPIOC_BASE
PortC,
#endif
[...]
PortEND,
LastPort = PortEND - 1
} PortName;
#define MAX_NB_PORT (LastPort-FirstPort+1)
extern const PinName digitalPin[];
extern const uint32_t analogInputPin[];
[...]
#define digitalPinToPinName(p) (((uint32_t)p < NUM_DIGITAL_PINS) ? digitalPin[p] : \
((uint32_t)p >= NUM_ANALOG_FIRST) && ((uint32_t)p <= NUM_ANALOG_LAST) ? \
digitalPin[analogInputPin[p-NUM_ANALOG_FIRST]] : NC)
STM_PIN_DATA()STM_PIN_DATA_EXT()pin_in_pinmap()bool pin_in_pinmap(PinName pin, const PinMap *map)
Looppinmap_peripheral()void *pinmap_peripheral(PinName pin, const PinMap *map)pinmap_pinout()void pinmap_pinout(PinName pin, const PinMap *map)pinmap_pin()PinName pinmap_pin(void *peripheral, const PinMap *map)
./cores/arduino/pins_arduino.h: pin_in_pinmap(digitalPinToPinName(p), PinMap_UART_TX)) ./cores/arduino/stm32/PeripheralPins.h: extern const PinMap PinMap_UART_TX[]; ./libraries/SrcWrapper/src/stm32/uart.c: #define DEBUG_UART pinmap_peripheral(digitalPinToPinName(PIN_SERIAL_TX), PinMap_UART_TX) ./libraries/SrcWrapper/src/stm32/uart.c: USART_TypeDef *uart_tx = pinmap_peripheral(obj->pin_tx, PinMap_UART_TX); ./libraries/SrcWrapper/src/stm32/uart.c: pinmap_pinout(obj->pin_tx, PinMap_UART_TX); ./libraries/SrcWrapper/src/stm32/uart.c: serial_debug.pin_tx = pinmap_pin(DEBUG_UART, PinMap_UART_TX);
Serial3
HAVE_HWSERIAL3ENABLE_HWSERIAL3SERIAL_UART_INSTANCE
[...] extern HardwareSerial Serial3; extern HardwareSerial Serial4; [...]
[...]
#if defined(HAVE_HWSERIAL3)
HardwareSerial Serial3(USART3);
void serialEvent3() __attribute__((weak));
#endif
#if defined(HAVE_HWSERIAL4)
#if defined(USART4)
HardwareSerial Serial4(USART4);
#else
HardwareSerial Serial4(UART4);
#endif
void serialEvent4() __attribute__((weak));
#endif
[...]
// Constructors ////////////////////////////////////////////////////////////////
/* ex. PA0 from #define in variant.h */
HardwareSerial::HardwareSerial(uint32_t _rx, uint32_t _tx)
{
init(digitalPinToPinName(_rx), digitalPinToPinName(_tx));
}
/* ex. PA_0 from enum PinName in PinNames.h*/
HardwareSerial::HardwareSerial(PinName _rx, PinName _tx)
{
init(_rx, _tx);
}
/* ex. peripheral Serial2 (stm32g071xx.h: USART2 => USART2_BASE => 0x40004400) */
HardwareSerial::HardwareSerial(void *peripheral, HalfDuplexMode_t halfDuplex)
{
[...]
/* if pins are defined (variant.h or compiler flag -D), use them, otherwise use from PinMap */
#if defined(Serial) && defined(PIN_SERIAL_TX)
if ((void *)this == (void *)&Serial) {
#if defined(PIN_SERIAL_RX)
setRx(PIN_SERIAL_RX);
#endif
setTx(PIN_SERIAL_TX);
} else
#endif
[...]
#if defined(PIN_SERIAL3_TX) && defined(USART3_BASE)
if (peripheral == USART3) {
#if defined(PIN_SERIAL3_RX)
setRx(PIN_SERIAL3_RX);
#endif
setTx(PIN_SERIAL3_TX);
} else
#endif
[...]
// else get the pins of the first peripheral occurence in PinMap
{
_serial.pin_rx = pinmap_pin(peripheral, PinMap_UART_RX);
_serial.pin_tx = pinmap_pin(peripheral, PinMap_UART_TX);
}
[...]
}
[...]
void HardwareSerial::init(PinName _rx, PinName _tx)
{
[...]
}
/*!< Peripheral declaration */ #define USART2 ((USART_TypeDef *) USART2_BASE) #define USART3 ((USART_TypeDef *) USART3_BASE) #define USART4 ((USART_TypeDef *) USART4_BASE) [...] #define LPUART1 ((USART_TypeDef *) LPUART1_BASE) [...] /*!< APB peripherals */ #define USART2_BASE (APBPERIPH_BASE + 0x00004400UL) #define USART3_BASE (APBPERIPH_BASE + 0x00004800UL) #define USART4_BASE (APBPERIPH_BASE + 0x00004C00UL) [...] #define LPUART1_BASE (APBPERIPH_BASE + 0x00008000UL)
[...]
#if defined(ENABLE_HWSERIAL3)
#if defined(USART3_BASE)
#define HAVE_HWSERIAL3
#endif
#endif
#if defined(ENABLE_HWSERIAL4)
#if defined(USART4_BASE) || defined(UART4_BASE)
#define HAVE_HWSERIAL4
#endif
#endif
[...]
WEAK void serialEventRun(void)
{
[...]
#if defined(HAVE_HWSERIAL3)
if (serialEvent3 && Serial3.available()) {
serialEvent3();
}
#endif
#if defined(HAVE_HWSERIAL4)
if (serialEvent4 && Serial4.available()) {
serialEvent4();
}
#endif
[...]
}
Callstack
size_t HardwareSerial::write(uint8_t c)
{
[...]
if (!serial_tx_active(&_serial)) {
uart_attach_tx_callback(&_serial, _tx_complete_irq);
}
[...]
}
int HardwareSerial::_tx_complete_irq(serial_t *obj)
{
// If interrupts are enabled, there must be more data in the output
// buffer. Send the next byte
obj->tx_tail = (obj->tx_tail + 1) % SERIAL_TX_BUFFER_SIZE;
if (obj->tx_head == obj->tx_tail) {
return -1;
}
return 0;
}
typedef struct serial_s serial_t;
struct serial_s {
/* The 1st 2 members USART_TypeDef *uart
* and UART_HandleTypeDef handle should
* be kept as the first members of this struct
* to have get_serial_obj() function work as expected
*/
USART_TypeDef *uart;
UART_HandleTypeDef handle;
void (*rx_callback)(serial_t *);
int (*tx_callback)(serial_t *);
PinName pin_tx;
PinName pin_rx;
IRQn_Type irq;
uint8_t index;
uint8_t recv;
uint8_t *rx_buff;
uint8_t *tx_buff;
uint16_t rx_tail;
uint16_t tx_head;
volatile uint16_t rx_head;
volatile uint16_t tx_tail;
};
/**
* Begin asynchronous TX transfer.
*
* @param obj : pointer to serial_t structure
* @param callback : function call at the end of transmission
* @retval none
*/
void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *))
{
if (obj == NULL) {
return;
}
obj->tx_callback = callback;
/* Must disable interrupt to prevent handle lock contention */
HAL_NVIC_DisableIRQ(obj->irq);
/* The following function will enable UART_IT_TXE and error interrupts */
HAL_UART_Transmit_IT(uart_handlers[obj->index], &obj->tx_buff[obj->tx_tail], 1);
/* Enable interrupt */
HAL_NVIC_SetPriority(obj->irq, UART_IRQ_PRIO, UART_IRQ_SUBPRIO);
HAL_NVIC_EnableIRQ(obj->irq);
}
/**
* @brief Tx Transfer completed callback
* @param UartHandle pointer on the uart reference
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
serial_t *obj = get_serial_obj(huart);
if (obj && obj->tx_callback(obj) != -1) {
if (HAL_UART_Transmit_IT(huart, &obj->tx_buff[obj->tx_tail], 1) != HAL_OK) {
return;
}
}
}
Rust Programming
Developer Survey
Rust language: Stack Overflow Developer Survey, 22. Juni 2022
Stack Overflow Developer Survey 2023
Stack Overflow Developer Survey 2022
10 Most Loved Programming Languages: Rust, TypeScript, and More, May 29, 2020
Documentation
The Rust Reference
The Rust Programming Language
Asynchronous Programming in Rust
Rust by Example
github.com/rust-lang/rust-by-example
Rust By Practice
Blog
Fearless Concurrency with Rust
Abstraction without overhead: traits in Rust
Virtual Structs Part 1: Where Rust’s enum shines
Virtual Structs Part 2: Classes strike back
Virtual Structs Part 3: Bringing Enums and Structs Together
Unsafe
- the meaning of (un)safety
- unsafe primitives provided by the language and standard library
- techniques for creating safe abstractions with those unsafe primitives
- subtyping and variance
- exception-safety (panic/unwind-safety)
- working with uninitialized memory
- type punning
- concurrency
- interoperating with other languages (FFI)
- optimization tricks
- how constructs lower to compiler/OS/hardware primitives
- how to not make the memory model people angry
- how you’re going to make the memory model people angry
Books
Fullstack Rust – Adding State to Our Web App
Syntax
unit type
Primitive Type unit
What is the purpose of the unit type in Rust?
Option and Result
Module std::option
Module std::result
Understanding Rust Option and Result enums
static
fn spawn<F>(f: F) where F: 'static, ... fn scoped<'a, F>(f: F) -> JoinGuard<'a> where F: 'a, ...
constraint
'static |
no borrowed data is permitted in the closure |
'a |
cannot escape the scope of any data borrowed by the closure |
trait
trait ClickCallback {
fn on_click(&self, x: i64, y: i64);
}
struct Button {
listeners: Vec<Box<ClickCallback>>,
...
}
trait object
- traits are types, but they are “unsized”
- they are only allowed to show up behind a pointer like
Box(which points onto the heap) or&(which can point anywhere) - Static and dynamic dispatch
&ClickCallback |
no borrowed data is permitted in the closure |
Box |
cannot escape the scope of any data borrowed by the closure |
Future trait
The Future Trait
Build an Executor
Tutorials
NICLAS ROSSBERGER
Rust-01: Why am I learning Rust?
Rust-02: The beginning
Rust-03: Improving the simple program
Medium
C++ vs Rust: an async Thread-per-Core story
How to Idiomatically Use Global Variables in Rust
Java
ExecutorService – Waiting for Threads to Finish
Guide to java.util.concurrent.Future
YouTube
Andrew Sharp
Learn Rust Part 1: numbers, variables, types and functions
Learn Rust Part 2: Structs
Learn Rust Part 3: References
Learn Rust Part 4: Mutable References
Learn Rust Part 5: Ownership
Learn Rust Part 6: Borrowing
Learn Rust Part 7: Lifetimes
Learn Rust Part 8: Lifetimes with Structs
Learn Rust Part 9: Constant Items and the Static Lifetime
Learn Rust Part 10: Methods and Associated Functions
Dave Halter
Rust für Python Developers (english) | Swiss Python Summit 2022
github.com/davidhalter/rust-for-python-developers








