Skip to content

Commit

Permalink
Add base project and implementations for STM32F 0, 1, 4 MCU
Browse files Browse the repository at this point in the history
  • Loading branch information
yh-sb committed Nov 18, 2024
1 parent 563d3c5 commit 8b53006
Show file tree
Hide file tree
Showing 1,344 changed files with 1,203,366 additions and 675 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/build*/
/.xmake/
71 changes: 71 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
cmake_minimum_required(VERSION 3.15)

find_program(CMAKE_ASM_COMPILER NAMES arm-none-eabi-gcc)
find_program(CMAKE_C_COMPILER NAMES arm-none-eabi-gcc)
find_program(CMAKE_CXX_COMPILER NAMES arm-none-eabi-g++)
find_program(CMAKE_LINKER NAMES arm-none-eabi-g++)
find_program(CMAKE_OBJCOPY NAMES arm-none-eabi-objcopy)
find_program(CMAKE_SIZE NAMES arm-none-eabi-size)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

project(stm32f4 C CXX ASM)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 20)

add_compile_options(
-mcpu=cortex-m4
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
-mthumb
-ffunction-sections
-fdata-sections
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>
$<$<COMPILE_LANGUAGE:CXX>:-fno-threadsafe-statics>
$<$<COMPILE_LANGUAGE:CXX>:-fno-use-cxa-atexit>
)

add_link_options(
-mcpu=cortex-m4
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
-Wl,--gc-sections
-specs=nano.specs
-specs=nosys.specs
-Wl,-Map=${CMAKE_PROJECT_NAME}.map,--cref
-T${CMAKE_CURRENT_SOURCE_DIR}/periph/stm32f4/CMSIS/Device/ST/STM32F4xx/Source/linker/STM32F407VGTx_FLASH.ld
)

add_compile_definitions(STM32F407xx)

add_subdirectory(periph)
add_subdirectory(periph/stm32f4)
add_subdirectory(drivers)

set(FREERTOS_PORT GCC_ARM_CM4F CACHE STRING "")
add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM INTERFACE periph/stm32f4/include)
add_subdirectory(third_party/FreeRTOS-Kernel)

add_subdirectory(third_party/printf)

add_executable(${CMAKE_PROJECT_NAME}
main.cpp
periph/stm32f4/src/FreeRTOSHooks.c
)

target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
periph
periph_stm32f4
drivers
freertos_kernel
)

set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES SUFFIX ".elf")
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_SIZE} ${CMAKE_PROJECT_NAME}.elf
COMMAND ${CMAKE_OBJCOPY} -O binary ${CMAKE_PROJECT_NAME}.elf "${CMAKE_PROJECT_NAME}.bin"
)
695 changes: 21 additions & 674 deletions LICENSE

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# mcu-cpp

[![Build](https://github.com/yh-sb/mcu-cpp/actions/workflows/build.yml/badge.svg)](https://github.com/yh-sb/mcu-cpp/actions/workflows/build.yml)

One C++ project for different microcontrollers types

See [examples](examples/).

## How to build
```bash
git clone --recursive https://github.com/yh-sb/mcu-cpp.git

# In Windows:
.\build.ps1

# In Linux:
./build.sh
```

## Requirements
* [GNU Arm Embedded Toolchain](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads)
* [CMake](https://cmake.org/download)
* [Ninja](https://ninja-build.org)
* [JLink](https://www.segger.com/downloads/jlink) for flashing and debugging
6 changes: 6 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
$ErrorActionPreference = "Stop"

$build_type = "Debug"

& 'cmake' . -Bbuild -G Ninja -DCMAKE_BUILD_TYPE=Debug
& 'cmake' --build build -j
12 changes: 12 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

set -e

srcs=$(git ls-files '*.c' '*.cc' '*.cpp' '*.cxx' '*.c++' '*.h' '*.hpp' '*.hh')
srcs=${srcs//$'\n'/ }

GREEN='\033[0;32m'
NC='\033[0m'

echo -e "${GREEN}clang-tidy -p build/compile_commands.json $srcs${NC}"
clang-tidy -p build/compile_commands.json $srcs
26 changes: 26 additions & 0 deletions drivers/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
add_library(drivers STATIC
src/dataflash.cpp
src/dht.cpp
src/gpio_pin_debouncer.cpp
src/ds18b20.cpp
src/encoder.cpp
src/hd44780.cpp
src/nrf24l01.cpp
src/onewire.cpp
src/sd.cpp
src/sd_spi.cpp
src/singlewire.cpp
)

target_include_directories(drivers
PUBLIC
include
)

target_link_libraries(drivers
PUBLIC
periph
freertos_kernel
PRIVATE
printf
)
235 changes: 235 additions & 0 deletions drivers/include/drivers/dataflash.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
#pragma once

#include "periph/gpio.hpp"
#include "periph/spi.hpp"
#include "FreeRTOS.h"
#include "semphr.h"

namespace drv
{
class dataflash
{
public:
enum class res : int8_t
{
ok = 0,
spi_error = -1,
erase_program_error = -2,
unsupported_chip = -3,
no_response = -4
};

enum class page_size : uint8_t
{
// Standard DataFlash page size: 264, 528, 1056 or 2112 bytes
dataflash,

// "power of 2" (binary) binary page size: 256, 512, 1024 or 2048 bytes
pow_2
};

dataflash(periph::spi &spi, periph::gpio &cs, periph::gpio *wp = nullptr,
periph::gpio *rst = nullptr);
~dataflash();

enum res init(enum page_size page_size = page_size::dataflash);

struct info_t
{
uint16_t page_size;
uint16_t pages;
};
info_t info() { return _info; }

enum res read(void *buff, uint16_t page, uint16_t pages = 1);
enum res write(void *buff, uint16_t page, uint16_t pages = 1);
enum res erase(uint16_t page, uint16_t pages = 1);

enum class density : uint8_t
{
_1_mbit = 2,
_2_mbit = 3,
_4_mbit = 4,
_8_mbit = 5,
_16_mbit = 6,
_32_mbit = 7,
_64_mbit = 8,
_128_mbit = 9,
_256_mbit = 10,
_512_mbit = 11
};
enum class family : uint8_t
{
AT45DXXX = 1,
AT26DFXXX = 2,
AT25F_AT25FSXXX = 3
};
#pragma pack(push, 1)
/* Based on JEDEC publication 106 (JEP106), Manufacturer ID data can be
comprised of any number of bytes. Some manufacturers may have
Manufacturer ID codes that are two, three or even four bytes long with
the first byte(s) in the sequence being 7FH. A system should detect code
7FH as a "Continuation Code" and continue to read Manufacturer ID bytes.
The first non-7FH byte would signify the last byte of Manufacturer ID
data. For Atmel (and some other manufacturers), the Manufacturer ID data
is comprised of only one byte. */
//uint8_t jedec_continuation_number;

struct jedec_t
{
uint8_t manufacturer_id:8; // JEDEC Assigned Code
struct
{
density density_code:5;
family family_code:3;
uint8_t product_vers_code:5;
uint8_t sub_code:3;
} dev_id;
/* Indicate number of additional bytes with extended info. As
indicated in the JEDEC Standard, reading the EDI String Length and
any subsequent data is optional. */
uint8_t extended_dev_info_len:8;
};
#pragma pack(pop)

enum res jedec(jedec_t &jedec);

private:
/* 0 bit allways equal to 0
3:1 bits are significant
density in Mbits for <= 64 MBit dataflash:
2^(significant_bits - 1)
*/
enum density_code_t
{
DENSITY_CODE_1_MBIT = (1 << 1) | 0b0001,
DENSITY_CODE_2_MBIT = (2 << 1) | 0b0001,
DENSITY_CODE_4_MBIT = (3 << 1) | 0b0001,
DENSITY_CODE_8_MBIT = (4 << 1) | 0b0001,
DENSITY_CODE_16_MBIT = (5 << 1) | 0b0001,
DENSITY_CODE_32_MBIT = (6 << 1) | 0b0001,
DENSITY_CODE_64_MBIT = (7 << 1) | 0b0001,
DENSITY_CODE_128_MBIT = 4,
DENSITY_CODE_256_MBIT = 6,
DENSITY_CODE_512_MBIT = 8
};

#pragma pack(push, 1)
struct status_t
{
// ----------- 1-st byte of status register
enum page_size page_size:1;
bool sector_protection:1;
density_code_t density_code:4;

/* 0 - Main memory page data matches buffer data
1 - Main memory page data does not match buffer data */
bool compare_result:1;
bool ready:1;

// ----------- 2-nd byte of status register (optional)
/* 0 - No sectors are erase suspended
1 - A sector is erase suspended */
bool erase_suspend:1;

/* 0 - No program operation has been suspended while using Buffer 1
1 - A sector is program suspended while using Buffer 1
*/
bool program_suspend_status_buff_1:1;

/* 0 - No program operation has been suspended while using Buffer 2
1 - A sector is program suspended while using Buffer 2 */
bool program_suspend_status_buff_2:1;

/* 0 - Sector Lockdown command is disabled
1 - Sector Lockdown command is enabled */
bool sector_lockdown:1;

bool reserved2:1;
bool erase_program_error:1;
bool reserved1:1;

/* 0 - Device is busy with an internal operation
1 - Device is ready */
bool ready2:1;
};
#pragma pack(pop)
struct args
{
args() {};
args(uint16_t page, uint16_t byte, info_t info);
args(uint8_t arg1, uint8_t arg2, uint8_t arg3);

uint8_t arg[4];

// May equal to 4 if chip size >= 128 MBit, otherwise equal to 3
uint8_t size;
};

periph::spi &spi;
periph::gpio &cs;
periph::gpio *wp, *rst;
SemaphoreHandle_t api_lock;
info_t _info;

enum res read_status(status_t &status);
bool is_status_valid(const status_t &status);
bool is_jedec_valid(const jedec_t &jedec);
info_t get_info(density_code_t density_code, enum page_size page_size);
density_code_t get_density_code(info_t &info);

enum class cmd : uint8_t
{
// Read commands
CONTINUOUS_ARRAY_READ = 0xE8, // Legacy command
CONTINUOUS_ARRAY_READ_HI_FREQ = 0x0B,
CONTINUOUS_ARRAY_READ_LOW_FREQ = 0x03,

MAIN_MEMORY_PAGE_READ = 0xD2,
BUFFER1_READ = 0xD4,
BUFFER2_READ = 0xD6,
STATUS_REG_READ = 0xD7,

SECURITY_REG_READ = 0x77, // Present since "D" family
SECURITY_REG_WRITE = 0x9A, // Present since "D" family

// Supported only by new AT45DBxxxD serial (unlike AT45DBxxxB)
READ_MANUFACTURER_AND_DEVICE_ID = 0x9F,

// Program and erase commands
BUFFER1_WRITE = 0x84,
BUFFER2_WRITE = 0x87,
BUFFER1_TO_MAIN_MEMORY_PAGE_PROGRAM_WITH_BUILTIN_ERASE = 0x83,
BUFFER2_TO_MAIN_MEMORY_PAGE_PROGRAM_WITH_BUILTIN_ERASE = 0x86,
BUFFER1_TO_MAIN_MEMORY_PAGE_PROGRAM_WITHOT_BUILTIN_ERASE = 0x88,
BUFFER2_TO_MAIN_MEMORY_PAGE_PROGRAM_WITHOT_BUILTIN_ERASE = 0x89,
PAGE_ERASE = 0x81,
BLOCK_ERASE = 0x50,
MAIN_MEMORY_PAGE_PROGRAM_THROUGH_BUFFER1 = 0x82,
MAIN_MEMORY_PAGE_PROGRAM_THROUGH_BUFFER2 = 0x85,
SECTOR_ERASE = 0x7C, // Present since "D" family

// Additional commands
MAIN_MEMORY_PAGE_TO_BUFFER1_TRANSFER = 0x53,
MAIN_MEMORY_PAGE_TO_BUFFER2_TRANSFER = 0x55,
MAIN_MEMORY_PAGE_TO_BUFFER1_COMPARE = 0x60,
MAIN_MEMORY_PAGE_TO_BUFFER2_COMPARE = 0x61,
AUTO_PAGE_REWRITE_THROUGH_BUFFER1 = 0x58,
AUTO_PAGE_REWRITE_THROUGH_BUFFER2 = 0x59,

ENTER_DEEP_POWER_DOWN = 0xB9, // Present since "D" family
EXIT_DEEP_POWER_DOWN = 0xAB, // Present since "D" family
};
enum res cmd(enum cmd cmd, args args, uint32_t timeout);
enum res cmd_with_write(enum cmd cmd, args args, void *buff, size_t size,
uint32_t timeout);
enum res cmd_with_read(enum cmd cmd, args args, void *buff, size_t size,
uint8_t dummy_bytes);

enum res wait_ready(uint32_t timeout_ms, status_t *status = nullptr);
enum res set_page_size(enum page_size page_size);
uint32_t get_timeout(enum cmd cmd, info_t &info);
uint32_t get_chip_erase_timeout(info_t &info);
};
}
Loading

0 comments on commit 8b53006

Please sign in to comment.