This commit is contained in:
Roelandts_Gert
2023-11-13 13:04:01 +01:00
26 changed files with 7496 additions and 610 deletions

22
.gitignore vendored
View File

@@ -31,8 +31,30 @@
*.out *.out
*.app *.app
# Log files
*.log
# Metadata directories
.metadata/
project/.metadata
# Test files
project/Core/Inc/stlogo.h
project/Core/Inc/test_img.h
project/Core/Inc/test_data.h
project/Debug/ project/Debug/
project/.idea/ project/.idea/
project/cmake-build-debug/ project/cmake-build-debug/
project/.settings/
project/.mxproject
project/project.launch
project/Scripts
Scripts/
project/project\ Debug.launch

View File

@@ -21,9 +21,9 @@ This way we can keep the code clean.
[tasks_and_taskowners.md](tasks_and_taskowners.md) [tasks_and_taskowners.md](tasks_and_taskowners.md)
## Style Guide ## Style Guide
To maintain a consistent and clean codebase, follow the [style guide](style_guide.md). This document provides detailed instructions on naming conventions, code structure, and commenting practices. To maintain a consistent and clean codebase, follow the [style guide](docs/style_guide.md). This document provides detailed instructions on naming conventions, code structure, and commenting practices.
Please read the [style_guide.md](style_guide.md) carefully before making contributions. Please read the [style_guide.md](docs/style_guide.md) carefully before making contributions.
### Editor Configuration ### Editor Configuration
@@ -57,4 +57,7 @@ Documentation is placed in the [docs](docs) folder.
If your part needs documentation (e.g. how to use tcp cmd interface), add a markdown file in the above-mentioned folder. If your part needs documentation (e.g. how to use tcp cmd interface), add a markdown file in the above-mentioned folder.
This folder contains the following documents: This folder contains the following documents:
- [llfs.md](docs/llfs.md): Linked List File System
- [logger.md](docs/logger.md): Logging and Debugging Messages - [logger.md](docs/logger.md): Logging and Debugging Messages
- [mkllfs.md](docs/mkllfs.md): Make Linked List File System
- [style_guide.md](docs/style_guide.md): Style Guide

92
docs/lcd_api.md Normal file
View File

@@ -0,0 +1,92 @@
# LCD API
## Introduction
The LCD API can be used to display BMP images or text onto the LCD screen.
At the moment of writing, only BMP's in C array's are supported.
Supported color schemes for BMP's are ARGB8888, RGB565, RGB888.
Displayed text that is exceeds the LCD width size, will be wrapped onto the next line and a '-' character will be injected if the wrap occurs within a word.
## Usage of LCD API
### Generating BMP C header files
#### Resizing images
To resize an image to the desired size (width and height), one can use an image editor such as Photoshop, GIMP, ImageMagick, ... .
For example, using ImageMagick:
```bash
convert in.png -resize 10% BMP3:out.bmp
#OR (depending on the version of ImageMagick)
magick in.png -resize 50x50 out.png
```
The resize option can both be used to resize in percentages or in pixels.
The BMP3 option is used to convert the PNG to Bitmap version 3.0 (note that the BMP header will still be present in the output image).
#### Generating the C array
To easily generate a BMP C array (in the desired color scheme) from an image, [lv_img_conv](https://github.com/lvgl/lv_img_conv) can be used.
See the installation instructions on Github or use the [online version](https://lvgl.io/tools/imageconverter).
Example:
```bash
./lv_img_conv.js test.png -f -c CF_TRUE_COLOR
```
The command above will generate a .c file in which arrays can be found for RGB332, RGB565, ARGB8888. It is also possible to generate a binary BMP image file in ARGB8332, ARGB8565, ARGB8565_RBSWAP, ARGB8888.
```bash
./lv_img_conv.js logo_lvgl.png -f -c CF_TRUE_COLOR -t bin --binary-format ARGB8888
```
### Using the LCD API
#### Initialization of LCD API
The `lcd_init(bool bl_on)` function initialises the LCD screen. The `bl_on` variable allows to enable or disable the LCD backlight.
```c
#include "lcd_api.h"
...
void main(void) {
...
lcd_init(true);
...
}
```
#### Drawing text on the screen
```c
void lcd_display_text(const char* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT *font);
```
```c
#include "lcd_api.h"
...
void main(void) {
...
lcd_init(true);
...
lcd_display_text("This is a text string.", 10, 10, LCD_GREEN, LCD_BLACK, LCD_FONT16);
}
```
Display text on the LCD screen in a certain color. When text width exceeds BSP_LCD_GetXSize(), a text wrap will be performed. If the text wrap is between two will be injected.
#### Drawing a BMP (C-array) onto the screen
```c
void lcd_draw_bmp(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode);
```
```c
#include "lcd_api.h"
#include "test_image.h"
void main(void) {
...
lcd_init(true);
...
lcd_draw_bmp(bmp_array, 0, 0, 50, 50, LCD_ARGB8888);
}
```
Draw BMP image from C array to the LCD screen at position X, Y. In color mode ARGB8888, RGB888, RGB565 or ARGB1555 Supports ARGB8888, RGB565, RGB888 (see LCD_* defines in header file).

163
docs/llfs.md Normal file
View File

@@ -0,0 +1,163 @@
# LLFS (Linked List File System)
## Introduction
The llfs filesystem can be generated using the [mkllfs](mkllfs.md) utility.
The resulting C file encapsulates the filesystem data within a linked list which can be used by the llfs library.
As a flat filesystem, llfs lacks support for directories.
Using the llfs API, information about the files in the filesystem can be retrieved,
and the files can be read using direct memory access.
Alternatively, the POSIX file functions can be used.
But this is more resource intensive, as data must be copied before using it.
It's essential to note that the llfs filesystem operates in a read-only mode,
restricting operations solely to read functions.
## Table of contents
- [Introduction](#introduction)
- [Table of contents](#table-of-contents)
- [Initialization](#initialization)
- [Usage of the llfs API](#usage-of-the-llfs-api)
- [The `llfs_file_t` struct](#the-llfs_file_t-struct)
- [Getting a list of files](#getting-a-list-of-files)
- [Iterator function (not recommended)](#iterator-function-not-recommended)
- [Reading a file](#reading-a-file)
- [Getting the number of files](#getting-the-number-of-files)
- [Using the POSIX file functions](#using-the-posix-file-functions)
## Initialization
Before using the llfs API, or the file related POSIX (fopen, fgetc, ...) functions, the filesystem must be initialized by calling `llfs_init()`.
## Usage of the llfs API
### The `llfs_file_t` struct
The `llfs_file_t` struct contains information about a file in the filesystem.
```c
typedef struct {
const uint8_t* data; // Pointer to the file data (len bytes)
const char* name; // Null-terminated string with the filename
size_t len; // Length of the file data
} llfs_file_t;
```
The data pointer points to the data of the file in the filesystem, and can be used to read the file.
### Getting a list of files
```c
#include "llfs.h"
void main(void) {
llfs_init();
// Allocate space for 10 files
llfs_file_t file_list[10];
// Get the file list
size_t file_count = llfs_file_list(file_list, 10, NULL);
// Loop through the files and print their names and sizes
for (int i = 0; i < file_count; i++) {
LOG_INFO(TAG, "File: %s, size: %d", file_list[i].name, file_list[i].len);
}
}
```
Result:
```
[Info] (2009) [main]: File: image.bmp, size: 9270
[Info] (2013) [main]: File: python_file.py, size: 645
[Info] (2019) [main]: File: image2.bmp, size: 7738
[Info] (2024) [main]: File: filename with a space.txt, size: 61
[Info] (2031) [main]: File: file1.txt, size: 77
```
It is also possible to use a file extension filter (e.g. `*.bmp`, `*.txt`, `*.py`).
```c
// ...
size_t file_count = llfs_file_list(file_list, 10, "*.bmp");
// ...
```
This will only return files with the `.bmp` extension.
````
[Info] (2009) [main]: File: image.bmp, size: 9270
[Info] (2019) [main]: File: image2.bmp, size: 7738
````
#### Iterator function (not recommended)
It is also possible to iterate through the files without allocating an array.
When the memory pointer is `NULL`, the iterator will start at the beginning of the file list.
Each call to `llfs_next_file()` will return the next file in the list,
if a filter is specified files that don't match the filter will be skipped.
```c
#include "llfs.h"
void main(void) {
llfs_init();
// Get the file list
void* mem = NULL; // Pointer for internal use by the llfs library
llfs_file_t* file;
while ((file = llfs_next_file(&mem, ".bmp")) != NULL) {
LOG_INFO(TAG, "File: %s", file->name);
}
}
```
While this method doesn't require allocating memory for the file list,
it is slower than the previous method due to the overhead calling the function for each file.
Additionally, the required memory for the filelist is very small, so it's recommended to use the first method.
### Reading a file
```c
#include "llfs.h"
void main(void) {
llfs_init();
// Get a file by name
llfs_file_t* file = llfs_file_open("filename with a space.txt");
if (file != NULL) {
// Print the file name, size and data
LOG_INFO(TAG, "File found: %s, size: %d", file->name, file->len);
LOG_INFO(TAG, "File data: %s", file->data);
} else {
LOG_WARN(TAG, "File not found");
}
}
```
Result:
```
[Info] (2040) [main]: File found: filename with a space.txt, size: 61
[Info] (2047) [main]: File data: This is a file with a space in it's filename.
```
### Getting the number of files
```c
#include "llfs.h"
void main(void) {
llfs_init();
// Get the number of files
size_t file_count = llfs_file_count();
// Print the number of files
LOG_INFO(TAG, "File count: %d", file_count);
}
```
## Using the POSIX file functions
The llfs library also supports the POSIX file functions.
As the file system is read-only, write functions are not implemented.
There is also a limit on the number of files that can be open concurrently,
this is set by the `POSIX_MAX_FILES` macro in `llfs.c`.
The default value is 10, but there are already 3 files in use (stdin, stdout, stderr),
so the maximum number of files that can be open is 7.
The following functions are tested and working, but other functions might also work:
- `fopen`
- `fclose`
- `fgetc`
- `fread`
- `fseek`
- `ftell`
- `rewind`
- `fstat`
- `fileno`

69
project/.clang-format Normal file
View File

@@ -0,0 +1,69 @@
---
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
BinPackArguments: true
BinPackParameters: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakStringLiterals: true
ColumnLimit: 120
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
IncludeBlocks: Preserve
IncludeCategories:
- Regex: "^<(.*)>"
Priority: 0
- Regex: ^"(.*)"
Priority: 1
- Regex: "(.*)"
Priority: 2
IncludeIsMainRegex: "(_test)?$"
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
MaxEmptyLinesToKeep: 1
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never
UseCRLF: false
...

View File

@@ -24,7 +24,7 @@
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.1374679552" name="Floating-point ABI" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.1374679552" name="Floating-point ABI" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.563119967" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="STM32F746G-DISCO" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.563119967" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="STM32F746G-DISCO" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1834000979" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F746G-DISCO || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../LWIP/App | ../LWIP/Target | ../Core/Inc | ../Middlewares/Third_Party/LwIP/src/include | ../Middlewares/Third_Party/LwIP/system | ../Drivers/STM32F7xx_HAL_Driver/Inc | ../Drivers/STM32F7xx_HAL_Driver/Inc/Legacy | ../Drivers/BSP/Components/lan8742 | ../Middlewares/Third_Party/LwIP/src/include/netif/ppp | ../Middlewares/Third_Party/LwIP/src/apps/http | ../Drivers/CMSIS/Device/ST/STM32F7xx/Include | ../Middlewares/Third_Party/LwIP/src/include/lwip | ../Middlewares/Third_Party/LwIP/src/include/lwip/apps | ../Middlewares/Third_Party/LwIP/src/include/lwip/priv | ../Middlewares/Third_Party/LwIP/src/include/lwip/prot | ../Middlewares/Third_Party/LwIP/src/include/netif | ../Middlewares/Third_Party/LwIP/src/include/compat/posix | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/arpa | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/net | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/sys | ../Middlewares/Third_Party/LwIP/src/include/compat/stdc | ../Middlewares/Third_Party/LwIP/system/arch | ../Drivers/CMSIS/Include || || || USE_HAL_DRIVER | STM32F746xx || || LWIP | Drivers | Core/Startup | Middlewares | Core || || || ${workspace_loc:/${ProjName}/STM32F746NGHX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1834000979" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F746G-DISCO || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../LWIP/App | ../LWIP/Target | ../Core/Inc | ../Middlewares/Third_Party/LwIP/src/include | ../Middlewares/Third_Party/LwIP/system | ../Drivers/STM32F7xx_HAL_Driver/Inc | ../Drivers/STM32F7xx_HAL_Driver/Inc/Legacy | ../Drivers/BSP/Components/lan8742 | ../Middlewares/Third_Party/LwIP/src/include/netif/ppp | ../Middlewares/Third_Party/LwIP/src/apps/http | ../Drivers/CMSIS/Device/ST/STM32F7xx/Include | ../Middlewares/Third_Party/LwIP/src/include/lwip | ../Middlewares/Third_Party/LwIP/src/include/lwip/apps | ../Middlewares/Third_Party/LwIP/src/include/lwip/priv | ../Middlewares/Third_Party/LwIP/src/include/lwip/prot | ../Middlewares/Third_Party/LwIP/src/include/netif | ../Middlewares/Third_Party/LwIP/src/include/compat/posix | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/arpa | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/net | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/sys | ../Middlewares/Third_Party/LwIP/src/include/compat/stdc | ../Middlewares/Third_Party/LwIP/system/arch | ../Drivers/CMSIS/Include || || || USE_HAL_DRIVER | STM32F746xx || || LWIP | Drivers | Core/Startup | Middlewares | Core || || || ${workspace_loc:/${ProjName}/STM32F746NGHX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.1771148873" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="200" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.1771148873" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="200" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.516061282" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/> <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.516061282" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/project}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1463828525" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/> <builder buildPath="${workspace_loc:/project}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1463828525" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.130096062" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler"> <tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.130096062" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
@@ -91,11 +91,12 @@
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec.2105531190" name="MCU Output Converter Motorola S-rec with symbols" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec"/> <tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec.2105531190" name="MCU Output Converter Motorola S-rec with symbols" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.objcopy.symbolsrec"/>
</toolChain> </toolChain>
</folderInfo> </folderInfo>
<fileInfo id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.1923792012.2015795402" name="test_data.h" rcbsApplicability="disable" resourcePath="Core/Inc/test_data.h" toolsToInvoke=""/>
<sourceEntries> <sourceEntries>
<entry excluding="Inc/fsdata_custom.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/> <entry excluding="Inc/fsdata_custom.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="LWIP"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="LWIP"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Middlewares"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Middlewares"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
</sourceEntries> </sourceEntries>
</configuration> </configuration>
</storageModule> </storageModule>
@@ -117,28 +118,28 @@
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.2077354707" name="Release" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release"> <configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.2077354707" name="Release" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release">
<folderInfo id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.2077354707." name="/" resourcePath=""> <folderInfo id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.2077354707." name="/" resourcePath="">
<toolChain id="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release.2091178292" name="MCU ARM GCC" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release"> <toolChain id="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release.2091178292" name="MCU ARM GCC" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu.191824980" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu" useByScannerDiscovery="true" value="STM32F746NGHx" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu.191824980" name="MCU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu" useByScannerDiscovery="true" value="STM32F746NGHx" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid.240275284" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid" useByScannerDiscovery="false" value="0" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid.240275284" name="CPU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid" useByScannerDiscovery="false" value="0" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid.123910523" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid" useByScannerDiscovery="false" value="0" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid.123910523" name="Core" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid" useByScannerDiscovery="false" value="0" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.1571746044" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.value.fpv5-sp-d16" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.1571746044" name="Floating-point unit" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.fpu.value.fpv5-sp-d16" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.118832767" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.118832767" name="Floating-point ABI" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.1749227860" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="STM32F746G-DISCO" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.1749227860" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="STM32F746G-DISCO" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.752119389" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F746G-DISCO || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../LWIP/App | ../LWIP/Target | ../Core/Inc | ../Middlewares/Third_Party/LwIP/src/include | ../Middlewares/Third_Party/LwIP/system | ../Drivers/STM32F7xx_HAL_Driver/Inc | ../Drivers/STM32F7xx_HAL_Driver/Inc/Legacy | ../Drivers/BSP/Components/lan8742 | ../Middlewares/Third_Party/LwIP/src/include/netif/ppp | ../Middlewares/Third_Party/LwIP/src/apps/http | ../Drivers/CMSIS/Device/ST/STM32F7xx/Include | ../Middlewares/Third_Party/LwIP/src/include/lwip | ../Middlewares/Third_Party/LwIP/src/include/lwip/apps | ../Middlewares/Third_Party/LwIP/src/include/lwip/priv | ../Middlewares/Third_Party/LwIP/src/include/lwip/prot | ../Middlewares/Third_Party/LwIP/src/include/netif | ../Middlewares/Third_Party/LwIP/src/include/compat/posix | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/arpa | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/net | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/sys | ../Middlewares/Third_Party/LwIP/src/include/compat/stdc | ../Middlewares/Third_Party/LwIP/system/arch | ../Drivers/CMSIS/Include || || || USE_HAL_DRIVER | STM32F746xx || || LWIP | Drivers | Core/Startup | Middlewares | Core || || || ${workspace_loc:/${ProjName}/STM32F746NGHX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.752119389" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32F746G-DISCO || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../LWIP/App | ../LWIP/Target | ../Core/Inc | ../Middlewares/Third_Party/LwIP/src/include | ../Middlewares/Third_Party/LwIP/system | ../Drivers/STM32F7xx_HAL_Driver/Inc | ../Drivers/STM32F7xx_HAL_Driver/Inc/Legacy | ../Drivers/BSP/Components/lan8742 | ../Middlewares/Third_Party/LwIP/src/include/netif/ppp | ../Middlewares/Third_Party/LwIP/src/apps/http | ../Drivers/CMSIS/Device/ST/STM32F7xx/Include | ../Middlewares/Third_Party/LwIP/src/include/lwip | ../Middlewares/Third_Party/LwIP/src/include/lwip/apps | ../Middlewares/Third_Party/LwIP/src/include/lwip/priv | ../Middlewares/Third_Party/LwIP/src/include/lwip/prot | ../Middlewares/Third_Party/LwIP/src/include/netif | ../Middlewares/Third_Party/LwIP/src/include/compat/posix | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/arpa | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/net | ../Middlewares/Third_Party/LwIP/src/include/compat/posix/sys | ../Middlewares/Third_Party/LwIP/src/include/compat/stdc | ../Middlewares/Third_Party/LwIP/system/arch | ../Drivers/CMSIS/Include || || || USE_HAL_DRIVER | STM32F746xx || || LWIP | Drivers | Core/Startup | Middlewares | Core || || || ${workspace_loc:/${ProjName}/STM32F746NGHX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.692149734" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="200" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.692149734" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="200" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.31610660" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/> <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.31610660" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/project}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.525679761" managedBuildOn="true" name="Gnu Make Builder.Release" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/> <builder buildPath="${workspace_loc:/project}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.525679761" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.936753340" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler"> <tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.936753340" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.968854718" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.value.g0" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.968854718" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.option.debuglevel.value.g0" valueType="enumerated"/>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input.1789271480" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input"/> <inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input.1789271480" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input"/>
</tool> </tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.62369603" name="MCU GCC Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler"> <tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.62369603" name="MCU GCC Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.51455808" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.value.g0" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.51455808" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.debuglevel.value.g0" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.132579829" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.value.os" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.132579829" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.optimization.level.value.os" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols.767346044" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols" useByScannerDiscovery="false" valueType="definedSymbols"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols.767346044" name="Define symbols (-D)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.definedsymbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="USE_HAL_DRIVER"/> <listOptionValue builtIn="false" value="USE_HAL_DRIVER"/>
<listOptionValue builtIn="false" value="STM32F746xx"/> <listOptionValue builtIn="false" value="STM32F746xx"/>
</option> </option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths.1698764284" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths" useByScannerDiscovery="false" valueType="includePath"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths.1698764284" name="Include paths (-I)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.option.includepaths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="../LWIP/App"/> <listOptionValue builtIn="false" value="../LWIP/App"/>
<listOptionValue builtIn="false" value="../LWIP/Target"/> <listOptionValue builtIn="false" value="../LWIP/Target"/>
<listOptionValue builtIn="false" value="../Core/Inc"/> <listOptionValue builtIn="false" value="../Core/Inc"/>
@@ -166,11 +167,11 @@
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.2006257133" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/> <inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.2006257133" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
</tool> </tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.71666735" name="MCU G++ Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler"> <tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.71666735" name="MCU G++ Compiler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.1614690145" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.value.g0" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.1614690145" name="Debug level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.debuglevel.value.g0" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level.732337455" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level.value.os" valueType="enumerated"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level.732337455" name="Optimization level" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.cpp.compiler.option.optimization.level.value.os" valueType="enumerated"/>
</tool> </tool>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.611884646" name="MCU GCC Linker" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker"> <tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.611884646" name="MCU GCC Linker" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script.233275983" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script" value="${workspace_loc:/${ProjName}/STM32F746NGHX_FLASH.ld}" valueType="string"/> <option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script.233275983" name="Linker Script (-T)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.option.script" value="${workspace_loc:/${ProjName}/STM32F746NGHX_FLASH.ld}" valueType="string"/>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input.2143593204" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input"> <inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input.2143593204" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/> <additionalInput kind="additionalinput" paths="$(LIBS)"/>

File diff suppressed because one or more lines are too long

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.1923792012" name="Debug">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1598175355152594562" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
<configuration id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.2077354707" name="Release">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1598175355152594562" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>

View File

@@ -1,4 +0,0 @@
635E684B79701B039C64EA45C3F84D30=80FB35DB9B6CC80F943DFC38749575DE
66BE74F758C12D739921AEA421D593D3=0
DC22A860405A8BF2F2C095E5B6529F12=61120D4BCEA54A37FDB6D8A0FEEC8DD5
eclipse.preferences.version=1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
/**
* @file lcd_api.h
* @brief API for LCD functionality
* @author Tim S.
*/
#ifndef INC_LCD_API_H_
#define INC_LCD_API_H_
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#define LOGGER_LEVEL_ALL
#include "log.h"
#include "../../Drivers/BSP/STM32746G-Discovery/stm32746g_discovery_lcd.h"
#define LCD_BLUE LCD_COLOR_BLUE
#define LCD_GREEN LCD_COLOR_GREEN
#define LCD_RED LCD_COLOR_RED
#define LCD_CYAN LCD_COLOR_CYAN
#define LCD_MAGENTA LCD_COLOR_MAGENTA
#define LCD_YELLOW LCD_COLOR_YELLOW
#define LCD_LIGHTBLUE LCD_COLOR_LIGHTBLUE
#define LCD_LIGHTGREEN LCD_COLOR_LIGHTGREEN
#define LCD_LIGHTRED LCD_COLOR_LIGHTRED
#define LCD_LIGHTCYAN LCD_COLOR_LIGHTCYAN
#define LCD_LIGHTMAGENTA LCD_COLOR_LIGHTMAGENTA
#define LCD_LIGHTYELLOW LCD_COLOR_LIGHTYELLOW
#define LCD_DARKBLUE LCD_COLOR_DARKBLUE
#define LCD_DARKGREEN LCD_COLOR_DARKGREEN
#define LCD_DARKRED LCD_COLOR_DARKRED
#define LCD_DARKCYAN LCD_COLOR_DARKCYAN
#define LCD_DARKMAGENTA LCD_COLOR_DARKMAGENTA
#define LCD_DARKYELLOW LCD_COLOR_DARKYELLOW
#define LCD_WHITE LCD_COLOR_WHITE
#define LCD_LIGHTGRAY LCD_COLOR_LIGHTGRAY
#define LCD_GRAY LCD_COLOR_GRAY
#define LCD_DARKGRAY LCD_COLOR_DARKGRAY
#define LCD_BLACK LCD_COLOR_BLACK
#define LCD_BROWN LCD_COLOR_BROWN
#define LCD_ORANGE LCD_COLOR_ORANGE
#define LCD_TRANSPARENT LCD_COLOR_TRANSPARENT
#define LCD_ARGB8888 0x00000000U
#define LCD_RGB888 0x00000001U
#define LCD_RGB565 0x00000002U
#define LCD_ARGB1555 0x00000003U
#define LCD_FONT8 &Font8
#define LCD_FONT12 &Font12
#define LCD_FONT16 &Font16
#define LCD_FONT20 &Font20
#define LCD_FONT24 &Font24
extern LTDC_HandleTypeDef hLtdcHandler;
/**
* @brief Initialise LCD
* Initialise the LCD screen with BackLight on or not
*
* @param[in] bl_on Bool to enable or disable the LCD backlight
*
*/
void lcd_init(bool bl_on);
/**
* @brief Display text
* Display text on the LCD screen in a certain color. When text width exceeds BSP_LCD_GetXSize(),
* a text wrap will be performed. If the text wrap is between two letters in a word, the '-' character
* will be injected.
*
* @param[in] text C-style text string to display on the LCD screen
* @param[in] x_pos X-position
* @param[in] y_pos Y-position
* @param[in] color Color in which the text will be displayed, see preset colors in defines above
* @param[in] bg_color Background color for the text
* @param[in] font Font size, see defines above in file
*/
void lcd_display_text(uint8_t* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT *font);
/**
* @brief Draw BMP image on screen
* Draw BMP image from C array to the LCD screen at position X, Y. In color mode ARGB8888, RGB888, RGB565 or ARGB1555
* Supports ARGB8888, RGB565, RGB888
*
* @author Wim Dams
*
* @param[in] p_src C array containing the image data
* @param[in] x_pos X-position
* @param[in] y_pos Y-position
* @param[in] x_size Width of image
* @param[in] y_size Height of image
* @param[in] color_mode Color mode (see defined color modes above in file)
*/
void lcd_draw_bmp(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode);
#endif /* INC_LCD_API_H_ */

86
project/Core/Inc/llfs.h Normal file
View File

@@ -0,0 +1,86 @@
/**
* @file llfs.h
* @brief Linked List Filesystem header (llfs)
* @author Lorenz C.
* @version 0.1.1
*/
#ifndef LLFS_H
#define LLFS_H
#include <stddef.h>
#include <stdint.h>
/**
* @brief Representation of a file in the llfs filesystem
*/
typedef struct llfs_file {
const uint8_t* data; // Pointer to the file data (len bytes)
const char* name; // Null-terminated string with the filename
size_t len; // Length of the file data
} llfs_file_t;
/**
* @brief Internal representation of a file in the filesystem
* @warning This struct should only be used in the llfs_data.c file.
*/
struct llfs_data_file {
const uint8_t* data;
const char* name;
const size_t len;
const struct llfs_data_file* next;
};
/**
* @brief Initialize the llfs filesystem
* @note This function should be called before any other llfs function or POSIX file operation (e.g. fopen, fread, ...)
* @return 0 on success
*/
int8_t llfs_init(void);
/**
* @brief Get a list of files in the filesystem
* Get a list of all the files in the filesystem.
*
* Use the filter to filter out files with a filename that do not match the file extension filter.
*
* The following members of the llfs_file_t struct are set: name, len and data. @ref llfs_file_t
*
*
* @param[out] file_list A pointer to an array of llfs_file_t to store the files in @ref llfs_file_t
* @param[in] max_files The maximum number of files to return (size of file_list)
* @param[in] filter A string with the file extensions to filter out. (e.g. "*.txt" or "*.png")
* @return The number of files returned
*/
size_t llfs_file_list(llfs_file_t* file_list, size_t max_files, char* filter);
/**
* @brief Open a file
* Get a file from the filesystem by name.
*
* @param[in] name The name of the file to open
* @return A pointer to a llfs_file_t with the file data @ref llfs_file_t
* NULL if the file does not exist
*/
llfs_file_t* llfs_file_open(const char* name);
/**
* @brief Iterate over all files in the filesystem
* For each call (with the same mem pointer) the next file in the filesystem is returned.
* The first call should be with mem = NULL.
* If a filter is specified, only files with a filename that matches the filter are returned.
*
* @param[in, out] mem A pointer to a void* that is used internally to keep track of the current file
* @param[in] filter A string with file extension to filter out. (e.g. "*.txt" or "*.png")
* @return The next file in the filesystem or NULL if there are no more files @ref llfs_file_t
*/
llfs_file_t* llfs_next_file(void** mem, char* filter);
/**
* @brief Get the number of files in the filesystem
*
* @return The number of files in the filesystem
*/
size_t llfs_file_count(void);
#endif // LLFS_H

View File

@@ -88,17 +88,17 @@
#endif #endif
#if LOGGER_LEVEL <= 1 #if LOGGER_LEVEL <= 1
#define LOG_DEBUG(tag, fmt, ...) printf(LOG_COLOR_D"[Debug] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_DEBUG(tag, fmt, ...) printf(LOG_COLOR_D"[Debug] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
#else #else
#define LOG_DEBUG(tag, fmt, ...) #define LOG_DEBUG(tag, fmt, ...)
#endif #endif
#if LOGGER_LEVEL <= 2 #if LOGGER_LEVEL <= 2
#define LOG_INFO(tag, fmt, ...) printf(LOG_COLOR_I"[Info] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_INFO(tag, fmt, ...) printf(LOG_COLOR_I"[Info] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
#else #else
#define LOG_INFO(tag, fmt, ...) #define LOG_INFO(tag, fmt, ...)
#endif #endif
#if LOGGER_LEVEL <= 3 #if LOGGER_LEVEL <= 3
#define LOG_WARN(tag, fmt, ...) printf(LOG_COLOR_W"[Warning] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_WARN(tag, fmt, ...) printf(LOG_COLOR_W"[Warning] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
#else #else
#define LOG_WARN(tag, fmt, ...) #define LOG_WARN(tag, fmt, ...)
#endif #endif
@@ -108,7 +108,7 @@
#define LOG_CRIT(tag, fmt, ...) #define LOG_CRIT(tag, fmt, ...)
#endif #endif
#if LOGGER_LEVEL <= 4 #if LOGGER_LEVEL <= 4
#define LOG_FATAL(tag, fmt, ...) printf(LOG_COLOR_F"[Fatal] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_FATAL(tag, fmt, ...) printf(LOG_COLOR_F"[Fatal] (%lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__)
#else #else
#define LOG_FATAL(tag, fmt, ...) #define LOG_FATAL(tag, fmt, ...)
#endif #endif

View File

@@ -31,6 +31,7 @@ extern "C" {
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
#include "../../Drivers/BSP/STM32746G-Discovery/stm32746g_discovery_lcd.h"
/* USER CODE END Includes */ /* USER CODE END Includes */

View File

@@ -0,0 +1,97 @@
/**
* @file lcd_api.c
* @brief LCD API implementation
* @author Tim S.
* @todo Implement function to read images from fs
*/
#include "lcd_api.h"
static const char* TAG = "lcd_api";
static DMA2D_HandleTypeDef hDma2dHandler2;
void lcd_init(bool bl_on) {
LOG_INFO(TAG, "Init LCD");
BSP_LCD_Init();
BSP_LCD_LayerDefaultInit(1, LCD_FB_START_ADDRESS);
BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS + (BSP_LCD_GetXSize()*BSP_LCD_GetYSize()*4));
BSP_LCD_SelectLayer(0);
BSP_LCD_Clear(LCD_COLOR_BLACK);
BSP_LCD_SelectLayer(1);
BSP_LCD_Clear(LCD_COLOR_BLACK);
if (bl_on) {
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_12, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_12, GPIO_PIN_RESET);
}
}
void lcd_display_text(uint8_t* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT *font) {
LOG_INFO(TAG, "Display text: %s @x=%d,y=%d", text, x_pos, y_pos);
uint16_t tot_length = x_pos + (strlen(text) * font->Width);
if ((x_pos % font->Width) != 0) {
x_pos -= (x_pos % font->Width);
}
BSP_LCD_SetTextColor(color);
BSP_LCD_SetBackColor(bg_color);
BSP_LCD_SetFont(font);
if (tot_length > BSP_LCD_GetXSize()) {
for (int i = 0; i < strlen(text); i++) {
if ((x_pos) > BSP_LCD_GetXSize() - (font->Width)*2) {
if (isalpha(text[i-1]) && isalpha(text[i])) {
BSP_LCD_DisplayChar(x_pos, y_pos, '-');
i -= 1;
}
x_pos = 0;
y_pos += font->Height;
} else {
BSP_LCD_DisplayChar(x_pos, y_pos, text[i]);
x_pos += font->Width;
}
}
} else {
BSP_LCD_DisplayStringAt(x_pos, y_pos, text, LEFT_MODE);
}
}
void lcd_draw_bmp(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode) {
uint32_t address = hLtdcHandler.LayerCfg[1].FBStartAdress + (((BSP_LCD_GetXSize()*y_pos) + x_pos)*(4));
void *p_dst = (void *)address;
hDma2dHandler2.Init.Mode = DMA2D_M2M_PFC;
hDma2dHandler2.Init.ColorMode = DMA2D_ARGB8888;
hDma2dHandler2.Init.OutputOffset = BSP_LCD_GetXSize()-x_size;
hDma2dHandler2.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hDma2dHandler2.LayerCfg[1].InputAlpha = 0xFF;
hDma2dHandler2.LayerCfg[1].InputColorMode = color_mode;
hDma2dHandler2.LayerCfg[1].InputOffset = 0;
LOG_INFO(TAG, "DMA2D init");
hDma2dHandler2.Instance = DMA2D;
if (HAL_DMA2D_Init(&hDma2dHandler2) != HAL_OK) {
LOG_CRIT(TAG, "HAL_DMA2D_Init error");
return;
}
LOG_INFO(TAG, "DMA2D config layer");
if (HAL_DMA2D_ConfigLayer(&hDma2dHandler2, 1) != HAL_OK) {
LOG_CRIT(TAG, "HAL_DMA2D_ConfigLayer error");
return;
}
LOG_INFO(TAG, "DMA2D start");
if (HAL_DMA2D_Start(&hDma2dHandler2, (uint32_t)p_src, (uint32_t)p_dst, x_size, y_size) != HAL_OK) {
LOG_CRIT(TAG, "HAL_DMA2D_Start error");
return;
}
LOG_INFO(TAG, "DMA2D poll");
HAL_DMA2D_PollForTransfer(&hDma2dHandler2, 10);
}

436
project/Core/Src/llfs.c Normal file
View File

@@ -0,0 +1,436 @@
/**
* @file llfs.c
* @brief Linked List Filesystem implementation (llfs)
* @author Lorenz C.
* @version 0.1.1
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#define LOGGER_LEVEL_WARN
#include "llfs.h"
#include "log.h"
/**
* @brief The maximum number of files that can be opened concurrently using the POSIX API
*/
#define POSIX_MAX_FILES 10
extern struct llfs_data_file* llfs_root;
const char* TAG = "llfs";
size_t file_count = 0;
FILE* file_table[POSIX_MAX_FILES];
static int new_file_table_entry(void);
static int free_file_table_entry(int file_id);
static FILE* file_id_to_stream(int file_id);
static uint8_t file_ext_cmp(const char* filename, const char* ext);
int8_t llfs_init(void) {
LOG_DEBUG(TAG, "Initializing llfs");
// Initialize the file table
for (int i = 0; i < POSIX_MAX_FILES; i++) {
file_table[i] = NULL;
}
// Add stdin, stdout and stderr to the file table
file_table[STDIN_FILENO] = stdin;
file_table[STDOUT_FILENO] = stdout;
file_table[STDERR_FILENO] = stderr;
return 0;
}
size_t llfs_file_list(llfs_file_t* file_list, size_t max_files, char* filter) {
size_t count = 0; // Number of files found
const struct llfs_data_file* file = llfs_root; // Pointer to the current file
if (filter != NULL) {
LOG_DEBUG(TAG, "Filtering files with filter: %s", filter);
if (filter[0] == '*') {
filter++;
}
}
// Iterate over all files in the filesystem
while (file != NULL && file_count < max_files) {
// Filter out files with a filename that does not match the filter
if (filter != NULL) {
if (!file_ext_cmp(file->name, filter)) {
file = file->next;
continue;
}
}
// Add the file to the file list
file_list[count].data = file->data;
file_list[count].name = file->name;
file_list[count].len = file->len;
// Move to the next file
count++;
file = file->next;
}
LOG_DEBUG(TAG, "Files found: %d", count);
return count;
}
llfs_file_t* llfs_file_open(const char* name) {
const struct llfs_data_file* file = llfs_root;
LOG_DEBUG(TAG, "Opening file: %s", name);
while (file != NULL) {
if (strcmp(file->name, name) == 0) {
LOG_DEBUG(TAG, "File found: %s, size: %d", file->name, file->len);
return (llfs_file_t*)file;
}
file = file->next;
}
LOG_DEBUG(TAG, "File not found: %s", name);
return NULL;
}
llfs_file_t* llfs_next_file(void** mem, char* filter) {
struct llfs_data_file* prev_file = (struct llfs_data_file*)*mem;
uint8_t filter_ok = 0;
if (prev_file == NULL) {
prev_file = llfs_root;
} else {
prev_file = (struct llfs_data_file*)prev_file->next;
}
// If a filter is specified, only return files that match the filter
if (filter != NULL) {
LOG_DEBUG(TAG, "Filtering files with filter: %s", filter);
// Remove the '*' from the filter
if (filter[0] == '*') {
filter++;
}
while (prev_file != NULL) {
if (file_ext_cmp(prev_file->name, filter)) {
filter_ok = 1;
break;
}
prev_file = (struct llfs_data_file*)prev_file->next;
}
}
*mem = (void*)prev_file;
return (llfs_file_t*)prev_file;
}
size_t llfs_file_count(void) {
if (file_count == 0) {
const struct llfs_data_file* file = llfs_root;
while (file != NULL) {
file_count++;
file = file->next;
}
}
return file_count;
}
/**
* @brief Newlib open implementation
*
* @param path
* @param flags
* @param mode
* @return
*/
int _open(char* path, int flags, int mode) {
int file_id;
FILE* stream;
errno = 0;
llfs_file_t* llfs_file;
// Add a new entry to the file table
file_id = new_file_table_entry();
if (file_id < 0) {
LOG_WARN(TAG, "Failed to add new file table entry. %s", strerror(errno));
return -1;
}
// Get the stream associated with the file id
stream = file_id_to_stream(file_id);
if (stream == NULL) {
LOG_WARN(TAG, "Failed to get file table entry. %s", strerror(errno));
free_file_table_entry(file_id);
return -1;
}
// Get the file from the llfs filesystem
llfs_file = llfs_file_open(path);
if (llfs_file == NULL) {
LOG_DEBUG(TAG, "Failed to open file: %s", path);
free_file_table_entry(file_id);
return -1;
}
// Initialize the stream
stream->_cookie = (void*)llfs_file;
stream->_offset = 0;
stream->_flags = __SRD;
return file_id;
}
/**
* @brief Newlib close implementation
*
* @param file_id
* @return
*/
int _close(int file_id) {
FILE* stream;
// Get the stream associated with the file id
stream = file_id_to_stream(file_id);
if (stream == NULL) {
LOG_WARN(TAG, "Failed to get file table entry. %s", strerror(errno));
return -1;
}
// Remove the entry from the file table
if (free_file_table_entry(file_id) < 0) {
LOG_WARN(TAG, "Failed to remove file table entry. %s", strerror(errno));
return -1;
}
return 0;
}
/**
* @brief Newlib read implementation
*
* @param file_id
* @param ptr
* @param len
* @return
*/
int _read(int file_id, char* ptr, int len) {
FILE* stream;
llfs_file_t* llfs_file;
size_t bytes_read;
// Read from stdin, stdout and stderr is not supported
if (file_id == STDIN_FILENO || file_id == STDOUT_FILENO || file_id == STDERR_FILENO) {
LOG_DEBUG(TAG, "Trying to read from stdin, stdout or stderr: %d", file_id);
return -1;
}
// Get the stream associated with the file id
stream = file_id_to_stream(file_id);
if (stream == NULL) {
LOG_WARN(TAG, "Failed to get file table entry. %s", strerror(errno));
return -1;
}
// Get the file from the llfs filesystem associated with the stream
llfs_file = (llfs_file_t*)stream->_cookie;
if (llfs_file == NULL) {
LOG_WARN(TAG, "Failed to get llfs file associated with stream: %d", file_id);
return -1;
}
// Calculate the number of bytes to read (limited by the file size)
bytes_read = llfs_file->len - stream->_offset;
if (bytes_read > len) {
bytes_read = len;
} else if (bytes_read == 0) { // End of file
stream->_flags |= __SEOF;
return 0;
}
// Copy the data over to the dst buffer
memcpy(ptr, llfs_file->data + stream->_offset, bytes_read);
stream->_offset += (off_t)bytes_read;
return (int)bytes_read;
}
/**
* @brief Newlib isatty implementation
*
* @param file
* @return 1 if the file is stdin, stdout or stderr, 0 otherwise
*/
int isatty(int file) {
if (file == STDIN_FILENO || file == STDOUT_FILENO || file == STDERR_FILENO) {
return 1;
}
return 0;
}
/**
* @brief Newlib lseek implementation
*
* @param file
* @param ptr
* @param dir
* @return
*/
int _lseek(int file, int ptr, int dir) {
FILE* stream;
if (file == STDIN_FILENO || file == STDOUT_FILENO || file == STDERR_FILENO) {
LOG_DEBUG(TAG, "Trying to seek stdin, stdout or stderr: %d", file);
return -1;
}
stream = file_id_to_stream(file);
if (stream == NULL) {
LOG_WARN(TAG, "Failed to get file table entry. %s", strerror(errno));
return -1;
}
switch (dir) {
case SEEK_SET:
stream->_offset = ptr;
break;
case SEEK_CUR:
stream->_offset += ptr;
break;
case SEEK_END:
stream->_offset = (off_t)((llfs_file_t*)stream->_cookie)->len + ptr;
break;
default:
LOG_WARN(TAG, "Invalid seek direction: %d", dir);
return -1;
}
return 0;
}
/**
* @brief Newlib fstat implementation
*
* @param[in] file
* @param[out] st
* @return
*/
int _fstat(int file, struct stat* st) {
FILE* stream;
llfs_file_t *llfs_file;
// Check if the file is stdin, stdout or stderr
if (file == STDIN_FILENO || file == STDOUT_FILENO || file == STDERR_FILENO) {
st->st_mode = S_IFCHR; // Character special file
return 0;
}
// Get the stream associated with the file id
stream = file_id_to_stream(file);
if (stream == NULL) {
LOG_WARN(TAG, "Failed to get file table entry. %s", strerror(errno));
return -1;
}
// Get the file from the llfs filesystem associated with the stream
llfs_file = (llfs_file_t*)stream->_cookie;
if (llfs_file == NULL) {
LOG_WARN(TAG, "Failed to get llfs file associated with stream: %d", file);
return -1;
}
st->st_mode = S_IFREG; // Regular file
st->st_size = (off_t)llfs_file->len;
return 0;
}
/**
* @brief Create a new entry in the file table
*
* @return The file id or -1 if an error occurred. See errno for more information.
*/
static int new_file_table_entry(void) {
FILE* stream;
// Try to find an empty entry in the file table
for (int i = 0; i < POSIX_MAX_FILES; i++) {
if (file_table[i] == NULL) {
stream = (FILE*)malloc(sizeof(FILE));
if (stream == NULL) {
errno = ENOMEM; // Out of memory
return -1;
}
file_table[i] = stream;
return i;
}
}
// No empty entry found
errno = ENFILE; // Too many open files
return -1;
}
/**
* @brief Remove an entry from the file table
*
* @param[in] file_id The file id to remove
* @return 0 if successful, -1 if an error occurred. See errno for more information.
*/
static int free_file_table_entry(int file_id) {
// Check if the file id is valid
if (file_id < 0 || file_id >= POSIX_MAX_FILES) {
errno = EBADF; // Bad file number
return -1;
}
// Remove the entry from the file table
free(file_table[file_id]);
file_table[file_id] = NULL;
return 0;
}
/**
* @brief Get the stream associated with a file id
*
* @param[in] file_id The file id to get the stream for
* @return The stream or NULL if an error occurred. See errno for more information.
*/
static FILE* file_id_to_stream(int file_id) {
if (file_id < 0 || file_id >= POSIX_MAX_FILES) {
errno = EBADF; // Bad file number
return NULL;
}
return file_table[file_id];
}
/**
* @brief Check if a filename ends with a given extension
*
* @param[in] filename The filename to check
* @param[in] ext The extension to check for
* @return 1 if the filename ends with the extension, 0 otherwise
*/
static uint8_t file_ext_cmp(const char* const filename, const char* const ext) {
uint8_t ext_len = strlen(ext);
uint8_t filename_len = strlen(filename);
if (filename_len < ext_len) {
return 0;
}
// Compare backwards
for (uint8_t i = 0; i < ext_len; i++) {
if (filename[filename_len - i] != ext[ext_len - i]) {
return 0;
}
}
return 1;
}

3152
project/Core/Src/llfs_data.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/** /**
* @file log.c * @file log.c
* @brief Logger implementation * @brief Logger implementation
* @authors Lorenz C. && Speetjens S. * @authors Lorenz C. && Sander S.
*/ */
#include <stdarg.h> #include <stdarg.h>

File diff suppressed because it is too large Load Diff

View File

@@ -89,14 +89,14 @@ __attribute__((weak)) int _write(int file, char *ptr, int len)
return len; return len;
} }
int _close(int file) __attribute__((weak)) int _close(int file)
{ {
(void)file; (void)file;
return -1; return -1;
} }
int _fstat(int file, struct stat *st) __attribute__((weak)) int _fstat(int file, struct stat *st)
{ {
(void)file; (void)file;
st->st_mode = S_IFCHR; st->st_mode = S_IFCHR;
@@ -109,7 +109,7 @@ int _isatty(int file)
return 1; return 1;
} }
int _lseek(int file, int ptr, int dir) __attribute__((weak)) int _lseek(int file, int ptr, int dir)
{ {
(void)file; (void)file;
(void)ptr; (void)ptr;
@@ -117,7 +117,7 @@ int _lseek(int file, int ptr, int dir)
return 0; return 0;
} }
int _open(char *path, int flags, ...) __attribute__((weak)) int _open(char *path, int flags, ...)
{ {
(void)path; (void)path;
(void)flags; (void)flags;
@@ -145,7 +145,7 @@ int _times(struct tms *buf)
return -1; return -1;
} }
int _stat(char *file, struct stat *st) __attribute__((weak)) int _stat(char *file, struct stat *st)
{ {
(void)file; (void)file;
st->st_mode = S_IFCHR; st->st_mode = S_IFCHR;

View File

@@ -116,7 +116,7 @@ EndDependencies */
/** @defgroup STM32746G_DISCOVERY_LCD_Private_Variables STM32746G_DISCOVERY_LCD Private Variables /** @defgroup STM32746G_DISCOVERY_LCD_Private_Variables STM32746G_DISCOVERY_LCD Private Variables
* @{ * @{
*/ */
LTDC_HandleTypeDef hLtdcHandler; LTDC_HandleTypeDef hLtdcHandler;
static DMA2D_HandleTypeDef hDma2dHandler; static DMA2D_HandleTypeDef hDma2dHandler;
@@ -1021,7 +1021,7 @@ void BSP_LCD_DrawPixel(uint16_t Xpos, uint16_t Ypos, uint32_t RGB_Code)
*/ */
void BSP_LCD_DrawBitmap(uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp) void BSP_LCD_DrawBitmap(uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp)
{ {
uint32_t index = 0, width = 0, height = 0, bit_pixel = 0; uint32_t index = 0, width = 0, height = 0, bit_pixel = 0, row_size = 0;
uint32_t address; uint32_t address;
uint32_t input_color_mode = 0; uint32_t input_color_mode = 0;
@@ -1039,6 +1039,9 @@ void BSP_LCD_DrawBitmap(uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp)
/* Set the address */ /* Set the address */
address = hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (((BSP_LCD_GetXSize()*Ypos) + Xpos)*(4)); address = hLtdcHandler.LayerCfg[ActiveLayer].FBStartAdress + (((BSP_LCD_GetXSize()*Ypos) + Xpos)*(4));
/* Calculate the row size in byte */
row_size = ((bit_pixel*width + 31)/32) * 4;
/* Get the layer pixel format */ /* Get the layer pixel format */
if ((bit_pixel/8) == 4) if ((bit_pixel/8) == 4)
@@ -1053,20 +1056,20 @@ void BSP_LCD_DrawBitmap(uint32_t Xpos, uint32_t Ypos, uint8_t *pbmp)
{ {
input_color_mode = CM_RGB888; input_color_mode = CM_RGB888;
} }
/* Bypass the bitmap header */ /* Bypass the bitmap header */
pbmp += (index + (width * (height - 1) * (bit_pixel/8))); pbmp += (index + (row_size * (height - 1)));
/* Convert picture to ARGB8888 pixel format */ /* Convert picture to ARGB8888 pixel format */
for(index=0; index < height; index++) for(index=0; index < height; index++)
{ {
/* Pixel format conversion */ /* Pixel format conversion */
LL_ConvertLineToARGB8888((uint32_t *)pbmp, (uint32_t *)address, width, input_color_mode); LL_ConvertLineToARGB8888((uint32_t *)pbmp, (uint32_t *)address, width, input_color_mode);
/* Increment the source and destination buffers */ /* Increment the source and destination buffers */
address+= (BSP_LCD_GetXSize()*4); address += (BSP_LCD_GetXSize()*4);
pbmp -= width*(bit_pixel/8); pbmp -= row_size;
} }
} }
/** /**

View File

@@ -43,7 +43,7 @@
/** @addtogroup STM32746G_DISCOVERY /** @addtogroup STM32746G_DISCOVERY
* @{ * @{
*/ */
/** @addtogroup STM32746G_DISCOVERY_LCD /** @addtogroup STM32746G_DISCOVERY_LCD
* @{ * @{
*/ */

View File

@@ -99,6 +99,8 @@
#define LWIP_HTTPD_CUSTOM_FILES 1 #define LWIP_HTTPD_CUSTOM_FILES 1
/*----- Value in opt.h for HTTPD_USE_CUSTOM_FSDATA: 0 -----*/ /*----- Value in opt.h for HTTPD_USE_CUSTOM_FSDATA: 0 -----*/
#define HTTPD_USE_CUSTOM_FSDATA 1 #define HTTPD_USE_CUSTOM_FSDATA 1
/*----- Default Value for LWIP_TFTP: 0 ---*/
#define LWIP_TFTP 1
/*----- Value in opt.h for LWIP_STATS: 1 -----*/ /*----- Value in opt.h for LWIP_STATS: 1 -----*/
#define LWIP_STATS 0 #define LWIP_STATS 0
/*----- Value in opt.h for CHECKSUM_GEN_IP: 1 -----*/ /*----- Value in opt.h for CHECKSUM_GEN_IP: 1 -----*/

View File

@@ -0,0 +1,435 @@
/**
*
* @file tftp_server.c
*
* @author Logan Gunthorpe <logang@deltatee.com>
* Dirk Ziegelmeier <dziegel@gmx.de>
*
* @brief Trivial File Transfer Protocol (RFC 1350)
*
* Copyright (c) Deltatee Enterprises Ltd. 2013
* All rights reserved.
*
*/
/*
* Redistribution and use in source and binary forms, with or without
* modification,are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Logan Gunthorpe <logang@deltatee.com>
* Dirk Ziegelmeier <dziegel@gmx.de>
*
*/
/**
* @defgroup tftp TFTP server
* @ingroup apps
*
* This is simple TFTP server for the lwIP raw API.
*/
#include "lwip/apps/tftp_server.h"
#if LWIP_UDP
#include "lwip/udp.h"
#include "lwip/timeouts.h"
#include "lwip/debug.h"
#define TFTP_MAX_PAYLOAD_SIZE 512
#define TFTP_HEADER_LENGTH 4
#define TFTP_RRQ 1
#define TFTP_WRQ 2
#define TFTP_DATA 3
#define TFTP_ACK 4
#define TFTP_ERROR 5
enum tftp_error {
TFTP_ERROR_FILE_NOT_FOUND = 1,
TFTP_ERROR_ACCESS_VIOLATION = 2,
TFTP_ERROR_DISK_FULL = 3,
TFTP_ERROR_ILLEGAL_OPERATION = 4,
TFTP_ERROR_UNKNOWN_TRFR_ID = 5,
TFTP_ERROR_FILE_EXISTS = 6,
TFTP_ERROR_NO_SUCH_USER = 7
};
#include <string.h>
struct tftp_state {
const struct tftp_context *ctx;
void *handle;
struct pbuf *last_data;
struct udp_pcb *upcb;
ip_addr_t addr;
u16_t port;
int timer;
int last_pkt;
u16_t blknum;
u8_t retries;
u8_t mode_write;
};
static struct tftp_state tftp_state;
static void tftp_tmr(void *arg);
static void
close_handle(void)
{
tftp_state.port = 0;
ip_addr_set_any(0, &tftp_state.addr);
if (tftp_state.last_data != NULL) {
pbuf_free(tftp_state.last_data);
tftp_state.last_data = NULL;
}
sys_untimeout(tftp_tmr, NULL);
if (tftp_state.handle) {
tftp_state.ctx->close(tftp_state.handle);
tftp_state.handle = NULL;
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n"));
}
}
static void
send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str)
{
int str_length = strlen(str);
struct pbuf *p;
u16_t *payload;
p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM);
if (p == NULL) {
return;
}
payload = (u16_t *) p->payload;
payload[0] = PP_HTONS(TFTP_ERROR);
payload[1] = lwip_htons(code);
MEMCPY(&payload[2], str, str_length + 1);
udp_sendto(tftp_state.upcb, p, addr, port);
pbuf_free(p);
}
static void
send_ack(u16_t blknum)
{
struct pbuf *p;
u16_t *payload;
p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM);
if (p == NULL) {
return;
}
payload = (u16_t *) p->payload;
payload[0] = PP_HTONS(TFTP_ACK);
payload[1] = lwip_htons(blknum);
udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port);
pbuf_free(p);
}
static void
resend_data(void)
{
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM);
if (p == NULL) {
return;
}
if (pbuf_copy(p, tftp_state.last_data) != ERR_OK) {
pbuf_free(p);
return;
}
udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port);
pbuf_free(p);
}
static void
send_data(void)
{
u16_t *payload;
int ret;
if (tftp_state.last_data != NULL) {
pbuf_free(tftp_state.last_data);
}
tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM);
if (tftp_state.last_data == NULL) {
return;
}
payload = (u16_t *) tftp_state.last_data->payload;
payload[0] = PP_HTONS(TFTP_DATA);
payload[1] = lwip_htons(tftp_state.blknum);
ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE);
if (ret < 0) {
send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file.");
close_handle();
return;
}
pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret));
resend_data();
}
static void
recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
u16_t *sbuf = (u16_t *) p->payload;
int opcode;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(upcb);
if (((tftp_state.port != 0) && (port != tftp_state.port)) ||
(!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported");
pbuf_free(p);
return;
}
opcode = sbuf[0];
tftp_state.last_pkt = tftp_state.timer;
tftp_state.retries = 0;
switch (opcode) {
case PP_HTONS(TFTP_RRQ): /* fall through */
case PP_HTONS(TFTP_WRQ): {
const char tftp_null = 0;
char filename[TFTP_MAX_FILENAME_LEN + 1];
char mode[TFTP_MAX_MODE_LEN + 1];
u16_t filename_end_offset;
u16_t mode_end_offset;
if (tftp_state.handle != NULL) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported");
break;
}
sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL);
/* find \0 in pbuf -> end of filename string */
filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2);
if ((u16_t)(filename_end_offset - 1) > sizeof(filename)) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated");
break;
}
pbuf_copy_partial(p, filename, filename_end_offset - 1, 2);
/* find \0 in pbuf -> end of mode string */
mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset + 1);
if ((u16_t)(mode_end_offset - filename_end_offset) > sizeof(mode)) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated");
break;
}
pbuf_copy_partial(p, mode, mode_end_offset - filename_end_offset, filename_end_offset + 1);
tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ));
tftp_state.blknum = 1;
if (!tftp_state.handle) {
send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file.");
break;
}
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read"));
ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr);
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode));
ip_addr_copy(tftp_state.addr, *addr);
tftp_state.port = port;
if (opcode == PP_HTONS(TFTP_WRQ)) {
tftp_state.mode_write = 1;
send_ack(0);
} else {
tftp_state.mode_write = 0;
send_data();
}
break;
}
case PP_HTONS(TFTP_DATA): {
int ret;
u16_t blknum;
if (tftp_state.handle == NULL) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection");
break;
}
if (tftp_state.mode_write != 1) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection");
break;
}
blknum = lwip_ntohs(sbuf[1]);
if (blknum == tftp_state.blknum) {
pbuf_remove_header(p, TFTP_HEADER_LENGTH);
ret = tftp_state.ctx->write(tftp_state.handle, p);
if (ret < 0) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file");
close_handle();
} else {
send_ack(blknum);
}
if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) {
close_handle();
} else {
tftp_state.blknum++;
}
} else if ((u16_t)(blknum + 1) == tftp_state.blknum) {
/* retransmit of previous block, ack again (casting to u16_t to care for overflow) */
send_ack(blknum);
} else {
send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number");
}
break;
}
case PP_HTONS(TFTP_ACK): {
u16_t blknum;
int lastpkt;
if (tftp_state.handle == NULL) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection");
break;
}
if (tftp_state.mode_write != 0) {
send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection");
break;
}
blknum = lwip_ntohs(sbuf[1]);
if (blknum != tftp_state.blknum) {
send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number");
break;
}
lastpkt = 0;
if (tftp_state.last_data != NULL) {
lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH);
}
if (!lastpkt) {
tftp_state.blknum++;
send_data();
} else {
close_handle();
}
break;
}
default:
send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation");
break;
}
pbuf_free(p);
}
static void
tftp_tmr(void *arg)
{
LWIP_UNUSED_ARG(arg);
tftp_state.timer++;
if (tftp_state.handle == NULL) {
return;
}
sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL);
if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) {
if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) {
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n"));
resend_data();
tftp_state.retries++;
} else {
LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n"));
close_handle();
}
}
}
/** @ingroup tftp
* Initialize TFTP server.
* @param ctx TFTP callback struct
*/
err_t
tftp_init(const struct tftp_context *ctx)
{
err_t ret;
/* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */
struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
if (pcb == NULL) {
return ERR_MEM;
}
ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT);
if (ret != ERR_OK) {
udp_remove(pcb);
return ret;
}
tftp_state.handle = NULL;
tftp_state.port = 0;
tftp_state.ctx = ctx;
tftp_state.timer = 0;
tftp_state.last_data = NULL;
tftp_state.upcb = pcb;
udp_recv(pcb, recv, NULL);
return ERR_OK;
}
/** @ingroup tftp
* Deinitialize ("turn off") TFTP server.
*/
void tftp_cleanup(void)
{
LWIP_ASSERT("Cleanup called on non-initialized TFTP", tftp_state.upcb != NULL);
udp_remove(tftp_state.upcb);
close_handle();
memset(&tftp_state, 0, sizeof(tftp_state));
}
#endif /* LWIP_UDP */

View File

@@ -33,7 +33,7 @@ LTDC.WindowX1_L1=480
LTDC.WindowY1_L0=272 LTDC.WindowY1_L0=272
LTDC.WindowY1_L1=272 LTDC.WindowY1_L1=272
LWIP.BSP.number=1 LWIP.BSP.number=1
LWIP.IPParameters=LWIP_DHCP,IP_ADDRESS,NETMASK_ADDRESS,LWIP_HTTPD,LWIP_HTTPD_CUSTOM_FILES,LWIP_HTTPD_CGI_SSI,LWIP_HTTPD_SSI,LWIP_HTTPD_SSI_RAW,LWIP_DNS,MEMP_MEM_MALLOC,LWIP_IGMP,LWIP_HTTPD_CGI,LWIP_HTTPD_SUPPORT_POST,MEM_LIBC_MALLOC LWIP.IPParameters=LWIP_DHCP,IP_ADDRESS,NETMASK_ADDRESS,LWIP_HTTPD,LWIP_HTTPD_CUSTOM_FILES,LWIP_HTTPD_CGI_SSI,LWIP_HTTPD_SSI,LWIP_HTTPD_SSI_RAW,LWIP_DNS,MEMP_MEM_MALLOC,LWIP_IGMP,LWIP_HTTPD_CGI,LWIP_HTTPD_SUPPORT_POST,MEM_LIBC_MALLOC,LWIP_TFTP
LWIP.IP_ADDRESS=192.168.069.010 LWIP.IP_ADDRESS=192.168.069.010
LWIP.LWIP_DHCP=0 LWIP.LWIP_DHCP=0
LWIP.LWIP_DNS=1 LWIP.LWIP_DNS=1
@@ -45,6 +45,7 @@ LWIP.LWIP_HTTPD_SSI=1
LWIP.LWIP_HTTPD_SSI_RAW=1 LWIP.LWIP_HTTPD_SSI_RAW=1
LWIP.LWIP_HTTPD_SUPPORT_POST=1 LWIP.LWIP_HTTPD_SUPPORT_POST=1
LWIP.LWIP_IGMP=1 LWIP.LWIP_IGMP=1
LWIP.LWIP_TFTP=1
LWIP.MEMP_MEM_MALLOC=1 LWIP.MEMP_MEM_MALLOC=1
LWIP.MEM_LIBC_MALLOC=1 LWIP.MEM_LIBC_MALLOC=1
LWIP.NETMASK_ADDRESS=255.255.255.000 LWIP.NETMASK_ADDRESS=255.255.255.000