We will install gcc in an upper directory, so that we can reuse it in all our projects
- create the dir:
mkdir stm32 && cd stm32
- go to the download page and find the latest version
wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
tar -xvf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
ln -s gcc-arm-none-eabi-10.3-2021.10 gcc
- create an
.envrc
file
echo 'export PATH=$PATH:`realpath $(pwd)/gcc/bin`' > .envrc
direnv allow
- check it worked
whereis arm-none-eabi-gcc
arm-none-eabi-gcc: /home/fred/work/toto/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc
- Create New project
- Select board
- Start Project (init all peripherials with default)
- Go to the "Project Manager" tab and setup the project name and path
- Set "Toolchain" as "STM32CubeIDE"
- in "Code Generator" select "Copy only necessary library files"
- Go to to generated project
- Create a git repo and add cubemx.cmake as submodule:
git init
git submodule add https://github.com/patrislav1/cubemx.cmake.git
- Create
CMakeLists.txt
(replace usblcd by the name of yout ioc file):
cat << \EOT > CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/cubemx.cmake/arm-gcc.cmake")
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED ON)
include(cubemx.cmake/cubemx.cmake)
project(usblcd)
add_executable(
usblcd
usr/lcd.c
)
# code folder
target_include_directories(usblcd PRIVATE "usr")
cubemx_target(
TARGET usblcd
IOC "${CMAKE_CURRENT_LIST_DIR}/usblcd.ioc"
)
# set the correct target if necessarry (see: ./Drivers/CMSIS/Device/ST/STM32F0xx/Include/stm32f0xx.h)
# target_compile_options(usblcd PRIVATE -DSTM32F030x8)
# warnings
target_compile_options(usblcd PRIVATE
-Wall
-Wextra
-Wno-unused-parameter
-Wshadow
-Wformat=2
-Wstrict-overflow
-fvisibility=hidden
-fno-strict-aliasing
-Werror
)
# debug
# target_compile_options(usblcd PRIVATE -Og -Wall -g -gdwarf-2)
# production
target_compile_options(usblcd PRIVATE
-s
-Os
-DNDEBUG
)
target_compile_definitions(usblcd PRIVATE
USE_FULL_LL_DRIVER
USE_HAL_DRIVER
)
EOT
- Add
.clang-format
cat << \EOT > .clang-format
---
BasedOnStyle: LLVM
ColumnLimit: 0
UseTab: ForIndentation
IndentWidth: 4
TabWidth: 4
AllowShortIfStatementsOnASingleLine: false
IndentAccessModifiers: false
AccessModifierOffset: -4
EmptyLineBeforeAccessModifier: LogicalBlock
EOT
- generate vscode project:
mkdir -p .vscode
cat << \EOT > .vscode/cmake-kits.json
[{
"name": "arm-gcc from CMake Toolchain",
"toolchainFile": "${workspaceRoot}/cubemx.cmake/arm-gcc.cmake"
}]
EOT
cat << \EOT > .vscode/settings.json
{
"editor.formatOnSave": true,
"C_Cpp.formatting": "Disabled",
"clang-format.executable": "/usr/bin/clang-format"
}
EOT
- generate build env:
mkdir -p build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../cubemx.cmake/arm-gcc.cmake ..
- compile:
make
- flash:
make flash
- reset:
make reset
see this reference article: https://community.st.com/s/article/how-to-redirect-the-printf-function-to-a-uart-for-debug-messages
- check virtual com port and connect:
sudo dmesg | grep tty
[994945.768623] cdc_acm 3-1.4:1.2: ttyACM0: USB ACM device
# if set on 8bits including parity (the default value)
screen /dev/ttyACM0 115200
# use Ctrl-a k to exit
# or minicom
minicom --device /dev/ttyACM0
Then leave everything by default and add the following:
/* USER CODE BEGIN Init */
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
/* USER CODE END Init */
/* USER CODE BEGIN PFP */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
/* USER CODE END PFP */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
HAL_Delay(50);
printf("Hello!\n\r");
}
/* USER CODE END 3 */
/* USER CODE BEGIN 4 */
PUTCHAR_PROTOTYPE {
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 4 */