Compare commits

...

494 Commits

Author SHA1 Message Date
5c429ec894 Remove trailing whitespace 2024-03-24 14:13:56 +01:00
62ef147105 Incrment Cmake required version number 2024-03-24 14:11:33 +01:00
c6038969ca Fix style and code issues in bin2carray python script 2023-06-23 22:43:45 +02:00
0c8a0cd562 Fix watchdog tcode to write correct reload value 2023-06-09 00:12:41 +02:00
1300fe88a4 Shorten wtchdog trigger interval to 1.25 seconds nominal. This will ensure the internal watchdog triggers before the external one 2023-06-09 00:04:32 +02:00
df593e2ab2 Merge pull request 'misc-crc-monitor' () from misc-crc-monitor into dev
Reviewed-on: 
2023-05-23 19:07:21 +02:00
34ad930bd8 Fix mask for misc crc cfg monitor 2023-05-23 19:03:50 +02:00
1c1874abf1 Make safety flag ERR_FLAG_CFG_CRC_MISC trigger panic mode 2023-05-23 18:46:27 +02:00
fd2994f9b9 Add err flag cfg crc misc to flag list 2023-05-23 18:32:03 +02:00
b6befa70a2 Implement misc CRC monitor to supervise clocks and other system settings 2023-05-23 18:30:27 +02:00
dd6a7bef18 Merge pull request 'Pre-Release v0.5' () from dev into master
Reviewed-on: 
2023-01-03 16:37:53 +01:00
a005afaa13 Merge pull request 'Update FatFS in Firmware and Updater RAM Blob' () from update-fatfs into dev
Reviewed-on: 
2023-01-03 16:32:21 +01:00
cadd33d5a4 : Update FatFS in RAM code of updater 2023-01-03 15:08:57 +01:00
da132028b1 Issue : Update FatFS of main firmware to R0.15 2023-01-03 15:02:48 +01:00
2cd4847a57 Merge pull request 'version-rework' () from version-rework into dev
Reviewed-on: 
2023-01-01 21:23:32 +01:00
e335cb42ac Add comment to cmake build step 2023-01-01 21:16:36 +01:00
34c1c3db4e Rework UI to use newly created version handling 2023-01-01 21:12:19 +01:00
df70238b36 Remove git_ver define from updater 2023-01-01 21:12:00 +01:00
2c2e4c1484 Add compile date and time to version.c 2023-01-01 21:07:10 +01:00
767aa75c25 Make git a required build dependency 2023-01-01 21:04:03 +01:00
745e7db78f Add version c file that includes a generated file during build 2023-01-01 21:02:49 +01:00
9c0cbb107b Add script to generate header file containing version and commit hash 2023-01-01 20:45:57 +01:00
d48ccf1612 Fix : Enable core cycle counter 2023-01-01 20:18:39 +01:00
fd12faff75 Merge pull request 'Update develop. Ready for pre-release v0.4' () from dev into master
Reviewed-on: 
2022-12-31 20:39:51 +01:00
5ad1d574ff Fix : Fix update bug of GUI. Works now 2022-12-31 20:38:22 +01:00
f95ad1729e Fix buf on sd mounting handling 2022-12-31 20:29:22 +01:00
b18186423f Fix : Add SD status to GUI 2022-12-31 20:22:41 +01:00
ec2d3da4cb Add missing header file required for memset() 2022-12-31 20:22:08 +01:00
5e00441d99 Add separate source file handling the mounting of the SD card. This will give proper access to the GUI to check whether an SD is mounted 2022-12-31 20:18:34 +01:00
e91b33f379 Remove old CRC patcher 2022-12-31 19:56:33 +01:00
b621c66378 Update Flag Weights
* Fix : Update flash and data CRCs to trigger panic mode
* Update meas ADC CRC flag to stop PID
* Update safety ADC CRC flag to trigger panic mode
2022-12-31 19:53:45 +01:00
8ff402caaa Merge branch 'dev' of git.shimatta.de:mhu/reflow-oven-control-sw into dev 2022-12-31 19:43:41 +01:00
aade3288eb Update doxygen headers in config parser 2022-12-31 19:43:37 +01:00
049afbd66f Merge pull request 'Use patchelfcrc program for CRC patching.' () from port-to-patchelfcrc into dev
Reviewed-on: 
2022-12-31 19:42:54 +01:00
240b1ffc8f Update gitignore for use with vscode and clangd 2022-12-31 19:25:55 +01:00
f46044e5fc Remove mthumb-interwork from GCC command line. It is not neededfor CM4 cores 2022-12-31 19:24:27 +01:00
354c26ca67 Change Build step to use pathcelfcrc program instead of python script 2022-10-25 21:23:02 +02:00
6570d217c7 Separate flash CRC checker from safety controller and implement shell command to calculate CRCs 2022-09-22 21:16:41 +02:00
aeffb9df99 Update C file generator script 2022-09-22 21:16:07 +02:00
ad3de6e6b7 Improve HW version detect code. Funtionally equivalent 2022-08-09 00:23:55 +02:00
ab5fd6433e Rename python file to snake case 2022-08-09 00:23:23 +02:00
35542f56cb Add pylintrc and fix style problems in crc patcher 2022-08-09 00:21:57 +02:00
f9b9a3c685 Add compile error for configuration mistake 2022-07-30 16:45:26 +02:00
aaed95cc95 Restructure safety handle function. Now returns worst flag state set. Used to blink LED 2022-07-30 16:04:46 +02:00
6ac108e1b2 make LED blink if error that stop the PID are present 2022-07-30 15:53:04 +02:00
7a36b597be Add comment to function 2022-07-30 15:52:47 +02:00
00b8d1f48e Fix style issues in config-parser.c 2022-07-16 15:14:35 +02:00
8ac1d52240 Fix style issues in spi-eeprom.c/h 2022-07-16 15:09:41 +02:00
3e82cf69b4 Fix style in settings-sd-card.c 2022-07-16 15:07:33 +02:00
62b256fd18 Fix style in settings-sd-card.c 2022-07-16 15:07:01 +02:00
74111826a0 Fix style in settings-eeprom.c 2022-07-16 15:04:09 +02:00
69d7724c8f Fix style problems in settings.c 2022-07-16 14:46:44 +02:00
48f69d0fb5 Fix style issues in watchdog.c 2022-07-16 14:44:55 +02:00
8fd924829e Fix style problems in stack-check.c 2022-07-16 14:43:29 +02:00
ba8072c21d Fix style problems in safety-memory.c 2022-07-16 14:40:54 +02:00
5ddae7efee Fiy style issues 2022-07-16 13:01:38 +02:00
14ea4d22fe Fix style issues in STM peripheral drivers 2022-07-16 12:46:52 +02:00
d5780500f3 Update C-style checker 2022-07-16 12:38:37 +02:00
d4d654e8dd Add additional debug info to version command and add CPU cycle counter to cc instruction's output 2022-07-13 19:47:16 +02:00
8a62ed2ea7 Fix wrong short shell command for setting baudrate 2022-06-09 18:44:39 +02:00
7d43b4130c Add connector info to LCD GUI. So TX and RX of UART can be found without looking at the schematic. 2022-06-09 18:18:30 +02:00
835faf7e4e Merge pull request 'enhancement/39-digio-cmd-profile-language' () from enhancement/39-digio-cmd-profile-language into dev
Reviewed-on: 
2021-12-26 21:20:15 +01:00
2957a42cef Fix indetation in header file 2021-12-26 20:59:08 +01:00
1e45c8b5d7 Issue : Implement DIGIO profile commands 2021-12-26 20:54:04 +01:00
3bb4607798 digio: Make digio check if an port to set is an output port. 2021-12-26 20:40:28 +01:00
a8a622df25 Make temperture profile executer reset the DIGIO settings after profile execution/abort 2021-12-26 20:36:49 +01:00
45f91a7c5a Add commands for DIGIO channels to profile parser and add base construct to the profile interpreter 2021-12-26 20:27:20 +01:00
bf6a222c9d Merge branch 'feature/42-update-fatfs' of mhu/reflow-oven-control-sw into dev 2021-12-16 20:55:34 +01:00
ef534746f8 Update updater to newest fatfs and enable exfat support 2021-12-16 20:47:08 +01:00
8cd47aeed5 Add new FatFS implementation 2021-12-16 20:41:10 +01:00
1291b0fb6a Add FatFS license 2021-12-16 20:28:39 +01:00
b6a2790a59 cleanup code and write a little documentation 2021-11-28 23:40:43 +01:00
7bfa0732db Fix wrong register bit in flash writer. This actually didn't result in an error but it's better to fix it either way. 2021-11-28 23:11:40 +01:00
0dace23021 Bugfix: Fix null pointer access in temp profile parser 2021-11-27 19:24:51 +01:00
c78477296a Bugfix: Fix hardfault when update menu is opened and no hex file is located on disk 2021-11-27 18:47:17 +01:00
96e0931c9f Add a bunch of stuff: Add baudrate reconfig command to shell and move the uart to separate C file 2021-11-27 17:41:11 +01:00
6b9b7d78a0 Add v1.3.1 to supported hardware revisions 2021-10-24 21:59:44 +02:00
22bb227bc7 Add a few comments 2021-10-24 14:50:07 +02:00
78f24f7338 Add LCD output to shell function 'Emulate UI' 2021-10-24 14:47:52 +02:00
e3a552248d Make a wrong size of the flashcrc struct an error becuase it might lead to misaligned CRCs in the structure 2021-10-23 21:26:01 +02:00
288b19c4fc Comment functions 2021-10-23 21:18:32 +02:00
56872086fa Comment code 2021-10-23 21:14:24 +02:00
fe0e8136d4 Refactor temperature profile executer 2021-10-23 21:00:21 +02:00
73606bf7a0 Write documentation for the config parser 2021-10-23 20:54:37 +02:00
78501143cc Fix wrongly typed float literal 2021-10-23 20:54:20 +02:00
bb0ea908cb Merge branch 'brown-out-detection' into dev 2021-10-17 12:52:59 +02:00
61cb92fbe8 Add command for printing option bytes 2021-10-17 12:30:58 +02:00
eb41e5e210 Implement option byte writing and set brown out level 2021-10-16 23:39:23 +02:00
decb484d06 Start implementation of option byte manipulation 2021-10-16 00:44:39 +02:00
4009a2794d Add STM device resvision to MOTD. 2021-10-15 22:06:30 +02:00
d9c145ec81 Fix some coding issues and a possible race condition 2021-10-15 21:16:26 +02:00
6fde4cfd66 Improve doxygen comments in code. 2021-10-11 19:45:13 +02:00
c82ca7d8f0 Merge branch 'jenkins' into dev 2021-10-10 22:41:00 +02:00
2bc2c0c670 Add example jenkins file 2021-10-10 22:38:58 +02:00
aad9be9905 Add doxygen to CMake and update the config 2021-10-10 22:09:46 +02:00
6f2b6e0839 Fix code in updater.c 2021-10-10 21:04:40 +02:00
45145c1f36 Clean up systick.c 2021-10-10 21:02:39 +02:00
1722ba7e5d Clean up shell.c 2021-10-10 21:00:28 +02:00
7a44a383ff Fix style in file 2021-10-10 20:49:42 +02:00
7a2c77a83e Fix style problems in main-cycle-counter 2021-10-10 20:47:15 +02:00
c8e3bf5de2 Fix style problems in main.c 2021-10-10 20:45:59 +02:00
400c77f11c Update c style checker 2021-10-10 20:42:15 +02:00
7be6047e04 Fix style warnings 2021-10-10 20:40:40 +02:00
2ab7257fe6 Remove unneeded parameter from fuction 2021-10-09 22:59:35 +02:00
376d9c7aaf Merge branch 'dev' of git.shimatta.de:mhu/reflow-oven-control-sw into dev 2021-10-03 19:38:47 +02:00
2a6a98deac Merge branch 'feature/41-updater-sha256-check' into dev 2021-10-03 19:38:31 +02:00
20b460cd5a Fix : Updater SHA256 check implemented and tested 2021-10-03 19:38:01 +02:00
ae60c30919 Implement SHA256 update file checking 2021-10-03 19:27:41 +02:00
c6fcd3154f Remove unneeded variable 2021-10-03 18:51:14 +02:00
a7394ef170 Feature : Add SHA calculation to updater. Has yet to be checked against file. Code not tested 2021-09-24 22:43:47 +02:00
01abb3e085 Delete unnecessary code for testing CRCs 2021-09-21 10:14:25 +02:00
d63761d016 Add sha 256 library and adapt license sections in documentation 2021-08-24 22:19:12 +02:00
d468e52dea Merge branch 'feature/40-fir-filter' into dev 2021-08-24 21:51:20 +02:00
5a1deeb9ee Reformat code 2021-08-24 21:50:57 +02:00
809c86a618 Add shell command to change filter alpha 2021-08-24 21:50:36 +02:00
88a4bb97a5 Remove fior filter again... Not needed. 2021-08-24 21:49:23 +02:00
4a98d41623 Add sample data and jupyter notebook containing filter analysis 2021-08-24 21:48:04 +02:00
836c7af163 Merge branch 'dev' into feature/40-fir-filter 2021-08-19 21:47:11 +02:00
e3670434ca Add FIR filter code 2021-08-19 21:44:50 +02:00
a802b5c1b5 Add main cylcle counter and increase filter alpha for PT1000 to 0.01 2021-08-19 21:25:04 +02:00
ffb544e21d Merge branch 'issue/37-crc-flags-config-regs' into dev 2021-07-23 20:06:35 +02:00
e4ebf9ec3f Add CRC monitoring over ADC registers 2021-07-23 20:06:09 +02:00
6e89c0e098 Update error memory viewer to newest memory structure 2021-07-19 22:44:13 +02:00
fdb1c6e893 Fix memory checking. The stack is now completely copied to CCMRAM before testing the main memory. 2021-07-19 22:29:13 +02:00
e753504ae3 Check for python in RAM code and use find_package to determine the python interpreter 2021-07-17 15:25:25 +02:00
2fa12cda60 Throw error in case the python virtualenv cannot be found 2021-07-17 15:12:45 +02:00
17609a2491 Add automatic flash CRC patching to cmake 2021-07-16 21:57:30 +02:00
1e870972e3 Improve code and add a Flash CRC check 2021-07-16 21:17:59 +02:00
864c3fa0f2 Fix bug in handling of error memory NOP entries 2021-07-16 17:29:04 +02:00
9c872f6746 Improve documentation and beatify pieces of code 2021-07-15 19:50:14 +02:00
0bf587b8bb Add documentation in rst for PID 2021-07-15 00:21:14 +02:00
8a9bd0df6e Add documentation for reflow controller 2021-07-15 00:20:03 +02:00
baf6b67658 Fix : List with updae filename was freed before it was used. This is now fixed and working 2021-07-13 21:05:00 +02:00
41fbb83b46 Fix : Broken PID derivate term calculation. Sign error fixed 2021-07-13 20:32:12 +02:00
f4fcaf1e3a Start documentation of PID controller 2021-06-14 23:16:07 +02:00
67932bf465 Fix aligment problems in Linkerscript 2021-05-24 12:38:37 +02:00
632973cdac Update docu about calibration 2021-05-22 17:52:55 +02:00
9558d4bb45 Write hardware documentation 2021-05-22 17:36:09 +02:00
90c6165278 Move push button and rotary encoder files to UI folder 2021-05-22 17:05:56 +02:00
8c0cfa4993 Doxygen headers 2021-05-22 17:02:37 +02:00
5f91659d04 Doxygen headers 2021-05-22 16:46:26 +02:00
fdb3ceb3e9 Restructuring and comments 2021-05-22 16:40:08 +02:00
7e3d2d1d0b Expand documentation 2021-05-22 15:27:55 +02:00
ef2cd6acfe Change doxygen config 2021-05-22 15:26:39 +02:00
d9bd434dc6 Fix indent 2021-05-22 12:45:46 +02:00
4ed2203b35 Improve code style and comments 2021-05-22 12:44:43 +02:00
0b1ce8b614 Fix :
* Implement clear flags command for profile language.
2021-05-22 12:13:43 +02:00
bc5e4c14df Issue : Implement startup screen in case apanic happened and prevent the PID controller from starting when a watchdog reset has occured 2021-05-22 11:59:54 +02:00
43abca4c51 Merge branch 'memory-test' into dev 2021-05-22 11:41:45 +02:00
00c796c58f Merge branch 'memory-test' of mhu/reflow-oven-control-sw into dev 2021-05-22 11:41:22 +02:00
4d0f963585 Merge branch 'dev' into memory-test 2021-05-22 11:35:03 +02:00
708fdea058 Add static blocking write function to gui. This allows us to set a updating... status on the display when starting the updater. 2021-05-22 11:34:33 +02:00
ebb1383957 Write memory test for system RAM 2021-05-22 11:25:55 +02:00
3345004213 Merge branch 'dev' into memory-test 2021-05-22 00:23:18 +02:00
afadd539c8 Merge branch '28-update-notification' of mhu/reflow-oven-control-sw into dev 2021-05-22 00:17:01 +02:00
71315b7c92 Issue : Implement update successful notification. 2021-05-22 00:14:56 +02:00
410a5d4dd1 Change -Og to -O0 because it made a lot of problems when debugging 2021-05-22 00:13:07 +02:00
528db7a581 Fix error in CCM Ram test 2021-05-22 00:06:51 +02:00
384e127085 Add first draft of memory checking for CCM RAM 2021-05-20 23:55:32 +02:00
fe0bde5c32 Fix wrong string constant 2021-05-20 23:54:42 +02:00
2beaccbe32 Fix typo in comment 2021-05-20 23:54:21 +02:00
b6760ff426 Merge branch 'issue/24-update-could-fail' of mhu/reflow-oven-control-sw into dev 2021-05-16 20:41:56 +02:00
1b2dac21f2 Merge branch 'issue/25-add-update-to-gui' of mhu/reflow-oven-control-sw into dev 2021-05-16 20:40:39 +02:00
97f154d3b9 Add working reflow profile so it isn't lost by accident 2021-05-16 20:38:17 +02:00
ee5dda4a33 Issue : Add update menu to GUI 2021-05-16 20:34:09 +02:00
afb8e93b13 Rework function for finding temperature profiles to be able to search for any pattern 2021-05-16 19:57:08 +02:00
9bd0dd194b Issue : Fix bug in update code 2021-05-16 19:53:46 +02:00
6322c3728b Use singly linked list to store profile commands. 2021-05-15 21:58:00 +02:00
174bf4220e Remove unused function 2021-05-15 21:57:23 +02:00
566436201e Increase heap size 2021-05-15 21:56:33 +02:00
61e3b58992 Use singly linked list dfor temperature profile file list 2021-05-07 22:09:55 +02:00
01b445a0fb Update linked list library and include it into build 2021-04-10 22:35:30 +02:00
5437a323c3 Add linklist submodule 2021-04-10 22:29:18 +02:00
28e42d3306 Shell: Update: Print error if no update file name is specified 2021-04-10 22:28:30 +02:00
08606689b4 Update fatfs in main application 2021-04-10 20:35:33 +02:00
5776feee85 Merge branch 'dev' of git.shimatta.de:mhu/reflow-oven-control-sw into dev 2021-04-10 20:13:29 +02:00
6273c68821 Shell update command: Take file name as argument 2021-04-10 20:09:52 +02:00
3381840bba Modify git version generation in cmake 2021-04-10 20:09:15 +02:00
cf35ba735f Modify git version generation in cmake 2021-04-10 19:40:49 +02:00
3f31acfada Updater: Fix missing line break in uart output 2021-04-10 15:42:19 +02:00
77251cc1bc increase stack and heap sizes 2021-04-10 14:44:27 +02:00
f2972903d5 Use safer string copying in gui for file list 2021-04-10 14:37:51 +02:00
31b17dfd8d Updater: Clear shell at startup and print size of update 2021-04-10 14:37:05 +02:00
9f1a791be2 Remove custom option checker and use the one of the shellmatta instead 2021-04-10 14:10:17 +02:00
54416a6350 Edit Cmake file to use ENV variable to device if Uart is on debug header or not 2021-04-10 13:45:00 +02:00
9c94428144 Bugfix: button ready state not correctly detected when menu drops back 2021-04-10 13:24:15 +02:00
81155887de Bug: Fix missing variable in printf varargs for gui 2021-04-10 13:11:35 +02:00
8309cef5ec Updater: Fix updating code 2021-04-08 22:03:38 +02:00
1a76a69b6d Switch updater to -Os compilation 2021-04-08 21:50:42 +02:00
e50e3f0ace Add verify step to updater 2021-04-08 21:49:53 +02:00
5fb1612773 make updater reboot after successful update 2021-04-08 21:37:49 +02:00
72735915ee Clear code updated status flag upon startup 2021-04-08 21:35:19 +02:00
08ec458e8f Add update code to updater and use uart for status updates 2021-04-08 21:23:25 +02:00
d962110823 Updater: Use -O0 and write flash writer and fix hex parser 2021-04-07 23:14:45 +02:00
bfdc3d3246 Updater: Store update file name in safety memory before executing updater. Currently name is hardcoded. 2021-04-07 13:26:39 +02:00
dca839ce2e Merge branch 'dev' into updater 2021-04-07 13:19:53 +02:00
eea0826c7b updater: Add function to safety memory for storing the update file name 2021-04-07 13:19:16 +02:00
6e5627fde2 Updater: Add safety memory to updater 2021-04-06 20:55:41 +02:00
0f239dc39d Fix warning in temp profile parser 2021-04-06 20:53:18 +02:00
08eee66d30 Issue : Change GUI of profile executer 2021-04-06 19:46:31 +02:00
7c9d296e34 Merge branch 'dev' into feature/28-profile-parser 2021-04-06 19:45:37 +02:00
533656ca28 Add Cmake variable for Uart on debug header in release and use -Og for debugbuild instead of -O0 2021-04-06 19:25:25 +02:00
d146b10569 Issue : Inmprove GUI of profile executer 2021-04-06 19:23:45 +02:00
8576bf4231 Merge branch 'dev' into feature/28-profile-parser 2021-04-04 19:35:52 +02:00
6ebd74cb31 Safety Bug: Add meas ADC timing flag to output of the pt1000 read function so it becomes invalid in this case. 2021-04-04 19:35:32 +02:00
46125ba752 Issue : Implement first working draft of temperature profile GUI 2021-04-04 19:34:13 +02:00
6c9f90c986 Issue : Fix buf in profile executer 2021-04-04 19:33:33 +02:00
74defd5384 Add main loop cycle counter for debugging 2021-04-04 19:32:44 +02:00
5deac33949 Implement basic gui for profile selection. Still doesn't do anything 2021-04-04 17:43:31 +02:00
666353e3b7 Merge branch 'dev' into feature/28-profile-parser 2021-04-04 17:01:51 +02:00
df40ab1be7 Update base64 lib submodule 2021-03-23 22:19:43 +01:00
4c3574c2e2 Make project Cmake ready 2021-03-23 22:15:11 +01:00
289f49204d fisr draft of cmake buidl system. Update generation still missing 2021-03-21 22:38:22 +01:00
4bc98e6baf Merge branch 'dev' into feature/28-profile-parser 2021-03-21 21:08:38 +01:00
e50ce0d541 Add pictures of external watchdog 2021-03-21 21:08:19 +01:00
78b63c853f Issue : Start GUI for Temp Profile execution 2021-03-21 21:07:54 +01:00
a25b249d77 Issue : Improve script handling 2021-03-21 19:21:36 +01:00
e815442617 Pid Controller: Set integral term lower boundary to 0 2021-03-21 19:18:08 +01:00
60104df30e Issue : Write temperture ramp command 2021-03-20 01:02:33 +01:00
5ab911b4b6 Merge branch 'dev' into feature/28-profile-parser 2021-03-19 20:55:00 +01:00
9c37e083a0 Merge branch 'error-mem-viewer' into dev
* This is a preliminary version of hte error memory viewer
2021-03-19 20:54:32 +01:00
08427cc589 Merge branch 'dev' into feature/28-profile-parser 2021-03-19 20:53:58 +01:00
62d745bd3a Fix doxygen header 2021-03-19 20:53:46 +01:00
ba6e0880b4 Merge branch 'dev' into feature/28-profile-parser 2021-03-19 20:52:13 +01:00
ec2c23c9f7 Change unstbale detection range from 10 Ohm to 20 Ohm 2021-03-19 20:51:54 +01:00
6a71416d2a Add void casts to unused parameters 2021-03-19 20:24:49 +01:00
1ecd5edd93 Add temperature profile executer and add shell command 2021-03-19 20:19:37 +01:00
1b4eba1871 Write parser for temp profile language. Not yet tested. 2021-03-19 16:58:14 +01:00
13e7cbfd81 Documentation: Fix docu of overtemp flag 2021-03-18 23:21:17 +01:00
857838f293 Docu: Improvements 2021-03-18 23:18:18 +01:00
ae97a69d26 documentation 2021-03-18 23:15:13 +01:00
001f2be176 Add a few flags to the documentation 2021-03-18 23:12:44 +01:00
1797dac60b Systick: Correct comments 2021-03-18 22:53:11 +01:00
e3e4a6d926 Merge branch 'dev' into feature/28-profile-parser 2021-03-18 22:50:28 +01:00
dca696cd6a Safety: Fix different spelling mistakes for persistence 2021-03-18 22:50:13 +01:00
93ff4959a2 Issue : Start Temp profile parser 2021-03-18 22:44:05 +01:00
b1a7af28a2 Merge branch 'dev' into error-mem-viewer 2021-03-15 21:24:13 +01:00
b560a91673 Merge branch 'issue/26-overtemp-flag' of mhu/reflow-oven-control-sw into dev 2021-03-14 22:01:06 +01:00
64a97fa048 Issue : Add overtemp function to shell 2021-03-14 21:57:33 +01:00
d1b8e91674 Fix typo in linker script 2021-03-14 20:08:52 +01:00
0fc35db53d Merge branch 'dev' into issue/26-overtemp-flag 2021-02-15 20:36:13 +01:00
8a764f599b Remove cat command from shell 2021-02-15 20:35:54 +01:00
b9dfe35652 Issue : Add overtemp limit setting to settings module and load it from EEPROM at startup 2021-02-15 20:28:45 +01:00
694a78982a Add missing parameter to doxygen header of dc_pt1000_set_resistance_calibration() 2021-02-14 20:11:21 +01:00
59ff842f56 Merge branch 'dev' into error-mem-viewer 2021-02-14 20:09:20 +01:00
7c5b60ec6b : Add over temperature monitor settings to eeprom 2021-02-14 20:06:28 +01:00
e614eaa23b Correct version of EEPROM header for settings and write check for overtemperature 2021-02-02 20:50:30 +01:00
50ad31d58a Issue : Add configuration for overtemperature flag to safety controller and include the config in the memory checking 2021-02-02 20:35:45 +01:00
64bb06882f Issue : Add reverse lookup function to temp converter that converts a temperature to a PT1000 resistance value 2021-02-02 19:32:12 +01:00
0b01be9840 Issue : Add ERR_FLAG_OVERTEMP Error flag
* Add error flag
* Set default persistence to false
* Set default flag weight to stop PID controller
2021-02-02 18:40:52 +01:00
ba9247be69 Merge branch 'issue/24-Change-ERR_FLAG_MEAS_ADC_UNSTABLE' of mhu/reflow-oven-control-sw into dev 2021-01-26 22:49:54 +01:00
e7aa714976 Update documentation regarding Unstable flag 2021-01-26 22:48:19 +01:00
125b41de44 Fix Doxyfile 2021-01-26 22:46:44 +01:00
4c1797aa24 Issue : Make UNSTABLE flag only go away, if the PT1000 value stays within the stable region for a given amount of samples 2021-01-26 21:59:41 +01:00
20a65fd7f9 Issue : Implement new handling for Unstable flag.
* Unstable flag will now be set, whenever the output of the moving average filter
  differs more than 10 Ohms from the measured prefilterd input.
2021-01-26 21:46:44 +01:00
67b079fe33 Improve rport error function of safety controller 2021-01-26 21:46:33 +01:00
a5c9350835 Fix typo 2021-01-26 21:26:58 +01:00
cc545bfc69 Doxygen: use short names 2021-01-26 21:24:11 +01:00
f6fb541924 Update doxygen config 2021-01-25 22:31:00 +01:00
86a0b2087e Fix bug in weight handling of error flags. 2021-01-25 21:07:09 +01:00
55f35a5009 Edit doxygen headers and improve flag weight handling in safety controller 2021-01-25 20:59:48 +01:00
870c228e37 update shellmatta tonewest version with fixed history 2021-01-24 20:59:07 +01:00
2fcc5d6a9f Add further doxygen headers 2021-01-24 20:31:01 +01:00
52272938b7 update handling of analog monitors. Manually adding analog monotprs to the checking function is not necessary anymore 2021-01-24 20:27:07 +01:00
58c72fb2bc Add documentation to safety controller code 2021-01-24 20:17:53 +01:00
99d96fb426 Add kd_tau to oven PID parameters 2021-01-24 19:56:00 +01:00
24651fa74d Remove empty lines 2021-01-24 19:55:46 +01:00
56b5ddc209 Fix spelling and underline in shell command for error flags 2021-01-09 23:44:25 +01:00
94726e1466 Fix float notation 2021-01-09 23:44:15 +01:00
d6356de1b6 Fix calculation of safety ADC monitors. 2021-01-09 22:28:22 +01:00
69ff13a991 Add fast moving average filter for faster startup 2021-01-09 22:26:31 +01:00
bbfcd429fe Add SSR safety enable to oven driver 2021-01-09 21:59:59 +01:00
3a07347f48 Implement EEPROM and use it for saving the calibration 2021-01-08 18:39:54 +01:00
0e233a257c Initialize EEPROM in at start of program 2021-01-02 23:04:57 +01:00
95bd606dd8 Add functions for eeprom. Not yet implemented 2021-01-02 23:03:59 +01:00
6e3f90d38e Fix missing magic in SPI driver 2021-01-02 23:03:22 +01:00
82cab98f59 Update SPI driver 2021-01-02 20:28:01 +01:00
2d29857c2f Add SPI driver 2021-01-02 18:56:29 +01:00
bea8e2df74 Store error flags in error memory if they cause a panic event. 2021-01-02 02:37:59 +01:00
7c6205d20a Add supply voltage monitor to safety adc and safety controller 2021-01-01 19:48:53 +01:00
0e114d1344 Add default frequency to loudspeaker set 2021-01-01 19:48:31 +01:00
2c3c1c9861 Add external watchdog to safety controller for HW revision > 1.3 and Release Build 2021-01-01 18:04:14 +01:00
75f9c58c54 Fix bug: Invalid calibration loaded if no calibration is present on sd card 2021-01-01 17:31:35 +01:00
44c861a245 Merge branch 'updater' into dev 2021-01-01 17:29:46 +01:00
c01b7a9825 Fix broken hardware version detect. v1.3 is now correctly detected. 2021-01-01 17:28:38 +01:00
87c372d871 Add measurement results for v1.3 HW revision 2021-01-01 17:27:58 +01:00
3125e34922 Update jupyter notebook 2020-12-21 17:23:48 +01:00
fed18f1c24 Ram code: Update gitignore 2020-12-21 17:23:19 +01:00
caabde39d2 Updater RAM Code
* Add Fatfs for reading from SD card
* Add structure of Hex parser
2020-12-21 17:21:04 +01:00
1167358c5a Add .bin.h files to ram code's gitignore 2020-12-14 20:32:41 +01:00
444fded972 Delete derived ram code include file 2020-12-14 20:31:53 +01:00
963b1e106c Updater: Write functional ram code loader
Updater RAM Code
----------------
* Ack running watchdog every 250 ms
* Blink green LED every 250 ms

Firmware
--------
* Add RAM code loader
* Reorganize initialization
* Add update command to shell
2020-12-14 20:29:51 +01:00
0d861b1aed Safety Controller: Fix return type of function 2020-12-14 20:29:21 +01:00
9226f43cad Merge branch 'updater' into dev 2020-12-13 22:51:36 +01:00
2ff2d963c8 Add measuremnts of v1.2 hardware 2020-12-13 22:49:25 +01:00
d353183826 updater: Add script for converting bin file to C array 2020-12-07 22:35:52 +01:00
a3e652ddb8 Start RAM code for updater 2020-12-07 21:39:14 +01:00
c67298118e Improve GUI 2020-12-07 00:19:42 +01:00
abb333cfe7 Add drawio image for PT1000 processing 2020-12-04 20:55:57 +01:00
5a41e7815f Add script that allows building the sphinx documentation using a virtualenv 2020-12-04 19:42:53 +01:00
8a8004e187 Add generic function to detzermine reset cuase to rcc manager 2020-12-01 21:24:59 +01:00
b1271cee43 Doxygen 2020-12-01 21:03:05 +01:00
daaf848e0c Renamed clock-enable manager to rcc manager and improve some header files with doxygen comments 2020-12-01 21:00:23 +01:00
ef8e6231ff Issue : Implement Constant temperature function in GUI. This is useful to verify the oven parameters 2020-11-30 21:43:38 +01:00
cd35f9e694 Add low pass for Derviative part in PID controller 2020-11-30 21:40:28 +01:00
91d9db6a4e Make Safety ADC use sequnece feature of ADC and use DMA to write data 2020-11-30 00:01:26 +01:00
898feac168 increase shell tx buffer 2020-11-29 20:00:16 +01:00
0b1d872ed0 Make safety controller use config overrides from backup ram 2020-11-29 19:59:58 +01:00
687c72bde7 Use new gui module in main 2020-11-29 19:04:10 +01:00
b6d4a2e35e Implement safety memory functions for config overrides 2020-11-29 19:03:42 +01:00
a474111f36 Use error checking function of config parser in settings module 2020-11-29 19:03:17 +01:00
ed4c18f2be Add error checking function for config parser 2020-11-29 19:02:52 +01:00
f4d6f5a1ae Add PCB/Hardware version detection 2020-11-29 19:02:30 +01:00
32da2a5fa6 Reflow Controller GUI: Move gui to gui.c file in UI subfolder 2020-11-29 19:01:24 +01:00
ec66814184 Decrease history buffer of shellmatta 2020-11-29 17:19:40 +01:00
37c68809d1 Error mem viewer almost finished 2020-11-29 17:18:28 +01:00
67d59928c9 Add unfinished construct of error memory viewer 2020-11-19 22:36:54 +01:00
37bc397e9a Add reset-cal shell command and modify cal command to show existing calibration 2020-11-17 00:53:21 +01:00
d176389711 Add limit to scrolling of flag list in LCD gui 2020-11-17 00:31:24 +01:00
e60da5b23f Merge branch 'issue/6-safety-flag-gui' of mhu/reflow-oven-control-sw into dev 2020-11-16 20:03:07 +01:00
8603f84142 Issue : Improve LCD menu and implement function to see safety flags 2020-11-16 20:01:15 +01:00
d51c73d694 Merge branch 'issue/21-calibration' of mhu/reflow-oven-control-sw into dev 2020-11-16 18:44:59 +01:00
8f6462bcc9 Issue 21: Change documentation for calibration path 2020-11-16 18:38:50 +01:00
c02d988350 Issue : Adapt calibration routine to new calibration format 2020-11-15 23:36:52 +01:00
11b84afca0 Issue : Change calibration apply function 2020-11-15 23:10:19 +01:00
a858223c35 Fix : Merge branch 'issue/3-load-oven-pid-params' into dev 2020-11-08 21:38:21 +01:00
f2405e23b4 Add settings load function for PID parameters 2020-11-08 21:35:41 +01:00
2e640fa7fa Update base 64 library 2020-11-02 23:47:32 +01:00
1a3889b72d Update base64 lib to newest version. Now supports decoding 2020-11-02 23:44:37 +01:00
a7e376deab Add safety memory dump to file functionality 2020-11-02 18:21:24 +01:00
bb39c4b6e0 Fix bug in settings parser 2020-11-02 18:20:57 +01:00
7b1ae3bdc6 Improve code in calibration module 2020-11-02 18:20:17 +01:00
e37001e3c4 improve SDIO driver 2020-11-02 18:19:42 +01:00
09ea84beaf Increase watchdog timeout because some SD card operations need a lot of time 2020-11-02 18:17:50 +01:00
dc9fc2f814 Fix code warnings 2020-11-01 21:24:13 +01:00
32c8e2e937 Add define to move uart on debug header even when compiled in release mode 2020-11-01 21:22:28 +01:00
88360fe307 close config parser after use for reading calibration 2020-11-01 21:03:00 +01:00
57308e18e3 Delete cmsis math library. It is not needed anymore 2020-11-01 21:00:47 +01:00
731cb4fec3 Remove cmsis dsp library from project 2020-11-01 20:59:17 +01:00
8ff276e30d see last commit 2020-11-01 20:58:32 +01:00
1166477a6c Calibration routines adapted
* Implement custom mean and std functions
* Use standard deviation in calibration measurment instead of peak-peak noise.
2020-11-01 20:55:57 +01:00
7aa0b62012 Implement saftey memory dump feature and increase heap space 2020-11-01 20:43:59 +01:00
10596cdbf0 Add base64 library to Makefile 2020-11-01 18:03:52 +01:00
fc6fb1aee0 Add base 64 library 2020-11-01 18:01:28 +01:00
1eeaf3d892 Use new config parser for calibration 2020-11-01 00:59:46 +01:00
a3778fcb6e Change double numbers to float in order to prevent unwanted double to float conversion 2020-10-31 01:11:17 +01:00
86f153bf69 Fix code style 2020-10-31 01:10:46 +01:00
3ca5e41602 Implement config read function 2020-10-30 23:12:39 +01:00
dcec366b0a Implement config_parser_reset_to_start() 2020-10-30 22:24:03 +01:00
14b7bdbf19 Start config parser 2020-10-30 22:21:31 +01:00
af9845cbba Improve style 2020-09-27 23:23:44 +02:00
034ecaa60f Fix bug in menu 2020-09-27 23:02:38 +02:00
ae91affc30 issue : Implement safety weight checking in control loop 2020-09-27 22:54:06 +02:00
5fd2db319d Configure safety weight defaults 2020-09-27 22:22:54 +02:00
eec15df271 Fix code style 2020-09-27 22:13:49 +02:00
84c747c81c silence compiler warning about unused parameter 2020-09-22 23:47:18 +02:00
b869ed9c45 Improve comments and doxygen headers 2020-09-22 23:45:22 +02:00
42f6d0270d Issue : Implement safety flag ack in shell command safety-flags 2020-09-21 21:51:00 +02:00
e8f59b6dc6 Implement automatic resotre of error mem corrupt flag 2020-09-21 21:10:26 +02:00
d91a1b1da0 Fix : Make safety controller use CRC checked settings arrays for weights and persistencies. Weights not yet checked. 2020-09-08 21:46:57 +02:00
004be4ea5c Move safety weights and persistencies to config file 2020-09-08 21:15:23 +02:00
a838bf3af8 Add new Flag: ERR_FLAG_SAFETY_TAB_CORRUPT 2020-09-08 20:15:40 +02:00
1c1d1c4c97 Issue : Store correct flag number in error memory 2020-09-08 19:23:14 +02:00
e0f61af709 Issue : Protect safety memory heder with CRC 2020-09-08 18:24:10 +02:00
b619fc5600 Restructure panic mode and hardfault calls 2020-09-08 18:23:47 +02:00
2f6590416d Improve documentation of Stack Checking 2020-09-07 23:52:34 +02:00
a877ef5f28 Merge branch 'issue/18-Backup-RAM' into issue/15-safety-controller-hardening 2020-09-07 21:58:25 +02:00
af555aba21 Issue : Move stack checker to safety folder 2020-09-07 21:56:04 +02:00
dd0ee47d86 Issue : Add stack checking based on protection area between stack and heap 2020-09-07 21:52:53 +02:00
452abfdd5c Merge branch 'issue/18-Backup-RAM' into issue/20-implement-better-stack-checking 2020-09-07 21:04:37 +02:00
ba41c0911d Add necessary sections for stack protection area and implement fill function 2020-09-07 21:03:37 +02:00
cbbd97e1bd Issue : Implement driver for RNG 2020-09-07 20:47:56 +02:00
ab8228f712 Fix bug in doxygen xml generation for sphinx regarding the IN_SECTION() macro 2020-09-06 22:14:06 +02:00
20e2a2b84b Doxygen: Fix bug of IN_SECTION macro and __atribute__ 2020-09-06 22:13:51 +02:00
039a35522e Fix bug in doxygen xml generation for sphinx regarding the IN_SECTION() macro 2020-09-06 22:11:12 +02:00
72668472a0 Doxygen: Fix bug of IN_SECTION macro and __atribute__ 2020-09-06 22:09:14 +02:00
569d42bbe9 Issue : Fix wrong documentation 2020-09-06 21:12:57 +02:00
c7ebe441c7 Merge branch 'issue/15-safety-controller-hardening' into issue/18-Backup-RAM 2020-09-06 21:10:30 +02:00
403786e0c6 Issue : Implement safety weight table
* CRC protected flag weight table.
* Currently only filled with dummy values. Has to be finished in issue 
* Config overrides from safety memor ynot yet implemented
2020-09-06 21:05:00 +02:00
192bcf01f6 Merge branch 'issue/18-Backup-RAM' into issue/15-safety-controller-hardening 2020-09-06 19:54:09 +02:00
9880c701b1 Issue : Introduce safety weigths 2020-09-06 19:52:44 +02:00
910037a562 Issue : Write doxygen headers for safety memory 2020-09-06 19:45:45 +02:00
6232e2f330 Issue : Store permanent errors in safety backup RAM 2020-09-06 01:40:10 +02:00
7ea0e73869 Merge branch 'issue/15-safety-controller-hardening' into issue/18-Backup-RAM 2020-09-05 20:31:23 +02:00
c4fe006efa Issue : Implement redundancy for error flags 2020-09-05 20:29:21 +02:00
b2b1702670 Issue : add redundant invers error flag 2020-09-05 20:17:35 +02:00
1f8a6347e9 Issue : Move safety controller working pages to CCMRAM 2020-09-05 20:14:08 +02:00
d0cf95db49 Issue : further iomplementation of safety memory 2020-09-05 20:06:13 +02:00
331b049868 Issue : Documentation of boot status flags 2020-09-05 19:00:57 +02:00
e50602611c Issue : Documentation of boot status flags 2020-09-05 19:00:01 +02:00
95382d9ab8 Make interrupt default handler trigger panic mode. 2020-09-05 18:23:53 +02:00
e96a710576 Make interrupt default handler trigger panic mode. 2020-09-05 18:23:17 +02:00
2673112a9c Reflow menu: Stop rendering the menu although nothing has changed. This reduces the current consumption. 2020-09-05 18:04:52 +02:00
b8b8e19206 Reflow menu: Stop rendering the menu although nothing has changed. This reduces the current consumption. 2020-09-05 18:03:05 +02:00
325fb24ed8 Issue : Improve documentation 2020-09-05 18:02:03 +02:00
ea26f56545 Issue : Check error memory entries at safety ram init 2020-09-05 17:37:56 +02:00
77c88c69cd Issue : Redefine error memory entries 2020-09-05 16:57:25 +02:00
e85a85d9c3 Issue : ommand to shell in order to test panic mode 2020-09-05 16:56:56 +02:00
3df0631ffc Issue : Implement writing and reading boot status structure from backup RAM 2020-09-05 16:32:31 +02:00
7434554319 Issue : Fix bugs in safety memory handling 2020-09-05 15:56:52 +02:00
c9a5a2c2ff Issue : Write init of safety memory 2020-09-05 15:15:46 +02:00
04008a07c0 Issue : Implement CRC calculation module 2020-09-05 12:17:36 +02:00
928dbfb9f3 Issue : Firther improve documentation 2020-09-04 23:51:51 +02:00
0f0afcf359 Issue : Add safety mem corrupt error flag 2020-09-04 23:04:27 +02:00
5d437f3a9f Fix documentation and add safety RAM module to Makefile 2020-09-04 23:02:23 +02:00
cb3b42aece Start documentation for safety RAM. Will be implemented afterwards 2020-09-04 22:55:34 +02:00
a12648ff7a Issue : Backup RAM: Make use of backup regulator optional 2020-09-04 21:33:54 +02:00
d3c4e1bffc Issue : Implement driver for backup RAM 2020-09-04 21:03:53 +02:00
45c0625864 fixup style issues 2020-08-31 22:58:00 +02:00
03e1ccf97e Fix style 2020-08-31 22:50:39 +02:00
0fd738f37e Fix startup code bug in release mode 2020-08-30 19:40:33 +02:00
3dfe59482e Fix : Merge branch 'issue/17-rotary-emulation-cmd' into dev 2020-08-30 19:04:01 +02:00
9024402a3b Issue : Write documentation for emulation function 2020-08-30 19:03:17 +02:00
f32d1afde5 Issue : Add ui-emulate command to shell 2020-08-30 18:44:36 +02:00
0da6925119 Issue : Add override function for deltas of rotary encoder 2020-08-30 18:25:10 +02:00
914abd8562 Issue : Add override function for button 2020-08-30 18:20:58 +02:00
80edd09528 temperature converter: Replace division with multiplication. This makes the code faster 2020-08-29 08:53:23 +02:00
ab4499a284 Fix mrpropewr make target to clean debug and release projects 2020-08-29 08:52:44 +02:00
cc6e922d1b Move variables to CCM RAM 2020-08-23 21:51:34 +02:00
149c5715c6 Add fault modes and start implementation of backup SRAM. However, this will probably never be used 2020-08-23 21:40:16 +02:00
627da0def5 Fix-up documentation 2020-08-23 00:04:02 +02:00
324e6d506d Issue : Write documentation for error flags and their handling 2020-08-22 23:57:26 +02:00
dcd1fa9605 remove executable flag from CCM memory because it is not executable 2020-08-22 13:45:17 +02:00
3cc49fb764 Remove unneeded variable 2020-08-22 13:33:53 +02:00
13ac487ddb remove unneeded variables 2020-08-22 13:30:59 +02:00
ec117e0627 Change linker script and startup code.
This is my own code from my template. It is much cleaner than the old code.
2020-08-21 23:47:55 +02:00
95de84fa85 Fix : Add hang command to shell 2020-08-21 00:29:19 +02:00
432d30cc34 Fix : Timing monitors are now correctly displayed in flags command 2020-08-21 00:20:16 +02:00
0395cd19d4 SD card settings folder: Use f_stat to determine if directory is present 2020-08-21 00:06:56 +02:00
04994bff51 Issue : Fix timeout bug in write block command 2020-08-21 00:00:08 +02:00
45564a7789 Fix safety issue 2020-08-18 20:47:08 +02:00
fa20304df8 Makefile: Add linker script as dependency for linking step 2020-08-18 20:23:44 +02:00
86ba94a3f3 Makefile: Add linker flag to show memory usage after linking 2020-08-18 20:10:15 +02:00
60e990632b Fix : Moved static and global variablöes that are 0 initialized to CCMRAM in order to make room and increase performance. 2020-08-18 19:57:13 +02:00
64ef7b4a3c Issue : Increase SDIO clock speed to 4.2 MHz 2020-08-18 19:30:51 +02:00
637ac77a09 Add license to docu 2020-08-18 01:34:45 +02:00
6c980721b2 Add GPLv2 license to project 2020-08-18 01:07:37 +02:00
107c676084 Documentation: Add part of the GPL license text to the disclaimer in the documentation. 2020-08-18 01:04:57 +02:00
34b6af3627 Documentation: Write some docu
* Safety notice
* HW modifications
* Links to PCB repo
2020-08-18 01:00:45 +02:00
277b28d7f5 Make green LED flash instead of orange one, when inserting SD card 2020-08-17 22:26:29 +02:00
bdfaa67070 Fix typo 2020-08-17 22:26:05 +02:00
4e9b28ce15 Improve SDIO handling 2020-08-17 22:10:04 +02:00
543127b187 Fix bugs in settings saving 2020-08-16 22:11:57 +02:00
6c92048de5 Remove emptry line 2020-08-16 20:35:11 +02:00
227562cf3c Load calibration when SD card is inserted.
* Load calibration when SD card is inserted and controller is not yet calibrated
* Fix : LED0 blinks when SD is inserted / removed.
2020-08-16 20:33:25 +02:00
58937b46f6 Improve code 2020-08-16 20:33:17 +02:00
e06c9f7ddc Remove toml. Write calibration to dat files. Implement first draft for reading function 2020-08-16 19:37:41 +02:00
a5402d3f04 Add gitignore to build directory of documentation 2020-08-16 13:18:04 +02:00
d04d8ebf9d Change save fuinction for SD card calibration data 2020-08-16 13:15:35 +02:00
42ca1a01b5 Merge branch 'issue/1-shell-function-save-calibration-data' into dev 2020-08-16 12:53:47 +02:00
68883735ec Remove global error state from main file 2020-08-16 12:53:05 +02:00
15d255778c Fix : Implement save function for calibration 2020-08-16 12:52:37 +02:00
2f39b5eb69 Merge branch 'dev' of git.shimatta.de:mhu/reflow-oven-control-sw into dev 2020-08-16 12:35:45 +02:00
d1d2d514bd Add timing monitor for main loop and add monitors to safety flag command 2020-08-16 12:34:41 +02:00
4a441a9c44 Documentation: Create build folder in case it does not exist. However, add it to the git repo by placing a .gitignore inside 2020-08-16 11:50:20 +02:00
fa3c980207 shell: Add dummy function save-calibration. Not yet correcly implemented! 2020-08-16 01:24:59 +02:00
3c6200e08c Settings: Add preliminary functions to store Claibration data on SD Card. Not yet implemented correctly 2020-08-16 01:24:20 +02:00
e7d150e8f5 FatFs: Enable relative paths 2020-08-16 01:23:50 +02:00
c5667c6895 Toml: Add TOML interpreter for config files 2020-08-16 01:22:57 +02:00
b7ccd8542e Increase safety ADC timing monitor to over a second. It might take a while for the ADC to be called if a demanding operation is taking place 2020-08-16 01:22:26 +02:00
1ad68a2c43 SDIO Driver: Fix bug created in commit 3705cc09d1 that makes writing to disk impossible 2020-08-16 01:19:56 +02:00
4ab91ace5f Remove redundant define macro 2020-08-11 23:37:26 +02:00
97c32b0443 Write documentation 2020-08-11 23:21:24 +02:00
a68b9176cb Move ADC_TO_RES macro to header file 2020-08-11 23:21:14 +02:00
cb3c989683 Docu 2020-08-04 00:55:16 +02:00
f6f01b0510 Improve sphinx 2020-08-03 21:13:04 +02:00
d6815f8285 Documentation: Breathe: Detect c/h files correctly as C Files and not C++ 2020-08-02 22:29:18 +02:00
62ea995c2d fix typo in sphinx doc 2020-08-02 22:20:41 +02:00
e8e3d71bbe doxygen: Remove latex output and add optional flags to buildscript 2020-08-02 22:15:33 +02:00
75d4af84c4 Basic template for documentation 2020-08-02 22:14:49 +02:00
6cde956c31 Merge branch 'safety-controller' into dev 2020-08-02 19:00:35 +02:00
bedf231550 Use the RTD theme for sphinx 2020-07-30 23:08:40 +02:00
a112cd80bf Add sphinx docu 2020-07-30 22:58:42 +02:00
fdf3f2c7d6 Merge branch 'dev' into safety-controller 2020-07-30 22:51:08 +02:00
21ad2ace4a Remove temp profile submodule 2020-07-30 22:50:34 +02:00
464c247e32 Fix a few bugs and implement flags command further 2020-07-30 20:29:48 +02:00
6c4b698fd7 Add safety flag for debugbuild 2020-07-28 23:29:35 +02:00
6498aaf8b8 Add color to flag monitor command and set oven output to 0 2020-07-28 23:26:28 +02:00
b65d94b0e8 Fix ADC measurement to run at 1000 Hz and fix wrong error handling for PT1000 Watchdog. Add function for flags to shell 2020-07-28 22:55:02 +02:00
97fc04399e Fix recursion loop in safety controller 2020-07-28 21:00:37 +02:00
da96daa767 Reworked measurement ADC to use safety controller 2020-07-27 22:15:01 +02:00
a9e300bf5b Make error structures volatile 2020-07-27 21:32:25 +02:00
4f3016649d First draft of safety controller 2020-07-27 21:29:15 +02:00
a04e894518 Further work on safety controller 2020-07-26 21:40:09 +02:00
9136dc196c Further rewrite safety handling 2020-07-09 22:31:42 +02:00
5eb51f08b6 Start safety implementation. Completely dumped old stuff 2020-07-07 20:47:22 +02:00
06a75559f0 Add structure for safety controller config. 2020-07-07 19:26:00 +02:00
248707055e Fix watchdog init code 2020-07-06 21:37:36 +02:00
67a32cdc20 Safety Controller:
* Add watchdog code
* Add file structure for safety controller
* Lay groundstones to move all error flags to the safety controller
* Improve doxygen
2020-07-06 21:12:18 +02:00
8a365ab5e0 Move safety ADC to safety subfolder 2020-07-06 20:13:01 +02:00
7cd05e1582 Update shellmatta 2020-06-25 23:54:36 +02:00
0e97d57883 Improve menu function 2020-06-25 23:52:58 +02:00
cced874460 Add Pullup to uart RX pin 2020-06-21 01:29:50 +02:00
49927a25cf Add Omega as unit for Ohm in LCD menu 2020-06-16 20:05:32 +02:00
233 changed files with 93925 additions and 11368 deletions
.gitmodulesGPLv2.mdJenkinsfileLICENSE.mdc-style-checker
doc
error-mem-viewer
measurement-data
reflow-controller-temp-profile-lang
stm-firmware

10
.gitmodules vendored

@ -5,7 +5,11 @@
path = c-style-checker
url = https://git.shimatta.de/mhu/c-style-checker.git
branch = master
[submodule "reflow-controller-temp-profile-lang"]
path = reflow-controller-temp-profile-lang
url = https://git.shimatta.de/mhu/reflow-controller-temp-profile-lang.git
[submodule "stm-firmware/base64-lib"]
path = stm-firmware/base64-lib
url = https://git.shimatta.de/mhu/base64-lib.git
branch = master
[submodule "stm-firmware/linklist-lib"]
path = stm-firmware/linklist-lib
url = https://git.shimatta.de/mhu/linklist-lib.git

361
GPLv2.md Normal file

@ -0,0 +1,361 @@
### GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
### Preamble
The licenses for most software are designed to take away your freedom
to share and change it. By contrast, the GNU General Public License is
intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on,
we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not reflect
on the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at
all.
The precise terms and conditions for copying, distribution and
modification follow.
### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
**0.** This License applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work
based on the Program" means either the Program or any derivative work
under copyright law: that is to say, a work containing the Program or
a portion of it, either verbatim or with modifications and/or
translated into another language. (Hereinafter, translation is
included without limitation in the term "modification".) Each licensee
is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the Program
(independent of having been made by running the Program). Whether that
is true depends on what the Program does.
**1.** You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a
fee.
**2.** You may modify your copy or copies of the Program or any
portion of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
**a)** You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
**b)** You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any part
thereof, to be licensed as a whole at no charge to all third parties
under the terms of this License.
**c)** If the modified program normally reads commands interactively
when run, you must cause it, when started running for such interactive
use in the most ordinary way, to print or display an announcement
including an appropriate copyright notice and a notice that there is
no warranty (or else, saying that you provide a warranty) and that
users may redistribute the program under these conditions, and telling
the user how to view a copy of this License. (Exception: if the
Program itself is interactive but does not normally print such an
announcement, your work based on the Program is not required to print
an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
**3.** You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
**a)** Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections 1
and 2 above on a medium customarily used for software interchange; or,
**b)** Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your cost of
physically performing source distribution, a complete machine-readable
copy of the corresponding source code, to be distributed under the
terms of Sections 1 and 2 above on a medium customarily used for
software interchange; or,
**c)** Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is allowed
only for noncommercial distribution and only if you received the
program in object code or executable form with such an offer, in
accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
**4.** You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt otherwise
to copy, modify, sublicense or distribute the Program is void, and
will automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
**5.** You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
**6.** Each time you redistribute the Program (or any work based on
the Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
**7.** If, as a consequence of a court judgment or allegation of
patent infringement or for any other reason (not limited to patent
issues), conditions are imposed on you (whether by court order,
agreement or otherwise) that contradict the conditions of this
License, they do not excuse you from the conditions of this License.
If you cannot distribute so as to satisfy simultaneously your
obligations under this License and any other pertinent obligations,
then as a consequence you may not distribute the Program at all. For
example, if a patent license would not permit royalty-free
redistribution of the Program by all those who receive copies directly
or indirectly through you, then the only way you could satisfy both it
and this License would be to refrain entirely from distribution of the
Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
**8.** If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
**9.** The Free Software Foundation may publish revised and/or new
versions of the General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Program does not specify a
version number of this License, you may choose any version ever
published by the Free Software Foundation.
**10.** If you wish to incorporate parts of the Program into other
free programs whose distribution conditions are different, write to
the author to ask for permission. For software which is copyrighted by
the Free Software Foundation, write to the Free Software Foundation;
we sometimes make exceptions for this. Our decision will be guided by
the two goals of preserving the free status of all derivatives of our
free software and of promoting the sharing and reuse of software
generally.
**NO WARRANTY**
**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
### END OF TERMS AND CONDITIONS
### How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does.
Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Also add information on how to contact you by electronic and paper
mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
The hypothetical commands \`show w' and \`show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than \`show w' and
\`show c'; they could even be mouse-clicks or menu items--whatever
suits your program.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the program,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library,
you may consider it more useful to permit linking proprietary
applications with the library. If this is what you want to do, use the
[GNU Lesser General Public
License](https://www.gnu.org/licenses/lgpl.html) instead of this
License.

21
Jenkinsfile vendored Normal file

@ -0,0 +1,21 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
}
}
stage('Test') {
steps {
echo 'Testing..'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}

10
LICENSE.md Normal file

@ -0,0 +1,10 @@
# License of the Relow Oven Control Firmware
This software is licsensed according to the GPLv2. See GPLv2.md for details.
However, this software includes various third party libraries for which different licenses apply:
- Shellmatta Shell implementation by Stefan Strobel: Licensed under ``Mozilla Public License Version 2.0``
- CMSIS by ARM Limited <https://github.com/ARM-software/CMSIS_5>, licensed under ``Apache License Version 2.0, January 2004``
- STM Header Files etc. by ST Microelectronics icensed under a custom license. See the sphinx documentation (section License) for details.
- FatFs: Custom License (See source files of FatFS)
- SHA256 Library <https://github.com/amosnier/sha-2> licensed under the ``Unilicense``

@ -1 +1 @@
Subproject commit 3a58e3dd1c2ef6de78df89c8fdc7ba96b51cd4e0
Subproject commit aeb2707d80049094337742d0f62cd24dbef1c01d

2
doc/.gitignore vendored Normal file

@ -0,0 +1,2 @@
build/*
venv

3
doc/.vscode/settings.json vendored Normal file

@ -0,0 +1,3 @@
{
"restructuredtext.confPath": "${workspaceFolder}/source"
}

22
doc/Makefile Normal file

@ -0,0 +1,22 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
livehtml:
sphinx-autobuild -b html $(SPHINXOPTS) $(SOURCEDIR) $(BUILDDIR)/html

@ -1,3 +1,3 @@
*
*.*
*/*
!.gitignore

21
doc/make-with-virtualenv.sh Executable file

@ -0,0 +1,21 @@
#!/bin/bash
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
cd "$DIR"
if [[ ! -d "venv" ]]; then
virtualenv venv
source ./venv/bin/activate
pip install -r requirements.txt
else
source ./venv/bin/activate
fi
make SPHINXBUILD='venv/bin/python venv/bin/sphinx-build' $@

35
doc/make.bat Normal file

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

32
doc/requirements.txt Normal file

@ -0,0 +1,32 @@
alabaster==0.7.12
Babel==2.9.0
blockdiag==2.0.1
breathe==4.24.1
certifi==2020.11.8
chardet==3.0.4
docutils==0.16
funcparserlib==0.3.6
idna==2.10
imagesize==1.2.0
Jinja2==2.11.2
MarkupSafe==1.1.1
packaging==20.7
Pillow==8.0.1
Pygments==2.7.2
pyparsing==2.4.7
pytz==2020.4
requests==2.25.0
six==1.15.0
snowballstemmer==2.0.0
Sphinx==3.3.1
sphinx-rtd-theme==0.5.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-blockdiag==2.0.0
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-drawio==0.0.12
sphinxcontrib-htmlhelp==1.0.3
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.4
urllib3==1.26.2
webcolors==1.11.1

2
doc/source/.gitignore vendored Normal file

@ -0,0 +1,2 @@
.drawio/*
.drawio

3
doc/source/.vscode/settings.json vendored Normal file

@ -0,0 +1,3 @@
{
"restructuredtext.confPath": "${workspaceFolder}"
}

2536
doc/source/Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

3432
doc/source/_static/ibom.html Normal file

File diff suppressed because one or more lines are too long

86
doc/source/conf.py Normal file

@ -0,0 +1,86 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os, subprocess
import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
import re
project = 'Shimatta Reflow Controller'
copyright = '2020, Mario Hüttel'
author = 'Mario Hüttel'
# The full version, including alpha/beta/rc tags.
release = re.sub('^v', '', os.popen('git describe --always --tags --dirty').read().strip())
# The short X.Y version.
version = release
try:
os.mkdir('../build/_doxygen')
except FileExistsError:
pass
subprocess.call('doxygen Doxyfile.in', shell=True)
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx_rtd_theme',
'sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinxcontrib.blockdiag',
'sphinxcontrib.drawio',
'breathe'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
breathe_projects = {
"Reflow Controller Firmware": "../build/_doxygen/xml/"
}
breathe_domain_by_extension = { "h" : "c",
"c" : "c" }
breathe_default_project = "Reflow Controller Firmware"
breathe_default_members = ('members', 'undoc-members')
blockdiag_html_image_format = 'SVG'
breathe_show_define_initializer = True
blockdiag_latex_image_format = 'PDF'
todo_include_todos = True

@ -0,0 +1 @@
<mxfile host="Electron" modified="2021-05-22T15:48:58.897Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="60nNVEjkDLNBMWFG8AC7" version="14.1.8" type="device"><diagram id="3R1YF1CA5z1RRVBQNkpO" name="Page-1">7VlLc9o6FP41LGFkCduwbCBtF+1cbtOZpkthy7Z6ZURk8eqvr2TLLwSBFIgnmZtFxjqSjh7n+85D9NAk3X4SeJl85SFhPQjCbQ9NexB6vq/+a8GuEKCRVwhiQcNC5NSCB/qbGCEw0hUNSdYaKDlnki7bwoAvFiSQLRkWgm/awyLO2qsucUwswUOAmS39QUOZFNIR9Gv5Z0LjpFzZ8cZFT4rLweYkWYJDvmmI0H0PTQTnsvhKtxPC9N2V91LM+3ikt9qYIAt5zgRvNpa/npLHmH16+jdwvo+m7rzvmr3JXXlgEqrzmyYXMuExX2B2X0vvBF8tQqK1AtWqx3zhfKmEjhL+IlLujDHxSnIlSmTKTK/asNg9mvl546duDNyyOd02O6c70yr2qjd49ApKiGARE/nMuceVARRwCU+JWkfNE4RhSddt/dhAKK7GVVNnnKqVITBor1BrwO74oK2i2JeZ1bTVnqJ9PZ7b1pPxlQiIpUd9NI5Ti3IkvAAVhqJrzFbmKr7hjRLMvjsAgPyeMppJvAjIQfx8wXPlBVo2x4zGC/UdKFMRoQRrIiRVPPtgOlIahgW8lO7feJ7r01Zf6lPm53bveu60woFWQLa9A07ATK6p10TIcRrYcDDa+2DgAH/cMknfLHkhYhwwGLug8YcOrlIq5FGUkZuY3OnGE2ypfGx8N/yAatVuQDdKL/C33iNvzYig6qo0Al/oUgrKnXIpZ7geZ3ih72mZ/qV2HlvU7kGPqf3ezdVHLPM7KQQRz5FaI8J7WvGyo5/lNv2gBiC03NadtZZKkdpooautX4kba+6DjzEV4jXINgmV5GGJ88vfqCRjz7FkyyLuR3SroXgXUcYmnHGRK0KhS0bhUMkzKfh/pNEzgnPkec/5EwsGR10ELPlTeuyhcT2bOmlwjShp5AsuuJGdHce+0vfF5ytStwy3p7kLb5M3oHa8h8Pz8oarOX9geYWJCthzgaVCAwT/1GGnCag2XE7wdI+WURTBIDhEy9Cbe+6VaOnv3atrs9KBB2jp3YyW6O3Rsmbiz2YC/wq0hGfS8tJs/jKTQos8fdv5SkHxImZnBDTBpdo11zlxfwxs5hBHhTT/EHPGno/wtQIabAe0qiRpUAcdYM6+57raNUP4ZpijGjfMMy/OHw/HIA+cqDlvHIMgej4GVbXnt3dWe8IjOUVdfCIXOC3bXKn4RM7gcFH7CuXm0LK2Zc3SSrlFZzyjxivOuZQ81Q6wfFHTpgpxllRMtyzeQMO+8aV2BVrXUq+bbmP9jjkgTBlT6HEDPFeeFgdykK70uyOjucZOygw03CNp12UGfINlRnf5jHdmPuP4nSY09vNf0xOb1wJRlu4PZKGpuaZSb3FK1rRIX958tYBg59XCqBN2/SVTbv3A5vjn0qfTF7Zym/8/sd029lXlR2exD9hX+h5+PDtNxLOfuruNY/Zbt52tXBKVXqkSHx95HDxRiaOX414169+ji1S//lEf3f8B</diagram></mxfile>

@ -0,0 +1,8 @@
.. _api_dmas:
Peripheral DMA Library Code
====================================
.. doxygengroup:: dma-ring-buffer
:project: Reflow Controller Firmware

@ -0,0 +1,11 @@
.. _api:
Important Code APIs
===================
.. toctree::
:maxdepth: 2
:glob:
*
safety/safety-controller

@ -0,0 +1,8 @@
.. _api_main:
Reflow Controller Firmware Main File
====================================
.. doxygenfile:: main.c
:project: Reflow Controller Firmware

@ -0,0 +1,8 @@
.. _dox_safety_adc:
Safety ADC
====================================
.. doxygengroup:: safety-adc
:project: Reflow Controller Firmware

@ -0,0 +1,11 @@
.. _dox_safety_controller:
Safety Controller
====================================
.. toctree::
:maxdepth: 1
safety-adc

@ -0,0 +1,31 @@
.. _hw_version_detect:
Automatic Hardware Version detection
====================================
Functional Description
----------------------
In order to automatically select the available hardware features, the firmware checks the PCB's version
using vertain pins on the microcontroller.
The hardware revision is represented by the enum type :c:enum:`hw_revision`. A call to :c:func:`get_pcb_hardware_version` retrieves the revision.
When the function is called for the first time, it activates pull-up resistors on pin numbers :c:macro:`HW_REV_DETECT_PIN_LOW` to :c:macro:`HW_REV_DETECT_PIN_HIGH`
on port :c:macro:`HW_REV_DETECT_GPIO` and reads in the binary number.
The revision is set by externally connecting the pins to ground. The bit pattern read from the port is inverted and then checked internally to derive the hardware version.
After the version is read for the first time, it is stored internally and subsequent calls to :c:func:`get_pcb_hardware_version` only retrieve the internally stored value to reduce the overhead of the function.
Hardware Version Dependent Features
-----------------------------------
- The settings module searches for an external EEPROM on the SPI interface to store some settings, like the calibration. This is enabled for all versions higher or equal to ``v1.3``.
- The safety controller enables the acknowledging of the external watchdog for all versions higher or equal to ``v1.3``.
- The oven driver has a separate safety enable for the solid state relay which it enables on all versions higher or equal to ``v1.3``.
API Documentation
-----------------
.. doxygengroup:: hw-version-detect
:project: Reflow Controller Firmware

@ -0,0 +1,18 @@
.. _firmware:
Reflow Controller Firmware
==========================
This chapter describes the reflow controller's firmware.
This is in most cases not intended to be a code documentation but an overview over the functional
mechanisms and the behavior. For a detailed code documentation see the doxygen output.
.. toctree::
:maxdepth: 2
pt1000-processing
pid-controller
safety/index
code/index
hw-version-detect
peripherals

@ -0,0 +1,44 @@
.. _peripherals:
Used Peripheral Modules
=======================
This section lists all the used peripheral modules of the ``STM32F407VxT6``.
Core Peripherals
----------------
- ``SysTick``: Generating a 100us tick for the LCD routine and 1ms base system tick.
- ``NVIC``: Interrupt controller
- ``FPU``: The Flaoting Point Unit is activated and used in this formware.
AHB Peripherals
---------------
- ``DMA2``
- ``Stream0``: DMA transfer of PT1000 measurement ADC to memory
- ``Stream4``: DMA transfer of Safety ADC measurement values
- ``Stream5``: Shell UART RX
- ``Stream7``: Shell UART TX
- ``RNG``: Random number generation for stack corruption / overflow checker.
- ``CRC``: CRC verfication of various data (Safety structures, EEPROM data, Safety RAM)
- ``Backup RAM``: Backup RAM storing errors and bootloader information beyond system resets. The memory is cleared by a power cycle!
ABP1 Peripherals
----------------
- ``IWDG``: Independent Watchdog
- ``TIM2``: PT1000 measurement ADC sample time generation timer. Genewrates the 1 KHz sample trigger to the ADC peripheral via the internal event routing system.
- ``TIM3``: PWM timer for oven relais output.
- ``TIM5``: Input capture for rotary encoder.
- ``TIM7``: Timer for loudspeaker tone generation.
APB2 Peripherals
----------------
- ``SPI1``: SPI for external SPI-EEPROM
- ``SDIO``: SD card interface
- ``USART1``: Shell UART
- ``ADC1``: Safety ADC for monitoring voltages
- ``ADC3``: PT1000 measurement ADC

@ -0,0 +1,78 @@
.. _pid_controller:
PID Controller
==============
The PID controller is the main element of the oven. It controls the output of the solid state relais in order to achieve the desired temperature.
The PID controller is implemented in the ``pid-controller.c`` file. See the :ref:`pid_code_api` for details.
Functional Description
----------------------
The following figure shows the PID controller's structure.
.. drawio-image:: pid.drawio
The controller is composed of 3 paths. The proportional, the derivate, and the integrator path.
Compared to a textbook PID controller, this version contains a few additional features.
The integrator has a configurable maximum limit of :c:var:`pid_controller.integral_max`. Once this value is reached (plus or minus), the integrator freezes.
The integrator is also frozen in case the output value is in saturation. This serves as an anti-windup protection.
The output value saturates at configurable high and low limits (:c:var:`pid_controller.output_sat_max` and :c:var:`pid_controller.output_sat_min`). The controller instance used for the
reflow oven's solid state relais output is saturated by software to a limit of 0 to 100.
In addition to the above features, the derivate term contains an additional first order low pass filter in order to prevent coupling of high frequency noise amplified by the derivate term.
The low pass filter is charcterized by its time constant :math:`k_{d\tau}`.
Time Continuous Transfer Function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The time continous transfer function of the PID controller is
.. math:: H_c(s) = \frac{Y_c(s)}{X_c(s)} = k_p + \frac{k_i}{s} + \frac{k_ds}{1+sk_{d\tau}}
Time Discrete Transfer Function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The time descrete transfer function which is implemented in the code is derived by converting the time continuous transfer function
with the bilinear transformation:
.. math:: s = \frac{2}{T_s}\cdot \frac{z-1}{z+1}
The frequency warping of the bilinear transform can be considered negligible because the PID controller is targetted for low frequency temperature signal data with a maximum far below the nyquist freqency.
In this area, the mapping of the continuous frequencies to the time descrete can be considered linear.
The time discrete transfer function after inserting the bilinear transform is:
.. math:: H_d(z) = H_c(s)\bigg|_{s=\frac{2}{T_s}\cdot \frac{z-1}{z+1}} = k_p + \frac{k_i T_s (z+1)}{2(z-1)} + \frac{\frac{2}{T_s}k_d(z-1)}{\left(1+\frac{2k_{d\tau}}{T_s}\right)z+\left(1-\frac{2k_{d\tau}}{T_s}\right)}.
Converted to an implementable form:
.. math:: H_d(z) = k_p + \frac{k_iT_s(1+ z^{-1})}{2(1-z^{-1})} + \frac{\frac{2}{T_s}k_d(1-z^{-1})}{(1+2k_{d\tau}T_s^{-1})+(1-2k_{d\tau}T_s^{-1})z^{-1}}
This function can be splitted in the three individual parts of the PID controller:
.. math:: H_{d1}(z) = k_p
.. math:: H_{d2}(z) = \frac{k_iT_s(1+ z^{-1})}{2(1-z^{-1})}
.. math:: H_{d3}(z) = \frac{\frac{2}{T_s}k_d(1-z^{-1})}{(1+2k_{d\tau}T_s^{-1})+(1-2k_{d\tau}T_s^{-1})z^{-1}}
The individual time domain difference equations :math:`y_i[n] = \mathcal{Z}^{-1}\left\lbrace H_{di} * X(z)\right\rbrace` that are implemented in software are:
.. math:: y_1[n] = k_p x[n]
.. math:: y_2[n] = \underbrace{\frac{k_iT_s}{2}}_{k_{i_t}} \left( x[n] + x[n-1]\right) + y_2[n-1]
.. math:: y_3[n] = \underbrace{\frac{2k_{d}}{2k_{d\tau} + T_s}}_{k_{d_t}}\left( x[n] - x[n-1] \right) + \underbrace{\frac{2k_{d\tau} - T_s}{2k_{d\tau} + T_s}}_{\overline{k_{d_t}}} y_3[n-1]
The final output value is the sum of all three terms:
.. math:: y[n] = \sum_{i=1}^{3} y_i[n]
.. _pid_code_api:
PID Controller Code API
-----------------------
.. doxygengroup:: pid-controller
:project: Reflow Controller Firmware

@ -0,0 +1 @@
<mxfile host="Electron" modified="2021-06-14T21:01:35.428Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="ORruDkFRflEPSgIrI-Cx" version="14.1.8" type="device"><diagram name="Page-1" id="b520641d-4fe3-3701-9064-5fc419738815">3Vttb6M4EP41+dgIMObl4/bl7lba1VXqSbt3XyonOMRXiDnjtGR//dnYQHhLySaEdFFV2ePx2Hjm8YzHZAbu4ux3hpL1VxrgaGYZQTYD9zPL8j1T/JeEnSJA6CtCyEigSGZFeCI/sCYamrolAU5rjJzSiJOkTlzSzQYveY2GGKNvdbYVjeqjJijELcLTEkVt6jcS8LWmmoZRNfyBSbjWQ3tQNyzQ8iVkdLvR480ssMof1RyjUpYipGsU0DdFykWAhxm4Y5RyVYqzOxzJpS2WTY3zW09rOW+GN3xIBy/JHl5eQ/vrX8//QJh8C+iPpxutq5TvivXAgVgeXaWMr2lINyh6qKi3+TtjKdUQtYrnC6WJIJqC+C/mfKd1jbacCtKax5FuxRnh3/fKf0tRc6hr95mWnFd2RWXD2e57xSirf++3Vd3yWq3fI2YkxhwzTVQvLd+0dy0LpdEtW+IDC1iYLGIh5of4zFLlAkmYiumwnejIcIQ4ea1PBGmbDku+susjJWKKlqHh50BLrEfeSePPstyCUohRk9M9KwsRhb2pVKTcbo6wISlyAiMqDaJmDpV19BjEcN2/r9NRVFrujIVCHWOQOtuC7HcEKeNuCfrEGNrtsSWSIT0wYbd7nN55NfjNOr8oqBmc1Ui1Gl5RtMXFfu1EQru3C1EIZeHzhuOQIU5Z0SRGKltLdlZRbPH38kxUoQWCysSlvb6tCcdPCcp3kzfhSuvmvCJRdEcjyvK+IIDYC2xBTzmjL3ivxbMWwHFKQ37FjOPssCm3TVR3ALChCe1CjLeaJ1S09b4TbFjSvlXXtpej1QQ+ikM6ow8Bo+wjtt+AJfTnHnRN21L//Ys6CfA+/u6Fl35Vb3wU/oJfBn/W9PgzPgr++gLCMjaYKCCEVxcQ+talA8JpNvHpA0I4TkBo1HcJAH7xgBBcIiCEHQ5J+ZOkx59wRtAmzI31Kp2JU8c96HAm3iV9ifO+y39kNBFQJxLo3U6/qQOc8fpao4iEG1FeimWS+/mtXESyRNEn3RCTIFA7DE7JD7TIRUngazMWcuHtDN5LWWJTSdX+MqEa62CwDdhSo9+hRmssNYI2Eq41JBCVMVM9I3ns93blkb212XU0bii8wNQXtMDRo8CIhKxoWlDOaSwhUSQ35ZoHKF2Xum/hc0/JTahyaRxSViLHjbNQZpznOMJLsfcKvjlaCOyhJZ+n2zhGchLPOYqnAitsgFVE9C2wwg6wwtHi92nA+pOh1+jJWWtg4HYytE9TmtUbi8zc22AG7zjaztz7nrjkWsAZ0ZAsn0PEcSrKbwlK02eBSiV4Eni2UiDAHQRP2xlL0+608Dzu7uScSHSGInFSIPaHrCua++xKcc5/W1o03Kig8ZNgMK0kqxqLOPYryki8jUUVxRJFm0WaHMhpCcQnsZysxH+Msj3slzGymlBPmHxS6gthb7Xsgqaz9PBiNQ403WGHldEcpzVJ4uuMCANDkxTjZJubO+3A1MLZ0ssDglghhiTpgOM7ShP1pcGKZFK7TYQY+XMeHFjNCBK2gWBd9LjXsXDXA4TzJ9csf+7bP2W7bVmwLUuQnEY0MfZNS/uq5fMm2cp5BviV5KemThXn8eN4yZVesOgve3TnWWna+8o/YKq90Lox5o4NzZo+dO1Eo7kBcG47RvXUBzHmvufvPZ5dH4CuVikeRff2JOCd+vp0nLS7Z7Rc2hyYBrBtz3Kh54BBqD42d+56x+XO3+EfJ3duX1FK0Bp8TWhNdfgBg+8ERzHklokMyy8ebbnNWx8bHrbcBj88bOjAdQ+wj2Tn7fPgn1uufGmK+JZpZ2qsMA7k96C/hl9V8O71q2Jr9626Mm7O41c9Z97cVsfzlaB9A1gq92lPuec8Wl8k69W6UADtI4XZdaZoxr1nO1PYkxyuT/yqxJ3MXXgD3cXJgc9pB0WvHz8x2ah814fLSzmNr2+9NnbcDujYo0HHbC3i9UNnMuT4HwM5/gHkFJniD48c054aOu1ESLnMitZc5It+XXKGJW+F3B3Xz11Z9J9IHopq9VMlFYJVPwcDD/8D</diagram></mxfile>

@ -0,0 +1,168 @@
.. _pt1000_processing:
PT1000 Temperature Value Processing
===================================
The PT1000 temperature sensor is the sensing element used for determining the Reflow Oven Temperature.
The PT1000 value processing is enabled by default and not intended to be turned off.
PT1000 Value Sampling
---------------------
The following block diagram shows the processing chain of the temperature signal.
.. drawio-image:: pt1000.drawio
ADC
~~~
The internal ADC of the STM32F407 controller is used to sample the analog signal from the :ref:`hw_analog_fe`. The ADC is triggered by the hardware Timer *TIM2* each millisecond, which results in a sampling frequency of
1 kHz. The ADC module provides an analog value `watchdog <Watchdog_>`_, which is used to detect wirebreaks and other hardware errors that result in a wrong resistance measurement.
The sample frequency is controlled by
.. doxygendefine:: ADC_PT1000_SAMPLE_CNT_DELAY
whereas the ADC Peripheral module is defined by
.. doxygendefine:: ADC_PT1000_PERIPH
Prefilter
~~~~~~~~~
The analog value prefilter is used to filter outliers. It is triggered after a certain amount ``n`` of values have been sampled by the `ADC`_.
The filter then removes the two most extreme values and computes the average of the remaining ``n - 2`` values. By default ``n`` is configured to:
.. doxygendefine:: ADC_PT1000_DMA_AVG_SAMPLES
Therefore, by default, the resulting datastream has a sampling rate of 1/6 kHz. This depends on the :c:macro:`ADC_PT1000_SAMPLE_CNT_DELAY` and ``n``
.. _firmware_meas_adc_watchdog:
Watchdog
~~~~~~~~
The analog watchdog supervises the measured value of the `ADC`_. It is configured by the following defines:
.. doxygendefine:: ADC_PT1000_LOWER_WATCHDOG
.. doxygendefine:: ADC_PT1000_UPPER_WATCHDOG
.. doxygendefine:: ADC_PT1000_WATCHDOG_SAMPLE_COUNT
The watchdog will set the :ref:`safety_flags_adc_watchdog` error flag.
ADC Value to Ohm
~~~~~~~~~~~~~~~~
This block converts the analog value to an Ohm resistance value.
The formula is:
.. math::
R(V) = \frac{V}{4096} \cdot 2500~\Omega
The equation is implemented in
.. doxygendefine:: ADC_TO_RES
and applied during the `Exponential Moving Average Filter`_.
.. _firmware_meas_adc_filter:
Exponential Moving Average Filter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The external moving average filter filters the measured resistance value. It's equation is:
.. math::
y[n] = (1-\alpha) y[n-1] + \alpha x[n]
The filter constant *alpha* defaults to the define
.. doxygendefine:: ADC_PT1000_FILTER_WEIGHT
and can be changed in code using
.. doxygenfunction:: adc_pt1000_set_moving_average_filter_param
The moving average filter is considered unstable, if the input to output difference is greater than
.. doxygendefine:: ADC_PT1000_FILTER_UNSTABLE_DIFF
In this case, the :ref:`safety_flags_adc_unstable` flag will be set until the filter output converges within the range for at least
.. doxygendefine:: ADC_PT1000_FILTER_STABLE_SAMPLE_COUNT
samples.
If the input value keeps changing or oscillating, the error flag will be permanently set.
The moving average filter's output signal is the Low Frequency (LF) PT1000 resistance signal used for internal PT1000 measurements.
Reading and Converting the PT1000 Value
---------------------------------------
Calibration
~~~~~~~~~~~
The functions
.. doxygenfunction:: adc_pt1000_set_resistance_calibration
:outline:
and
.. doxygenfunction:: adc_pt1000_get_resistance_calibration
:outline:
are used to set the resistance calibration internally. For a guide on how to calibrate the deivce, see the corresponding :ref:`usage_calibration` usage page.
The calibration is calculated the following way:
.. drawio-image:: calibration.drawio
The final calibrated PT1000 resistance is calculated as:
.. math::
R_{PT1000_{corr}} = (R_{PT1000_{LF}} - O) \cdot (1 + \sigma)
The default values, if no calibration is loaded / executed, are:
======== =====================
Offset Sensitivity Deviation
======== =====================
0 0
======== =====================
Get Calibration Corrected Value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The PT1000 value is available through the following function.
If a calibration is set, it is applied.
.. doxygenfunction:: adc_pt1000_get_current_resistance
Converting the Value
~~~~~~~~~~~~~~~~~~~~
The valid range for conversion is between
.. doxygendefine:: TEMP_CONVERSION_MIN_RES
:outline:
and
.. doxygendefine:: TEMP_CONVERSION_MAX_RES
:outline:
By default, the valid range is:
.. math::
1000~\Omega \le R_{PT1000} \le 2200~\Omega
.. doxygenfunction:: temp_converter_convert_resistance_to_temp
The cvonversion function is based on a lookup table with linear interpolation between the data points.
The lookuptable is stored as a header file and can, if necessary, be recreated using the ``create-temp-lookup-table.py`` script.

@ -0,0 +1 @@
<mxfile host="Electron" modified="2021-01-26T21:12:06.071Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="PrKjQ8DyGBUrBwv3aoCi" version="14.1.8" type="device"><diagram name="Page-1" id="099fd60b-425b-db50-ffb0-6b813814b670">7Vxbd6M4Ev41Pmf3IT7cL49ObHfmTHqS7cx07+yLj4xlWx2MHJAvya9fCQQGJGPHBl/S0w9pKGQJqr66qKqgpd/N1l9CMJ9+xSPotzRltG7p3ZamuY5K/zLCW0JQLUtPKJMQjThtQ3hG75ATFU5doBGMCgMJxj5B8yLRw0EAPVKggTDEq+KwMfaLq87BBAqEZw/4IvUHGpFpQnVMZUO/h2gyTVdWFX5lCLyXSYgXAV+vpenj+F9yeQbSufj4aApGeJUj6b2WfhdiTJKj2foO+oy3KduS3/W3XM3uO4QB2ecH8N5wZ2TQ/+PnqoPhj3Xn0fp5o2r85shbyhA4ovzhpzgkUzzBAfB7G+pt/NCQTavQs82YB4znlKhS4k9IyBsXNlgQTElTMvP5VbhG5L/85+z4b3bcNvlZd5271H3LnTzBEM0ggSGnRSTEL/AO+ziM7113tKFuWWx0QMK3bAl2kluDnW4Wic/SVcbI93PzjUzojAxKF5nN+R/hRehxzv3UX5V38HU98L4twG/6+rszgTdcGwgIJ5BUSMJOxjHu5xbgovwCMX3u8I0OCKEPCFoW0Qu4EkyycdlPnzCit6wpXGF1i8Mx1dcU6OkUyY3yX23gRA9yt7EhxSD7CODsawbcobCKz/ZH7/lQqFp1w7AAoAq0VN32EvgLvlKnS2eyfPoMt8OQHk1IxpccpJYwJIja+AcwhP4TjhBBOKCXhpgQPGO8T40xE8QIRNMMXcBHEzbUozxmosrDKJ22w8cQBj8215ytO1tPmItsQ5/6qZCNa4MhFTLwSHsEvBjHBPA7iddFIR2ZnK9gxJ6EzjBCdOWueKkECqhSWNgyGLmWrQMrN1nuWtfsOd1KKLFnhOtK2fOrmlk0JS5X7dXGjdp8xDTnQQ2rIbCo5uWYFkc/xri03RrMCwxGHRYf0dMABzCh9BHjqczV7YGnw82PIZof6bjLsj6pMbwEQKnWIYCqRkCt3uyXgJM8pnJKIZW9X0hFZQPecsPmbEC0fRlXHrn19xxuKyWFSNY/NLqTa4xzTo1RCxpzhAFWf1Hzq1+U+TWE4K+LxmNIH58+rKZ0ZnMfjREMxXjwC0ABHRH/SEkTDZccHtK4cMBmGPtofp8ChB5/5zPXCJb94ztVLVoQ2xTiuywZkg/wXKUhQJgCIATJxjYUhr0lZKa0KJZzSzui44A/SLQ1anuLkAlnkGrveYSslbyEIsjYkIjYakrE1f6DG9KLSQec0oafKJYxaKhpaI5p879qAR4ZPurPFlU99LVqfAgjFBEcRu0lCBEY+nCQkmJzn08ABAzHYo7gPJa/ZPhFo2BJjELmDGq3Cu5uGOTCLc8HUYS8ouy2cmWnQuWe2pQ8dUo7Ni/rtm1Lyf0zi4pXYm1iLgS9++i0zSV/5duDq642HG27ry39Iaqd1tYogJT7d/rn4eli42ofT5A3mABCwywfr+bUHgyoIU0mPo9FdXfmSk1NNC515EqleX79WhRxWylke/FkLzWVFz/2VNPat8lbbLdSwsyJK3WC9j8DuuVmW+8/qV2km23lX3SM8nL//m8BTTmpF9R8NUVUKecglsOK6m29It5fIXWjyFxNjHEynS1oZA0xjpTdZ801H5s5+3gpM8u13ShtRc0oyQ0Yrn5Iyu1wzZckyKTjNPc0qm+XInC1HP/VlFK2DUO6Tl1J4qGrWl9ty/vr5vX19jnovg6Wy5uzdgAcnSP2h3EAk8YkeSjnMsV/t3JZ5CPKKHsbwxIia1MDqQT1RkBv2UXQ66f1d2K6ubee44AyEVExCznmr3iJggnLQ1MosB4zTeknIeZniIpP44Qt3bqoqFg1zmKaDizDNtQ/VNWdtrt/6GwlpKrbzvcPUclgprbfY5qm/ADEm44Y6epD2BS++RhWlr0vZ33q0x+xX6v37ZvA2dRG0RnRPIJFbdjJ63nOY/IZck60LIrxeKx5nkwUI2tomTWJwilt1WTbCd0RJZHSapeEVh1kxVHMRcZXpzRq9Tc7busPKe81m4nmjXIjilVvNC/PJKmfDmlnaR6vROhOv5vGyk1D2TQP25jWlpQSK4JPIRz/E3h/MHRw3csKvCUVPkPh2UVBrvQhSVEkgrjKMpqh0SgxPzBC76wSywXNbSqd17xtmV02F7U4UWJ8KguHH+C2vjP5L6unllWrvuBA2cLtvvVJOG5YOzkua01vjuOS1qXPxfFyxvLsHHcEjt/36XkXEED/a7F90eUI4CI2LVm9I79/1E4qNNENPPwjtGqhSTr2Tis0vbqWfCEbgCt4ca8ysN+5A+C5nwtJvOknzz/k64l2qYHfcM8s5t37N7Nu8W2psVjFBrDUTe/oK/toJkJYpvpVlfJwp3q4WSoUWW4Jr02kOUTX1A/ha5uS7qbQe5HCPd54NuePRLhV6qLgZLKPKvBVWvkPE8icD9UtzdRLJePk7Ni8gt5WiltStW0UJ8HjcQSPTSpIy5lXVfW5vKqxzEU1Vzb+sCkqv+FQ/kzGjvHp4zVrXcQdeVqfumlpFpixDBN/1V15nM4EwBbhGJdNnotlkxz0zpJyMktJkKxbPBe4OpK4tbGGK10s+GfFwU1RUOn7QKwNfv59hl1K9GqmI4hLWlxsbp8h5lB+zeKiKSqOrLbYnOKIOfj4qxysLTRpiflVdaYUxuqSrbnakMr8rvXu4X/Cx5fftYe38Y8/jf8tHUkLb+ePzsPjlwr3oX7YfZymgb7UP6/tm6uq401FKW81gbddNEGEtYopbGZNecZjsqLPXCu3T1Qfss0LY7fYWfK4IPMFC9zS7CBjerlLrxeGlD+JRYpqFcSJTIrQE3lCQUiDeIlNiY3/X0GU7CNT88+j1mAYzTNeXJs7kGyZBXFWuIPSTkLyHmVjqVqp7ESbdTUR1FGScJTia8w3JwyhpIK46s+knCrZcMLW83KIfaO5bce1TFO1NUPVbVcpNerV1+ay/SmrX3i+lOaWzSfuoE/98OHwOErDs6/OpgI0xI+V6Jqo4eV3DGrTcDFd/FuQhCtpYueZukvkI8KeokvVK/kQwFndZA2CMJ1i5Ch1ek11AsgDFjG3FueelNad1ro1O/ToLvkUy/Uzf/f+U/bBngNYT083Xy5OrN7m89B67/8=</diagram></mxfile>

@ -0,0 +1,112 @@
.. _backup_ram:
Safety Backup RAM
=================
Overview
--------
The STM controller's backup RAM is used to store different kinds of information that shall be preserved if the controller resets.
The hardware setup is missing a separate powersupply for the controller's backup domain. Therefore, the backup RAM is cleared, when the power is cut.
The backup RAM is used to store permanent error flags (See :ref:`safety_flags`). This ensures the flags that trigger hard faults / the panic mode, can be identified, although the wathcoog resets the controller. The only way to clear them is by cutting the power.
Because cutting the power is a way to clear the backup RAM, no separate method for clearing the error entries in the backup RAM is defined.
The backup RAM contents are protected by a `CRC Checksum`_.
The backup RAM is initialized and checked after boot. If the controller starts from a powered down state,
the backup RAM is empty. This is detected by an invalid `Header`_ at the beginning of the backup RAM. If this is the case, the safety ocntoller
will create a valid backup RAM image with a `Header`_, empty `Boot Status Flag Entries`_, empty `Config Overrides`_, an empty `Error Memory`_, and a valid `CRC Checksum`_.
If the Header is valid during boot (verified by plausible values and correct magic numbers), the backup RAM is CRC checked and the error memory is
checked for valid entries.
In case of a CRC error or invalid entries in the error memory, the Backup RAM is wiped and reinitialized. On top of that, the error flag :ref:`safety_flags_safety_mem_corrupt` is set.
.. note:: It may be possible that future versions of the hardware include a backup RAM battery / Goldcap. In this case, a way to clear the error memory will be implemented,
because it will no longer be possible to clear the error memory by cutting the power.
On top of that, the backup memory will also contain the calibration data.
.. note:: The firmware will not use the ``NOP`` entries of the error memory by default, but they will be respected by the validity checker.
Partitioning and Entries
------------------------
The backup RAM consists of multiple sections. The memory section are listed below.
Header
~~~~~~
The backup memory header is located at offset address:
.. doxygendefine:: SAFETY_MEMORY_HEADER_ADDRESS
The header is defined by the following structure:
.. doxygenstruct:: safety_memory_header
The validity of the header is checked, if the magic and inverse amgic fields contain the correct values, and if the offset address pointers
have values that are located inside the error memory and are not ``0`` or the same value.
The safety memory header magic is:
.. doxygendefine:: SAFETY_MEMORY_MAGIC
.. _backup_ram_boot_flags:
Boot Status Flag Entries
~~~~~~~~~~~~~~~~~~~~~~~~
The boot status flag entries are use to store system states over resets.
The flags are stored in memory using the follwoing structure:
.. doxygenstruct:: safety_memory_boot_status
Flags are evaluated active, if the corresponding word is unequal to ``0``.
Config Overrides
~~~~~~~~~~~~~~~~
Config overrides are used to override persistance and flag weights dynamically. The safety controller will parse the entries on
startup.
======================= ============ ================= ===================== =====================================
Entry Byte 1 (LSB) Byte 2 Byte 3 Byte 4 (MSB)
======================= ============ ================= ===================== =====================================
Weight override ``0xA2`` ``Weight`` ``Flag Number`` reserved don't care (written as 0xAA)
Persistance override ``0x8E`` ``Persistance`` ``Flag Number`` reserved don't care (written as 0xBB)
======================= ============ ================= ===================== =====================================
All words, not matching the table above are ignored and do not cause an error. By default the firmware fills this memory area with zeroes.
Error Memory
~~~~~~~~~~~~
The error memory contains error entries in form of 32 bit words. The entries are coded as stated below.
``Error Flag`` entries are used to restore error flags after boot. In theory, all flags can be set using this entry type.
However, only persistent flags are stored in the error memory by the firmware.
``NOP`` entries have no meaning. They are used as a filler. When adding a new error memory entry, the error memory is scanned until the first ``NOP`` entry is found.
It is replaced with a valid entry. If the error memory contains a word, that is not defined below, it is considered invalid and will trigger the RAM checker on boot.
``NOP`` entries can be used to preallocate the error memory in advance. if the end of the error memory is reached, it is expanded by 1 word to first
the new error entry, until the backup RAM is full. After this, no further errors are stored.
If the same persistent error is triggered mutliple times, the ``COUNTER`` in the error entry is incremented.
======================= ============ ================= ===================== =====================================
Entry Byte 1 (LSB) Byte 2 Byte 3 Byte 4 (MSB)
======================= ============ ================= ===================== =====================================
Error Flag ``0x51`` ``Flag Number`` ``COUNTER 7:0`` ``COUNTER 15:8``
NOP Entry ``0x22`` ``0x12`` ``0xAA`` ``0xC1``
======================= ============ ================= ===================== =====================================
CRC Checksum
~~~~~~~~~~~~
The CRC checksum is located after the error memory. The checksum is calculated by the internal peripheral module of the STM32F4 controller.
Therefore, the CRC calculation is fixed.
The polynomial is ``0x4C11DB7`` (Ethernet CRC32):
.. math:: P_{CRC}(x) = x^{32}+x^{26}+x^{23}+x^{22}+x^{16}+x^{12}+x^{11}+x^{10}+x^{8}+x^{7}+x^{5}+x^{4}+x^{2}+x+1

@ -0,0 +1,20 @@
.. _safety_handling:
Error Handling
==============
.. _safety_panic:
Panic Mode
----------
.. _safety_error_mem:
Error memory
------------
Permanent errors are stored in the backup RAM of the STM. This ensures, that errors can be read even after a full system reset has occured.
.. seealso:: :ref:`backup_ram`

@ -0,0 +1,150 @@
.. _safety_flags:
Safety Flags
============
The safety flags are represented in software by the following enums
.. doxygenenum:: safety_flag
The safety flags can be temporarily or permanent. Some temporary flags are reset automatically, once the error condition disappears. Others have to be explicitly cleared.
The safety weights (if a flag stops the PID controller, or triggers the panic mode) are configured by default as described below. However, it will be possible to override these weights by
setting config entries in the safety memory.
.. todo:: Change docu of config entires in memory
----------------------------------------------------------------------------------------------------------------------------------
.. _safety_flags_adc_overflow:
ERR_FLAG_MEAS_ADC_OVERFLOW
--------------------------
``ERR_FLAG_MEAS_ADC_OVERFLOW`` is triggered in case of an overflow in the signal path of the measurement ADC. This should never happen unless there is a bug in the software.
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
yes no yes no
========== ============= ============= ===========
----------------------------------------------------------------------------------------------------------------------------------
.. _safety_flags_adc_off:
ERR_FLAG_MEAS_ADC_OFF
---------------------
``ERR_FLAG_MEAS_ADC_OFF`` signals that the measurement ADC for the PT1000 sensor is deactivated. This flag is automatically cleared by the firmware
once the ADC is started.
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
no yes yes no
========== ============= ============= ===========
----------------------------------------------------------------------------------------------------------------------------------
.. _safety_flags_adc_watchdog:
ERR_FLAG_MEAS_ADC_WATCHDOG
--------------------------
``ERR_FLAG_MEAS_ADC_WATCHDOG`` is used as a wire break detection mechanism. This flag is set when the PT1000 measurement ADC detects an invalid resistance measurement.
.. seealso:: :ref:`ADC Watchdog<firmware_meas_adc_watchdog>`
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
no no yes no
========== ============= ============= ===========
----------------------------------------------------------------------------------------------------------------------------------
.. _safety_flags_adc_unstable:
ERR_FLAG_MEAS_ADC_UNSTABLE
--------------------------
``ERR_FLAG_MEAS_ADC_UNSTABLE`` is set if the Moving Average Filter of the PT1000 ADC detects a bigger deviation between input and filtered output value.
The flag is automatically cleared by the controller as soon as the unstable condition is not met anymore. For this, the filter input to filter output difference has to stay below a certain threshold for a defined amount of samples.
.. seealso:: :ref:`firmware_meas_adc_filter`
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
no yes no no
========== ============= ============= ===========
.. _safety_flags_safety_mem_corrupt:
ERR_FLAG_SAFETY_MEM_CORRUPT
---------------------------
``ERR_FLAG_SAFETY_MEM_CORRUPT`` is set during the initialization of the controller, in case a corrupted safety memory is encountered.
In this case the error memory is reinitialized and the flag is set in the error memory. Afer a reboot it will stay asserted until the
safety backup memory is cleared.
.. seealso:: :ref:`backup_ram`
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
yes no yes no
========== ============= ============= ===========
.. _safety_flags_stack:
ERR_FLAG_STACK
---------------------------
``ERR_FLAG_STACK`` Shutdown of the controller, in case a corrupted safety memory is encountered.
This error is not recoverable and will trigger the panic mode.
.. seealso:: :ref:`safety_stack_checking`
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
yes no yes yes
========== ============= ============= ===========
.. _safety_flags_timing_pid:
ERR_FLAG_TIMING_PID
---------------------------
``ERR_FLAG_TIMING_PID`` is set if the timing monitor of the PID controller detects a violation in the sample frequency.
The flag is recoverable and only shuts down the PID and therefore the oven control output.
.. seealso:: Timing Monitor
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
no no yes no
========== ============= ============= ===========
.. _safety_flags_overtemp:
ERR_FLAG_OVERTEMP
---------------------------
``ERR_FLAG_OVERTEMP`` is set if the :ref:`pt1000_processing` detects an overtemperature.
The default limit is set to:
.. doxygendefine:: SAFETY_DEFAULT_OVERTEMP_LIMIT_DEGC
However, it is possible to configure the limit and permanenty store it in the EEPROM since hardware version v1.3.
========== ============= ============= ===========
persistent self-clearing Stops PID Panic Mode
========== ============= ============= ===========
no no yes no
========== ============= ============= ===========

@ -0,0 +1,25 @@
.. _firmware_safety:
Safety Controller
=================
The safety controller is the software component that monitors the overall condition of the reflow controller,
and stops the output driver in case of an error.
Severe error flags, like a drifting reference voltage, stop the PID controller and force the output to zero.
The controller stays in a usable state. After the errors have been cleared, normal operation may continue.
On the other hand, fatal errors like an over-temperature error, or memory problem, lead to the activation of the :ref:`safety_panic`,
which forces the output zero, but does not allow any further interaction.
On top of this, a :ref:`backup_ram` is implemented. It stores permantent errors, which are reset at a restart. On top of that, it stores the :ref:`backup_ram_boot_flags`,
which are used to retain boot information across resets, for example to communicate with the firmware updater etc. The RAM also contains entries, that allow overrides of flag weights and persistance.
.. toctree::
:maxdepth: 3
flags
backup-ram
error-handling
startup-tests
stack-checking

@ -0,0 +1,39 @@
.. _safety_stack_checking:
Safety Stack Checking
=====================
To ensure correct operation of the controller, the stack is continuously monitored. For this, the :ref:`firmware_safety` checks the stack in each run.
These checks include:
1. Checking of used stack space and limit to end of stack
2. Checking a protection area between heap and stack for memory corruption
Any detected error will set the :ref:`safety_flags_stack` error flag.
Stack Pointer Checking
----------------------
The stack pointer is checked using :c:func:`stack_check_get_free`. The returned value for the remaining stack space is checked against
.. doxygendefine:: SAFETY_MIN_STACK_FREE
.. doxygenfunction:: stack_check_get_free
Stack and Heap Corruption Checking
----------------------------------
A section of memory is located between the stack and the heap. It is defined inside the linker script. It's size is configured by the linker script parameter ``__stack_corruption_area_size``, which is set to ``128`` by default.
This section is filled at the initializazion of the safety controller by a call to
.. doxygenfunction:: stack_check_init_corruption_detect_area
On each run of the safety controller's handling function (:c:func:`safety_controller_handle`) the following function is called:
.. doxygenfunction:: stack_check_corruption_detect_area
This function checks the memory area for write modifications, and therefore detects, if the stack or heap have grown outside their boundaries. This canary approach does, however, not guarantee a full protection against heap or stack overflows.

@ -0,0 +1,23 @@
.. _safety_startup_tests:
Startup Tests
=============
The following tests will be performed after each reset / power cycle of the controller.
Internal Memory Test
--------------------
Directly after startup and after setting up the system clocks, the controller performs memory checks on the internal SRAM and the core coupled memory.
RAM checking is performed by testing the following sequences:
- Alternating 0x55AA55AA / 0xAA55AA55 pattern
- Alternating 0xAA55AA55 / 0x55AA55AA pattern
- 0xFFFFFFFF constant value
- 0x00000000 constant value
The following functions implement the RAM checking:
.. doxygenfunction:: startup_test_perform_ccm_ram_check
.. doxygenfunction:: startup_test_perform_system_ram_check

@ -0,0 +1,8 @@
.. _hw_bom:
Interactive BoM of Controller Board
===================================
.. raw:: html
<iframe src="../_static/ibom.html" width="100%" height="1500"></iframe>

File diff suppressed because it is too large Load Diff

After

(image error) Size: 284 KiB

@ -0,0 +1,10 @@
.. _hw_analog_fe:
Analog Frontend
===============
Schematic
---------
.. image:: frontend-schematic_v1.2.svg
:target: /_images/frontend-schematic_v1.2.svg

@ -0,0 +1,27 @@
.. _hw_watchdog:
Hardware Watchdog
=================
the PCB (> v1.3) is equipped with an external power supply monitor and hardware watchdog IC ``STM6822S``.
The watchdog is periodically reset by the firmware.
.. note:: The external watchdog is only activated in Release mode. When building the application in Debug mode, it is deactivated because setting breakpoints or other events that distrb the program flow would trigger a the external watchdog and force a software reset.
During startup of the power supply, it keeps the controller in reset until the power supply is stable.
The following picture shows the 3.3 Volt supply rail on channel 2 and the low active reset signal of the STM32F407 on channel 1.
.. image:: hw_watchdog_delay.png
:alt: Image not found
The total startup delay is larger than 200 ms.
The follwoing figure shows the startup of the voltage rgulator and the reset signal.
.. image:: hw_watchdog_startup.png
:alt: Image not found
The power supply is gradually ramped up over approximately 500 us. The external watchdog does not work fpr voltages below 0.9 Volt. Therefore the reset signal rises simultaneously.
Once the supply voltage exceeds 0.9 Volts, the reset signal is pulled low. This ensures that the controller is not able to start until the > 200 ms startup time have passed.

Binary file not shown.

After

(image error) Size: 27 KiB

Binary file not shown.

After

(image error) Size: 28 KiB

@ -0,0 +1,20 @@
.. _hw:
Hardware
========
This guide on the reflow controller's hardware is based on the ``reflow-oven-control-pcb`` -- Version ``v1.3``
.. toctree::
:maxdepth: 2
:glob:
*
Links
-----
- `Reflow Oven Control PCB v1.2 schematic <https://git.shimatta.de/attachments/788fde4e-a560-445b-87ea-de1d67f6846a>`__
- `Git Repository for Controller PCB <https://git.shimatta.de/pcb/reflow-oven-control-pcb>`__

@ -0,0 +1,23 @@
.. _hardware_modifications_v1_2:
Hardware Modifications for PCB v1.2
===================================
Analog Frontend
---------------
.. note::
Solder a ``100 nF`` capacitor parallel to ``R315`` in order to implement a low pass characteristic of the difference amplifier in the :ref:`analog frontend<hw_analog_fe>`. This massively increases EMI performance which prevents the :ref:`ADC Watchdog<firmware_meas_adc_watchdog>` from triggering.
Power Supply
------------
.. note::
Replace transformer ``BV-EI-303-2010`` with ``BV-EI-303-2050``, which has the same footprint but a little more power and does not heat that much.
.. _hardware_modifications_v1_3:
Hardware Modifications for PCB v1.3
===================================
.. note::
solder jumpers to bridge GND and Earth together must be soldered for the SD card slot to work properly. The card detect's switch terminal is on Earth potential.

27
doc/source/index.rst Normal file

@ -0,0 +1,27 @@
.. Shimatta Reflow Controller documentation master file, created by
sphinx-quickstart on Thu Jul 30 22:56:09 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Shimatta Reflow Controller's documentation!
======================================================
Quick Links
===========
* :ref:`genindex`
* :ref:`hardware_modifications_v1_2`
* :ref:`hardware_modifications_v1_3`
.. warning::
Although the Shimatta Reflow Controller provides a bunch of safety mechanisms that -- in theory -- prevent your house from burning down, NEVER leave the oven controller running unattended. This project is published in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
.. toctree::
:maxdepth: 2
:caption: Contents
self
usage/index
hardware/index
firmware/index
license

427
doc/source/license.rst Normal file

@ -0,0 +1,427 @@
.. _license:
License
=======
The firmware of the reflow controller and its hardware are distributed under the GPLv2 license (see below).
The firmware includes following third-party software libraries:
- ``shellmatta`` by ``Stefan Strobel`` <https://git.shimatta.net/shimatta/shellmatta>, licensed under ``Mozilla Public License Version 2.0``
- ``CMSIS`` by ``ARM Limited`` <https://github.com/ARM-software/CMSIS_5>, licensed under ``Apache License Version 2.0, January 2004``
- ``STM Header files and startup code`` by ``ST Microelectronics``, licensed under a `custom license <ST License for Used Header Files_>`_
- ``SHA-256 Library`` by ``Alain Mosnier`` <https://github.com/amosnier/sha-2>, licensed under ``Zero Clause BSD License`` or the ``Unlicense``
- ``FatFS`` Library by ``ChaN`` licensed under a `custom license <FatFS License_>`_
FatFS License
-------------
FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files.::
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module Rx.xx /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 20xx, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license.
ST License for Used Header Files
--------------------------------
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. Neither the name of STMicroelectronics nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
GNU GENERAL PUBLIC LICENSE
--------------------------
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
~~~~~~~~
The licenses for most software are designed to take away your freedom
to share and change it. By contrast, the GNU General Public License is
intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on,
we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not reflect
on the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at
all.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**0.** This License applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work
based on the Program" means either the Program or any derivative work
under copyright law: that is to say, a work containing the Program or
a portion of it, either verbatim or with modifications and/or
translated into another language. (Hereinafter, translation is
included without limitation in the term "modification".) Each licensee
is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the Program
(independent of having been made by running the Program). Whether that
is true depends on what the Program does.
**1.** You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a
fee.
**2.** You may modify your copy or copies of the Program or any
portion of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
**a)** You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
**b)** You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any part
thereof, to be licensed as a whole at no charge to all third parties
under the terms of this License.
**c)** If the modified program normally reads commands interactively
when run, you must cause it, when started running for such interactive
use in the most ordinary way, to print or display an announcement
including an appropriate copyright notice and a notice that there is
no warranty (or else, saying that you provide a warranty) and that
users may redistribute the program under these conditions, and telling
the user how to view a copy of this License. (Exception: if the
Program itself is interactive but does not normally print such an
announcement, your work based on the Program is not required to print
an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
**3.** You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
**a)** Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections 1
and 2 above on a medium customarily used for software interchange; or,
**b)** Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your cost of
physically performing source distribution, a complete machine-readable
copy of the corresponding source code, to be distributed under the
terms of Sections 1 and 2 above on a medium customarily used for
software interchange; or,
**c)** Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is allowed
only for noncommercial distribution and only if you received the
program in object code or executable form with such an offer, in
accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
**4.** You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt otherwise
to copy, modify, sublicense or distribute the Program is void, and
will automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
**5.** You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
**6.** Each time you redistribute the Program (or any work based on
the Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
**7.** If, as a consequence of a court judgment or allegation of
patent infringement or for any other reason (not limited to patent
issues), conditions are imposed on you (whether by court order,
agreement or otherwise) that contradict the conditions of this
License, they do not excuse you from the conditions of this License.
If you cannot distribute so as to satisfy simultaneously your
obligations under this License and any other pertinent obligations,
then as a consequence you may not distribute the Program at all. For
example, if a patent license would not permit royalty-free
redistribution of the Program by all those who receive copies directly
or indirectly through you, then the only way you could satisfy both it
and this License would be to refrain entirely from distribution of the
Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
**8.** If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
**9.** The Free Software Foundation may publish revised and/or new
versions of the General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Program does not specify a
version number of this License, you may choose any version ever
published by the Free Software Foundation.
**10.** If you wish to incorporate parts of the Program into other
free programs whose distribution conditions are different, write to
the author to ask for permission. For software which is copyrighted by
the Free Software Foundation, write to the Free Software Foundation;
we sometimes make exceptions for this. Our decision will be guided by
the two goals of preserving the free status of all derivatives of our
free software and of promoting the sharing and reuse of software
generally.
**NO WARRANTY**
**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does.
Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Also add information on how to contact you by electronic and paper
mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type ``show w``. This is free software, and you are welcome
to redistribute it under certain conditions; type ``show c``
for details.
The hypothetical commands \`show w' and \`show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than \`show w' and
\`show c'; they could even be mouse-clicks or menu items--whatever
suits your program.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the program,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program ``Gnomovision``
(which makes passes at compilers) written
by James Hacker.
signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice``
This General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library,
you may consider it more useful to permit linking proprietary
applications with the library. If this is what you want to do, use the
[GNU Lesser General Public
License](<https://www.gnu.org/licenses/lgpl.html>) instead of this
License.

@ -0,0 +1,15 @@
# This is a comment
pid_conf 10 0.3 5 60 2.5 0.5
temp_set 50
wait_temp 45
temp_set 45
temp_ramp 150 120
temp_ramp 190 90
pid_conf 9 0.5 6 60 2.5 0.5
temp_set 250
wait_temp 245
temp_off
beep 1
wait_time 1
beep 0

@ -0,0 +1,17 @@
.. _usage_calibration:
Calibration
===========
In order to provide higher measurement accuracy, the PT1000 measurement can be calibrated. The calibration only calibrates the internal :ref:`hw_analog_fe` and not the PT1000 Sensor element itself.
The Sensor element must be conform with the standard PT1000 norms.
Tests have shown, that a calibration is most likely not necessary, because the resolution of the 12 bit analog measurement is far worse than the reistance reading error produced by the :ref:`hw_analog_fe`.
Calibration might only be necessary if no precission reistors in the frontend hardware are used.
Calibration can be performed the following ways:
Command Line Calibration
------------------------
Use the :ref:`command_line` to invoke the :ref:`shell_command_calibrate` command.

@ -0,0 +1,88 @@
.. _command_line:
Command Line Interface
======================
This section describes the command line interface located on the UART interface.
The command line interface is implemented using a "shellmatta" shell module <https://git.shimatta.net/shimatta/shellmatta>
Hardware Settings
-----------------
General Settings
~~~~~~~~~~~~~~~~
The UART is configured for the following settings:
- 115200 Baud
- 1 Stopbit
- No parity
- 8 data bits
Setup in Debug Build
~~~~~~~~~~~~~~~~~~~~
If the Reflow controller is build in **debug** mode, the UART is located on the internal spring contact connector, which is also used for the SWD interface.
Setup in Release Build
~~~~~~~~~~~~~~~~~~~~~~
In case of a **release** build, the UART is externally accessible on the DIGIO Header. The voltage level is 3.3 Volt LVCMOS. The inputs are ESD protected. Overvoltage is interally clamped and may dammage the clamping diodes!
- DIGIO2: Reflow Controller's TX
- DIGIO3: Reflow Controller's RX
Shell Commands
--------------
The following shell commands are available.
- `safety-flags <safety-flags_>`_ (alias: flags)
- `calibrate`_ (alias: cal)
safety-flags
~~~~~~~~~~~~
The ``safety-flags`` (``flags``) command displays the status of all safety flags and analog monitors. See: :ref:`safety_flags`
.. _shell_command_calibrate:
calibrate
~~~~~~~~~
The ``calibrate`` (``cal``) command is used to calibrate the :ref:`hw_analog_fe`, in order to ensure correct resistance measurement.
Calibration is most likely not necessary! See the :ref:`usage_calibration` page.
The command will guide you through the calibration process and will ask for two reference resistors with ``1000 Ohm`` and ``2000 Ohm`` values.
Calibration can be aborted using ``CTRL + C``.
.. _shell_command_hang:
hang
~~~~
The ``hang`` command hangs the main-loop in an infinite loop. This function tests, whether the controller is correctly rescued by the watchdog.
.. _shell_command_ui_emulate:
ui-emulate
~~~~~~~~~~
The ``ui-emulate`` command emulates the rotary encoder and button from the shell. The following keys are available:
========== ================================
Key Emulation
========== ================================
``CTRL+C`` Exit the command
``ENTER`` Button press: short released
``s`` Rotary Encoder: anti-clockwise
``w`` Rotary Encoder: clockwise
``l`` Button press: long
``k`` Button press: short
``r`` Button press: long released
========== ================================

@ -0,0 +1,12 @@
.. _usage:
Reflow Controller Usage Guide
=============================
.. toctree::
:maxdepth: 2
command-line
calibration

3
error-mem-viewer/.gitignore vendored Normal file

@ -0,0 +1,3 @@
*.ui~
*.user
*.user*

@ -0,0 +1,26 @@
project(error-mem-viewer)
cmake_minimum_required(VERSION 2.8)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED glib-2.0)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
pkg_check_modules(GTK_MOD REQUIRED gmodule-2.0)
aux_source_directory("src" SRCES)
include_directories("include" ${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS} ${GTK_MOD_INCLUDE_DIRS})
add_subdirectory(resources)
set(SOURCE_GENERATED
${CMAKE_CURRENT_BINARY_DIR}/resources/resources.c
)
SET_SOURCE_FILES_PROPERTIES(${SOURCE_GENERATED} PROPERTIES GENERATED 1)
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
link_directories(${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS} ${GTK_MOD_LINK_DIRS})
add_definitions(${GLIB2_CFLAGS_OTHER} ${GTK_MOD_CFLAGS_OTHER})
add_executable(${PROJECT_NAME} ${SRCES} ${SOURCE_GENERATED})
target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${GTK3_LDFLAGS} ${GTK_MOD_LDFLAGS})
add_dependencies(${PROJECT_NAME} glib-resources)

@ -0,0 +1,10 @@
#ifndef _CRC_H_
#define _CRC_H_
#include <stdint.h>
#include <stddef.h>
uint32_t calculate_stm_crc(uint32_t *data, size_t len);
#endif /* _CRC_H_ */

@ -0,0 +1,15 @@
#ifndef _ERR_MEM_VIEWER_ADDRESS_CELL_RENDERER_H_
#define _ERR_MEM_VIEWER_ADDRESS_CELL_RENDERER_H_
#include <gtk/gtk.h>
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(ErrMemViewHexCellRenderer, err_mem_view_hex_cell_renderer, ERR_MEM_VIEW, HEX_CELL_RENDERER, GtkCellRendererText)
#define ERR_MEM_VIEW_TYPE_HEX_CELL_RENDERER (err_mem_view_address_cell_renderer_get_type())
GtkCellRenderer *err_mem_view_hex_cell_renderer_new();
G_END_DECLS
#endif /* _ERR_MEM_VIEWER_ADDRESS_CELL_RENDERER_H_ */

@ -0,0 +1,58 @@
#ifndef _SAFETY_MEM_TYPES_H_
#define _SAFETY_MEM_TYPES_H_
#include <stdint.h>
/**
* @brief Magic number to signal a valid safety memory header.
*/
#define SAFETY_MEMORY_MAGIC 0x12AA5CB7
/**
* @brief Error memory NOP entry
*/
#define SAFETY_MEMORY_NOP_ENTRY 0xC1AA1222
/**
* @brief Safety memory header
*/
struct safety_memory_header {
uint32_t magic; /**< @brief Magic. Set to @ref SAFETY_MEMORY_MAGIC */
uint32_t boot_status_offset; /**< @brief Offset of the safety_memory_boot_status struct (in 32 bit words)*/
uint32_t config_overrides_offset; /**< @brief Offset address of override entries */
uint32_t config_overrides_len; /**< @brief Length of override entries in words */
uint32_t firmware_update_filename; /**< @brief Filename of the firmware update. This string is at maximum 256 bytes long including the 0 terminator */
uint32_t err_memory_offset; /**< @brief Offset of the error memory */
uint32_t err_memory_end; /**< @brief End of the error memory. This points to the word after the error memory, containing the CRC of the whole backup RAM. */
uint32_t crc; /**< @brief CRC of the header */
};
struct safety_memory_boot_status {
/**
* @brief Reboot into the bootloader
*
* When this flag is set, the controller will load the bootloader to
* memory and execute it.
*/
uint32_t reboot_to_bootloader;
/**
* @brief Bootloader has updated the code
*
* This flag is set, if the firmware ahs been updated successfully
*/
uint32_t code_updated;
/**
* @brief reset_from_panic
*
* This flag is set, when entering the panic mode.
* Because the panic mode is reset by a watchdog reset,
* this flag is needed, in order to ensure, that the panic is handled correcly after
* the watchdog reset.
*/
uint32_t reset_from_panic;
};
#endif /* _SAFETY_MEM_TYPES_H_ */

@ -0,0 +1,9 @@
add_custom_target(glib-resources DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/resources.c")
add_custom_command(DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/*.ui"
"${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/resources.c"
COMMAND
glib-compile-resources --target="${CMAKE_CURRENT_BINARY_DIR}/resources.c" --sourcedir="${CMAKE_CURRENT_SOURCE_DIR}" --generate-source "${CMAKE_CURRENT_SOURCE_DIR}/resources.xml"
)

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.1 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="main-window">
<property name="name">main-window</property>
<property name="can-focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkInfoBar" id="info-bar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="message-type">warning</property>
<property name="show-close-button">True</property>
<property name="revealed">False</property>
<signal name="response" handler="info_bar_close_cb" swapped="no"/>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can-focus">False</property>
<property name="spacing">6</property>
<property name="layout-style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child internal-child="content_area">
<object class="GtkBox">
<property name="can-focus">False</property>
<property name="spacing">16</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTreeView" id="error-mem-tree-view">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar" id="header-bar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="title" translatable="yes">Error Memory Viewer</property>
<property name="subtitle" translatable="yes">Reflow Controller Error Memory Viewer</property>
<property name="show-close-button">True</property>
<child>
<object class="GtkButton" id="open-button">
<property name="label">gtk-open</property>
<property name="name">open-button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="open_button_clicked_cb" swapped="no"/>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</child>
</object>
</interface>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/gui">
<file compressed="true" alias="main">main-window.ui</file>
</gresource>
</gresources>

@ -0,0 +1,25 @@
#include <error-mem-viewer/crc.h>
static uint32_t do_crc(uint32_t init, uint32_t data)
{
uint32_t crc = init;
uint32_t cnt;
for (cnt=0; cnt < 32; cnt++) {
crc = ((int32_t)(crc ^ data))<0 ? (crc << 1) ^ 0x04C11DB7 : crc << 1;
data <<=1;
}
return crc;
}
uint32_t calculate_stm_crc(uint32_t *data, size_t len)
{
uint32_t crc = ~0U;
while (len--) {
crc = do_crc(crc, *data++);
}
return crc;
}

@ -0,0 +1,81 @@
#include <error-mem-viewer/err-mem-viewer-hex-cell-renderer.h>
#include <string.h>
struct _ErrMemViewHexCellRenderer {
GtkCellRendererText base;
};
enum {
PROP_HEXNUM = 1,
PROP_COUNT
};
G_DEFINE_TYPE(ErrMemViewHexCellRenderer, err_mem_view_address_cell_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
static void err_mem_view_address_cell_renderer_init(ErrMemViewHexCellRenderer *self)
{
(void)self;
}
static void convert_gvalue_uint_to_string(const GValue *in, GValue *out)
{
uint32_t val;
char text[32];
if (!in || !out)
return;
g_value_init(out, G_TYPE_STRING);
val = g_value_get_uint(in);
snprintf(text, sizeof(text), "0x%08X", val);
g_value_set_string(out, text);
}
static void err_mem_view_address_cell_renderer_set_property(GObject *obj, guint param_id, const GValue *value, GParamSpec *pspec)
{
GValue val = G_VALUE_INIT;
switch (param_id) {
case PROP_HEXNUM:
convert_gvalue_uint_to_string(value, &val);
g_object_set_property(obj, "text", &val);
g_value_unset(&val);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
}
}
static void err_mem_view_address_cell_renderer_get_property(GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
(void)value;
switch (param_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
break;
}
}
static GParamSpec *properties[PROP_COUNT];
void err_mem_view_address_cell_renderer_class_init(ErrMemViewHexCellRendererClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS(klass);
oclass->set_property = err_mem_view_address_cell_renderer_set_property;
oclass->get_property = err_mem_view_address_cell_renderer_get_property;
properties[PROP_HEXNUM] = g_param_spec_uint("hex-num", "hex-num", "Hex number to display", 0U, UINT_MAX, 0U, G_PARAM_WRITABLE);
g_object_class_install_properties(oclass, PROP_COUNT, properties);
}
GtkCellRenderer *err_mem_view_hex_cell_renderer_new()
{
return GTK_CELL_RENDERER(g_object_new(ERR_MEM_VIEW_TYPE_HEX_CELL_RENDERER, NULL));
}

542
error-mem-viewer/src/main.c Normal file

@ -0,0 +1,542 @@
#include <gtk/gtk.h>
#include <glib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <error-mem-viewer/err-mem-viewer-hex-cell-renderer.h>
#include <error-mem-viewer/safety-memory-types.h>
#include <error-mem-viewer/crc.h>
enum memory_view_columns {
MEM_VIEW_COL_ADDRESS = 0,
MEM_VIEW_COL_DATA,
MEM_VIEW_COL_INTERPRETATION,
MEM_VIEW_COLOR,
MEM_VIEW_COLUMN_COUNT
};
struct application_data {
GtkWidget *borrowed_main_window;
GtkTreeView *borrowed_tree_view;
GtkHeaderBar *borrowed_header_bar;
GtkInfoBar *borrowed_info_bar;
const char *error_memory_data;
size_t file_size;
};
enum entry_state {
ENTRY_STATE_VALID = 0,
ENTRY_STATE_INVALID,
ENTRY_STATE_NOT_PARSED,
ENTRY_STATE_BLOCK
};
static void append_data(GtkTreeStore *store, GtkTreeIter *parent, GtkTreeIter *iter, GString *interpretation, enum entry_state state, uint32_t addr, uint32_t val)
{
const GdkRGBA invalid_color = {
.red = 1.0,
.alpha = 1.0,
.green = 0.0,
.blue = 0.0,
};
const GdkRGBA valid_color = {
.red = 0.0,
.alpha = 1.0,
.green = 1.0,
.blue = 0.0,
};
const GdkRGBA warn_color = {
.red = 1.0,
.alpha = 1.0,
.green = 1.0,
.blue = 0.0,
};
const GdkRGBA block_color = {
.red = 1.0,
.alpha = 1.0,
.green = 0.3,
.blue = 0.5,
};
const GdkRGBA *col;
switch (state) {
case ENTRY_STATE_VALID:
col = &valid_color;
break;
case ENTRY_STATE_NOT_PARSED:
col = &warn_color;
break;
case ENTRY_STATE_BLOCK:
col = &block_color;
break;
case ENTRY_STATE_INVALID:
default:
col = &invalid_color;
break;
}
gtk_tree_store_append(store, iter, parent);
gtk_tree_store_set(store, iter, MEM_VIEW_COL_ADDRESS, addr, MEM_VIEW_COLOR, col, MEM_VIEW_COL_INTERPRETATION, (interpretation ? interpretation->str : ""), MEM_VIEW_COL_DATA, val, -1);
if (interpretation)
g_string_free(interpretation, TRUE);
}
static void info_bar_show_message(GtkInfoBar *info_bar, GtkMessageType type, const char *format, ...)
{
GString *string;
va_list args;
GtkWidget *content;
GList *children, *iter;
GtkWidget *label;
va_start(args, format);
string = g_string_new(NULL);
g_string_vprintf(string, format, args);
va_end(args);
content = gtk_info_bar_get_content_area(info_bar);
children = gtk_container_get_children(GTK_CONTAINER(content));
for (iter = children; iter; iter = g_list_next(iter))
gtk_widget_destroy(GTK_WIDGET(iter->data));
g_list_free(children);
label = gtk_label_new(string->str);
gtk_container_add(GTK_CONTAINER(content), label);
gtk_widget_show(label);
gtk_info_bar_set_message_type(info_bar, type);
gtk_widget_show(GTK_WIDGET(info_bar));
gtk_info_bar_set_revealed(info_bar, TRUE);
g_string_free(string, TRUE);
}
static bool check_err_mem_header(struct safety_memory_header *header, uint32_t *expected)
{
uint32_t crc;
crc = calculate_stm_crc((uint32_t *)header, sizeof(*header) / sizeof(uint32_t) - 1);
if (expected)
*expected = crc;
if (crc == header->crc)
return true;
else
return false;
}
static GString *new_string_printf(const char *fmt, ...)
{
GString *string;
va_list args;
va_start(args, fmt);
string = g_string_new(NULL);
g_string_vprintf(string, fmt, args);
va_end(args);
return string;
}
static void show_error_memory(GtkTreeView *tree_view, const unsigned char *memory, size_t len)
{
GtkTreeStore *store;
GtkTreeIter iter;
GtkTreeIter iter2;
GtkTreeIter *parent_iter, *child_iter;
enum entry_state state;
GString *interpret;
bool valid;
bool analyze_further = true;
struct safety_memory_header header;
unsigned int i;
uint32_t dat, expected_value;
store = GTK_TREE_STORE(gtk_tree_view_get_model(tree_view));
gtk_tree_store_clear(store);
for (i = 0; i < len / 4; i++) {
valid = false;
interpret = NULL;
dat = memory[i*4];
dat |= ((uint32_t)memory[i*4+1]) << 8;
dat |= ((uint32_t)memory[i*4+2]) << 16;
dat |= ((uint32_t)memory[i*4+3]) << 24;
state = ENTRY_STATE_NOT_PARSED;
if (!analyze_further) {
interpret = g_string_new("Not analyzed due to previous error");
state = ENTRY_STATE_NOT_PARSED;
parent_iter = NULL;
child_iter = &iter;
goto print;
}
/* Parse header */
switch (i) {
case 0: /* Magic */
parent_iter = NULL;
child_iter = &iter;
append_data(store, parent_iter, child_iter, new_string_printf("Header"), ENTRY_STATE_BLOCK, i * 4, dat);
parent_iter = child_iter;
child_iter = &iter2;
if (dat == SAFETY_MEMORY_MAGIC) {
valid = true;
interpret = g_string_new("Valid Header Magic");
} else {
interpret = g_string_new("Invalid Header Magic");
analyze_further = false;
}
header.magic = dat;
break;
case 1:
header.boot_status_offset = dat;
valid = true;
interpret = new_string_printf("Boot status offset addr: %u", dat);
break;
case 2:
header.config_overrides_offset = dat;
interpret = new_string_printf("Config override offset addr: %u", dat);
valid = true;
break;
case 3:
header.config_overrides_len = dat;
interpret = new_string_printf("Config override length: %u", dat);
valid = true;
break;
case 4:
header.firmware_update_filename = dat;
interpret = new_string_printf("Offset of FW update filename: %u", dat);
valid = true;
break;
case 5:
header.err_memory_offset = dat;
interpret = new_string_printf("Error memory offset addr: %u", dat);
valid = true;
break;
case 6:
header.err_memory_end = dat;
interpret = new_string_printf("Error memory end ptr: %u", dat);
valid = true;
break;
case 7:
header.crc = dat;
valid = check_err_mem_header(&header, &expected_value);
if (valid) {
interpret = new_string_printf("Header CRC: 0x%08X", dat);
} else {
interpret = new_string_printf("Invalid CRC: 0x%08X | Expected: 0x%08X", dat, expected_value);
analyze_further = false;
}
break;
}
if (i <= 7) {
state = ENTRY_STATE_INVALID;
goto print;
}
/* Check if we're in the boot status structure */
if (i >= header.boot_status_offset && i < header.boot_status_offset + sizeof(struct safety_memory_boot_status) / 4) {
if (i == header.boot_status_offset) {
/* First entry of boot status struct */
parent_iter = NULL;
child_iter = &iter;
interpret = new_string_printf("Boot Status Struct");
append_data(store, parent_iter, child_iter, interpret, ENTRY_STATE_BLOCK, i * 4, dat);
parent_iter = &iter;
child_iter = &iter2;
interpret = NULL;
}
switch (i - header.boot_status_offset) {
case 0:
interpret = new_string_printf("%s into bootloader", (dat ? "Boot" : "Do not boot"));
valid = true;
break;
case 1:
interpret = new_string_printf("Code %s been updated", (dat ? "has" : "hasn't"));
valid = true;
break;
case 2:
interpret = new_string_printf("Panic %s", (dat ? "occured" : "did not occur"));
valid = true;
break;
default:
valid = false;
interpret = new_string_printf("Value undefined!");
break;
}
state = ENTRY_STATE_INVALID;
goto print;
}
if (i >= header.config_overrides_offset && i < (header.config_overrides_offset + header.config_overrides_len)) {
if (i == header.config_overrides_offset) {
parent_iter = NULL;
child_iter = &iter;
append_data(store, parent_iter, child_iter,
new_string_printf("Config Overrides"),
ENTRY_STATE_BLOCK, i * 4, dat);
parent_iter = child_iter;
child_iter = &iter2;
}
interpret = new_string_printf("Config Overrides not yet implemented");
valid = true;
state = ENTRY_STATE_INVALID;
goto print;
}
if (i >= header.err_memory_offset && i < header.err_memory_end) {
if (i == header.err_memory_offset) {
parent_iter = NULL;
child_iter = &iter;
append_data(store, parent_iter, child_iter,
new_string_printf("Error Memory (length: %d)", header.err_memory_end - header.err_memory_offset),
ENTRY_STATE_BLOCK, i * 4, dat);
parent_iter = child_iter;
child_iter = &iter2;
}
switch (dat) {
case SAFETY_MEMORY_NOP_ENTRY:
valid = true;
interpret = new_string_printf("Error Memory NOP");
break;
default:
if ((dat & 0xFFU) == 0x51U) {
valid = true;
interpret = new_string_printf("Err memory Entry");
} else
interpret = new_string_printf("Invalid error memory entry");
break;
}
state = ENTRY_STATE_INVALID;
goto print;
}
if (i == header.err_memory_end) {
expected_value = calculate_stm_crc((uint32_t *)memory, header.err_memory_end);
if (expected_value == dat) {
interpret = new_string_printf("Valid Memory CRC");
valid = true;
} else {
interpret = new_string_printf("Invalid CRC. Expected: 0x%08X", expected_value);
}
state = ENTRY_STATE_INVALID;
parent_iter = NULL;
child_iter = &iter;
goto print;
}
parent_iter = NULL;
child_iter = &iter;
print:
if (state != ENTRY_STATE_NOT_PARSED) {
state = (valid ? ENTRY_STATE_VALID : ENTRY_STATE_INVALID);
}
append_data(store, parent_iter, child_iter, interpret, state, i * 4, dat);
}
if (!store)
return;
}
void setup_tree_view(GtkTreeView *tree_view)
{
GtkTreeStore *tree_store;
GtkCellRenderer *string_renderer;
GtkCellRenderer *hex_renderer;
GtkTreeViewColumn *column;
g_return_if_fail(GTK_IS_TREE_VIEW(tree_view));
tree_store = gtk_tree_store_new(MEM_VIEW_COLUMN_COUNT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING, GDK_TYPE_RGBA);
gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(tree_store));
string_renderer = gtk_cell_renderer_text_new();
hex_renderer = err_mem_view_hex_cell_renderer_new();
column = gtk_tree_view_column_new_with_attributes("Address", hex_renderer, "hex-num", MEM_VIEW_COL_ADDRESS, "foreground-rgba", MEM_VIEW_COLOR, NULL);
gtk_tree_view_append_column(tree_view, column);
column = gtk_tree_view_column_new_with_attributes("Data", hex_renderer, "hex-num", MEM_VIEW_COL_DATA, "foreground-rgba", MEM_VIEW_COLOR, NULL);
gtk_tree_view_append_column(tree_view, column);
column = gtk_tree_view_column_new_with_attributes("Interpretation", string_renderer, "text", MEM_VIEW_COL_INTERPRETATION, "foreground-rgba", MEM_VIEW_COLOR, NULL);
gtk_tree_view_append_column(tree_view, column);
}
static ptrdiff_t get_file_size(const char *filename)
{
struct stat file_stat;
int res;
ptrdiff_t size;
res = stat(filename, &file_stat);
if (res)
size = -1UL;
else
size = (ptrdiff_t)file_stat.st_size;
return size;
}
/**
* @brief Loads a file to memory and decodes it using base64
* @param name Filename
* @param detected_size detected Size of the ouput generated
* @return Buffer of decoded data with size \p detected_size, NULL in case of an error.
* @note Return buffer is allocated on heap. Use free() to free the memory.
*/
static char *load_file_to_memory(const char *name, size_t *detected_size)
{
ptrdiff_t size;
FILE *f;
char *ret = NULL;
size_t read_bytes;
gsize decoded_size;
size = get_file_size(name);
if (size <= 0)
goto exit;
f = fopen(name, "rb");
ret = (char *)malloc(size + 1);
if (!ret)
goto exit_close_file;
read_bytes = fread(ret, 1UL, (size_t)size, f);
if (read_bytes != (size_t)size) {
free(ret);
ret = NULL;
goto exit_close_file;
}
ret[size] = '\0';
g_base64_decode_inplace(ret, &decoded_size);
if (decoded_size == 0) {
free(ret);
ret = NULL;
goto exit_close_file;
}
if (detected_size)
*detected_size = (size_t)decoded_size;
exit_close_file:
fclose(f);
exit:
return ret;
}
G_MODULE_EXPORT
void info_bar_close_cb(GtkInfoBar *info_bar, gpointer user_data)
{
(void)user_data;
gtk_info_bar_set_revealed(info_bar, FALSE);
}
G_MODULE_EXPORT
void open_button_clicked_cb(GtkButton *button, gpointer *user_data)
{
struct application_data *data = (struct application_data *)user_data;
(void)button;
GtkDialog *dialog;
gint res;
gchar *filename;
dialog = GTK_DIALOG(gtk_file_chooser_dialog_new("Open File", GTK_WINDOW(data->borrowed_main_window),
GTK_FILE_CHOOSER_ACTION_OPEN,
"Cancel", GTK_RESPONSE_CANCEL,
"Open", GTK_RESPONSE_ACCEPT,
NULL));
res = gtk_dialog_run(dialog);
if (res == GTK_RESPONSE_ACCEPT) {
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
if (data->error_memory_data)
free((void *)data->error_memory_data);
data->error_memory_data = load_file_to_memory(filename, &data->file_size);
if (!data->error_memory_data) {
g_warning("File could not be loaded");
g_free(filename);
goto ret_destroy_dialog;
}
gtk_header_bar_set_subtitle(data->borrowed_header_bar, filename);
g_free(filename);
} else {
goto ret_destroy_dialog;
}
if (data->file_size % 4 || data->file_size == 0) {
free((void *)data->error_memory_data);
data->error_memory_data = NULL;
info_bar_show_message(data->borrowed_info_bar, GTK_MESSAGE_WARNING,
"Data must be base64 encoded and must contain full 32 bit words of data.");
goto ret_destroy_dialog;
}
show_error_memory(data->borrowed_tree_view, (const unsigned char *)data->error_memory_data, data->file_size);
ret_destroy_dialog:
gtk_widget_destroy(GTK_WIDGET(dialog));
}
static void app_activated(GApplication *app, gpointer user_data)
{
struct application_data *data = (struct application_data *)user_data;
GtkBuilder *builder;
GtkWindow *main_window;
builder = gtk_builder_new_from_resource("/gui/main");
main_window = GTK_WINDOW(gtk_builder_get_object(builder, "main-window"));
data->borrowed_main_window = GTK_WIDGET(main_window);
data->error_memory_data = NULL;
data->borrowed_tree_view = GTK_TREE_VIEW(gtk_builder_get_object(builder, "error-mem-tree-view"));
data->borrowed_header_bar = GTK_HEADER_BAR(gtk_builder_get_object(builder, "header-bar"));
data->borrowed_info_bar = GTK_INFO_BAR(gtk_builder_get_object(builder, "info-bar"));
setup_tree_view(data->borrowed_tree_view);
gtk_builder_connect_signals(builder, data);
g_object_unref(builder);
gtk_application_add_window(GTK_APPLICATION(app), main_window);
gtk_widget_show(GTK_WIDGET(main_window));
}
static int start_gui(int argc, char **argv)
{
int ret = 0;
GtkApplication *g_app;
static struct application_data data;
/* Create a new G application which will start a completely new process for each call to the program (NON_UNIQUE) instead
* of creating an additional window in the same process
*/
g_app = gtk_application_new("de.shimatta.reflow.error-mem-viewer", G_APPLICATION_NON_UNIQUE);
g_signal_connect(g_app, "activate", G_CALLBACK(app_activated), &data);
ret = g_application_run(G_APPLICATION(g_app), argc, argv);
g_object_unref(g_app);
if (data.error_memory_data)
free((void *)data.error_memory_data);
return ret;
}
int main(int argc, char **argv)
{
return start_gui(argc, argv);
}

File diff suppressed because it is too large Load Diff

@ -384,6 +384,30 @@
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig, axes = plt.subplots(nrows=1, ncols=2, sharex='col', figsize=(28, 8))\n",
"v12_df = pd.read_csv(r'hw-v12-1000Ohm.csv') \n",
"plot_histogram(axes[0], v12_df['pt1000_res_raw_lf'], 21, 'HW v1.2 1k Ohm Sampling', '1k Resistance')\n",
"plot_histogram(axes[1], v12_df['adc_pt1000_raw_reading_hf'], 21, 'HW v1.2 1k Ohm Sampling', '1k Resistance HF RAW')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig, axes = plt.subplots(nrows=1, ncols=2, sharex='col', figsize=(28, 8))\n",
"v13_df = pd.read_csv(r'1000OhmSampling-v1.3.csv') \n",
"plot_histogram(axes[0], v13_df['pt1000_res_raw_lf'], 21, 'HW v1.3 1k Ohm Sampling', '1k Resistance')\n",
"plot_histogram(axes[1], v13_df['adc_pt1000_raw_reading_hf'], 21, 'HW v1.3 1k Ohm Sampling', '1k Resistance')"
]
},
{
"cell_type": "code",
"execution_count": null,
@ -398,6 +422,13 @@
"print(calc_temp(2000))\n",
"print(calc_temp(2000+adc_min_res))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@ -416,7 +447,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.2"
"version": "3.9.6"
}
},
"nbformat": 4,

@ -0,0 +1,475 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "7c270395",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from scipy import signal\n",
"import matplotlib.pyplot as plt\n",
"import pandas as pd\n",
"from scipy.fft import fft, fftfreq"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b09956cf",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "348b4663",
"metadata": {},
"source": [
"## Filter comparison"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eef8fc32",
"metadata": {},
"outputs": [],
"source": [
"alpha = 0.01\n",
"mavg_b = [alpha]\n",
"mavg_a = [1, -(1-alpha)]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "06cc8d91",
"metadata": {},
"outputs": [],
"source": [
"# Sinc filter\n",
"b_sinc = [\n",
" 0.013166773445594984,\n",
" 0.015510026576574206,\n",
" 0.017943762856303655,\n",
" 0.020436419999452039,\n",
" 0.022953654956480787,\n",
" 0.025459023223972144,\n",
" 0.027914730737546672,\n",
" 0.030282439536854874,\n",
" 0.032524106530629059,\n",
" 0.034602833419516990,\n",
" 0.036483705201686277,\n",
" 0.038134594717421900,\n",
" 0.039526911389630152,\n",
" 0.040636273671486346,\n",
" 0.041443086683647982,\n",
" 0.041933009054862178,\n",
" 0.042097295996679322,\n",
" 0.041933009054862178,\n",
" 0.041443086683647982,\n",
" 0.040636273671486346,\n",
" 0.039526911389630152,\n",
" 0.038134594717421900,\n",
" 0.036483705201686277,\n",
" 0.034602833419516990,\n",
" 0.032524106530629059,\n",
" 0.030282439536854874,\n",
" 0.027914730737546672,\n",
" 0.025459023223972144,\n",
" 0.022953654956480787,\n",
" 0.020436419999452039,\n",
" 0.017943762856303655,\n",
" 0.015510026576574206,\n",
" 0.013166773445594984,\n",
"]\n",
"b_sinc = [\n",
" -0.000005301919181359,\n",
" -0.000020372384569462,\n",
" -0.000043393375246200,\n",
" -0.000071643508460196,\n",
" -0.000101272447699964,\n",
" -0.000127045709202358,\n",
" -0.000142084479366378,\n",
" -0.000137630058679112,\n",
" -0.000102865422361326,\n",
" -0.000024826753571648,\n",
" 0.000111564545505229,\n",
" 0.000323323938002668,\n",
" 0.000629062120588115,\n",
" 0.001048471626315150,\n",
" 0.001601644955843253,\n",
" 0.002308239744151386,\n",
" 0.003186518744650963,\n",
" 0.004252303894058680,\n",
" 0.005517893567100900,\n",
" 0.006990999568786174,\n",
" 0.008673764799041549,\n",
" 0.010561923390649710,\n",
" 0.012644162210467481,\n",
" 0.014901735907231652,\n",
" 0.017308377414832196,\n",
" 0.019830532444994709,\n",
" 0.022427930710902887,\n",
" 0.025054489273884574,\n",
" 0.027659525485854094,\n",
" 0.030189239563895277,\n",
" 0.032588410933658420,\n",
" 0.034802239101869442,\n",
" 0.036778249821351520,\n",
" 0.038468181363671021,\n",
" 0.039829764251821352,\n",
" 0.040828311002284692,\n",
" 0.041438040179150003,\n",
" 0.041643070995549647,\n",
" 0.041438040179150003,\n",
" 0.040828311002284692,\n",
" 0.039829764251821366,\n",
" 0.038468181363671021,\n",
" 0.036778249821351520,\n",
" 0.034802239101869456,\n",
" 0.032588410933658420,\n",
" 0.030189239563895291,\n",
" 0.027659525485854094,\n",
" 0.025054489273884584,\n",
" 0.022427930710902898,\n",
" 0.019830532444994709,\n",
" 0.017308377414832207,\n",
" 0.014901735907231647,\n",
" 0.012644162210467488,\n",
" 0.010561923390649715,\n",
" 0.008673764799041547,\n",
" 0.006990999568786178,\n",
" 0.005517893567100902,\n",
" 0.004252303894058680,\n",
" 0.003186518744650965,\n",
" 0.002308239744151388,\n",
" 0.001601644955843254,\n",
" 0.001048471626315152,\n",
" 0.000629062120588114,\n",
" 0.000323323938002668,\n",
" 0.000111564545505229,\n",
" -0.000024826753571648,\n",
" -0.000102865422361327,\n",
" -0.000137630058679112,\n",
" -0.000142084479366378,\n",
" -0.000127045709202359,\n",
" -0.000101272447699963,\n",
" -0.000071643508460196,\n",
" -0.000043393375246200,\n",
" -0.000020372384569461,\n",
" -0.000005301919181359,\n",
"]\n",
"b_sinc = np.around([k * 56536 for k in b_sinc])/65536\n",
"\n",
"\n",
"def combined_sinc_mavg(alpha = 0.4):\n",
" b1 = [alpha]\n",
" b2 = b_sinc\n",
" a1 = [1, -(1-alpha)]\n",
" a2 = [1]\n",
" \n",
" b = np.convolve(b1, b2)\n",
" a = np.convolve(a1, a2)\n",
" return b,a\n",
"\n",
"def iir_notch(freq, r, fsa):\n",
" b = [1, -2*np.cos(freq/fsa*2*np.pi), 1]\n",
" a = [1, -2*r*np.cos(freq/fsa*2*np.pi), r*r]\n",
" return b,a"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "299fc59e",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "0af3fa7b",
"metadata": {},
"outputs": [],
"source": [
"def plot_transfer_func(b, a, fsa = 1):\n",
" omega, vals = signal.freqz(b, a, worN = 1024)\n",
" plt.plot(omega/(2*np.pi)*fsa, abs(vals))\n",
" \n",
"sample_rate = 1e3/6\n",
"plt.figure(figsize=(16,8))\n",
"plt.yscale('log')\n",
"plot_transfer_func(mavg_b, mavg_a, sample_rate)\n",
"plt.ylabel('|H(w)| [dB]')\n",
"plt.xlabel('Frequency [Hz]')\n",
"\n",
"plot_transfer_func(b_sinc, [1], sample_rate)\n",
"\n",
"# Combined filter\n",
"b,a = combined_sinc_mavg(alpha = 1)\n",
"b_notch, a_notch = iir_notch(50, 0.875, sample_rate)\n",
"b = np.convolve(b, b_notch)\n",
"a = np.convolve(a, a_notch)\n",
"plot_transfer_func(b,a, sample_rate)\n",
"plt.grid()\n",
"\n",
"plt.legend(['MAVG a = 0.01', 'SINC', 'SINC+MAVG'])\n",
"plt.xlim(0, 70)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "c9b87b82",
"metadata": {},
"source": [
"# Notch filters (Not used for implementation)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c360b127",
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(16,8))\n",
"plt.yscale('log')\n",
"a = [1]\n",
"b = [1, -2*np.cos(50/sample_rate*2*np.pi), 1]\n",
"plot_transfer_func(b,a, sample_rate)\n",
"\n",
"b = [1, -2*np.cos(60/sample_rate*2*np.pi), 1]\n",
"plot_transfer_func(b,a, sample_rate)\n",
"\n",
"r = 0.875\n",
"b,a = iir_notch(50, r, sample_rate)\n",
"plot_transfer_func(b,a, sample_rate)\n",
"\n",
"b,a = iir_notch(60, r, sample_rate)\n",
"plot_transfer_func(b,a, sample_rate)\n",
"plt.xlim(40,70)\n",
"plt.legend(['FIR 50 Hz Notch', 'FIR 60 Hz', 'IIR 50Hz', 'IIR 60Hz'])\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "891bf909",
"metadata": {},
"source": [
"# Singal testing"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "29277520",
"metadata": {},
"outputs": [],
"source": [
"N = 30000\n",
"time = np.linspace(0, 1/sample_rate*N, N, endpoint=False)\n",
"sig = 10*signal.sawtooth(2*np.pi*0.2*time)+10 #+ 0.5 * np.sin(2*np.pi*50*time)+0.8 * np.sin(2*np.pi*80*time)\n",
"\n",
"plt.figure(figsize=(16,8))\n",
"\n",
"spur_len = 3\n",
"\n",
"sig[1000:1000+spur_len] = sig[1000]+5\n",
"sig[2000:2000+spur_len] = sig[2000]-6\n",
"sig[3000:3000+spur_len] = sig[3000]+2\n",
"sig[4000:4000+spur_len] = sig[4000]+8\n",
"\n",
"\n",
"plt.plot(time, sig)\n",
"\n",
"\n",
"# Apply the combined filter:\n",
"b,a = combined_sinc_mavg(alpha = 1)\n",
"\n",
"bn,an = iir_notch(50, 0.875, sample_rate)\n",
"a = np.convolve(a, an)\n",
"b = np.convolve(b, bn)\n",
"\n",
"#b,a = mavg_b, mavg_a\n",
"\n",
"w,h = signal.freqz(b,a)\n",
"gain_corr = round(1/abs(h[0])*65536)/65536\n",
"\n",
"sig_f = signal.lfilter(b, a, sig) * gain_corr\n",
"\n",
"\n",
"print('Gain correction:', gain_corr)\n",
"\n",
"plt.plot(time, sig_f)\n",
"plt.xlim(5,10)\n",
"plt.show()\n",
"\n",
"plt.figure(figsize=(16,8))\n",
"plt.plot(time, abs(sig-sig_f))\n",
"plt.xlim(5,10)\n",
"plt.ylim(0,2)\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "13758640",
"metadata": {},
"outputs": [],
"source": [
"\n",
"window = signal.windows.hamming(N)\n",
"\n",
"h_sig = fft(sig*window)\n",
"f_sig = fftfreq(N, 1/sample_rate)[:N//2]\n",
"\n",
"h_sig_f = fft(sig_f*window)\n",
"f_sig_f = fftfreq(N, 1/sample_rate)[:N//2]\n",
"\n",
"plt.figure(figsize=(16,10))\n",
"plt.yscale('log')\n",
"plt.plot(f_sig, 2.0/N*abs(h_sig[0:N//2]))\n",
"plt.plot(f_sig_f, 2.0/N*abs(h_sig_f[0:N//2]))\n",
"plt.show();"
]
},
{
"cell_type": "markdown",
"id": "f4b81600",
"metadata": {},
"source": [
"# PT1000 HF Filtering"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a87370ee",
"metadata": {},
"outputs": [],
"source": [
"raw_data = pd.read_csv(r'pt1000_hf_2kOhm_v1.3.dat')\n",
"raw_data = pd.read_csv(r'pt1000_hf_changing.dat')\n",
"time = np.linspace(0, 2000*6e-3, 2000, endpoint=False)\n",
"\n",
"plt.figure(figsize=(22,12))\n",
"plt.plot(time, raw_data['hf_value']*2500/4096)\n",
"\n",
"alpha = 0.005\n",
"\n",
"mavg_b = [alpha]\n",
"mavg_a = [1, -(1-alpha)]\n",
"\n",
"zi = signal.lfilter_zi(mavg_b, mavg_a)\n",
"filtered, _ = signal.lfilter(mavg_b, mavg_a, raw_data['hf_value'], zi=zi*raw_data['hf_value'][0])\n",
"plt.plot(time, filtered*2500/4096)\n",
"filtered_avg_low = filtered\n",
"\n",
"alpha = 0.01\n",
"mavg_b = [alpha]\n",
"mavg_a = [1, -(1-alpha)]\n",
"\n",
"zi = signal.lfilter_zi(mavg_b, mavg_a)\n",
"filtered, _ = signal.lfilter(mavg_b, mavg_a, raw_data['hf_value'], zi=zi*raw_data['hf_value'][0])\n",
"plt.plot(time, filtered*2500/4096)\n",
"filtered_avg = filtered\n",
"\n",
"\n",
"\n",
"# Apply the combined filter:\n",
"b,a = combined_sinc_mavg(alpha = 0.08)\n",
"\n",
"bn,an = iir_notch(4, 0.75, sample_rate)\n",
"a = np.convolve(a, an)\n",
"b = np.convolve(b, bn)\n",
"\n",
"zi = signal.lfilter_zi(b, a)\n",
"filtered, _ = signal.lfilter(b, a, raw_data['hf_value'], zi=zi*raw_data['hf_value'][0])\n",
"\n",
"w,h = signal.freqz(b,a)\n",
"gain_corr = round(1/abs(h[0])*65536)/65536\n",
"\n",
"plt.plot(time, filtered*gain_corr*2500/4096)\n",
"plt.savefig('expl.pdf', format='pdf', dpi=1200)\n",
"plt.show()\n"
]
},
{
"cell_type": "markdown",
"id": "3eae0e71",
"metadata": {},
"source": [
"## Spectrum"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8d082b99",
"metadata": {},
"outputs": [],
"source": [
"window =signal.windows.hamming(len(raw_data['hf_value']))\n",
"raw_fft = fft(np.array(raw_data['hf_value'].to_list())*window)\n",
"f_raw = fftfreq(len(raw_data), 1/sample_rate)[:len(raw_data)//2]\n",
"plt.figure(figsize=(16,10));\n",
"plt.yscale('log')\n",
"plt.plot(f_raw, abs(raw_fft[:len(raw_data)//2]))\n",
"\n",
"avg_fft = fft(np.array(filtered_avg)*window)\n",
"plt.plot(f_raw, abs(avg_fft[:len(raw_data)//2]))\n",
"\n",
"avg_fft = fft(np.array(filtered_avg_low)*window)\n",
"plt.plot(f_raw, abs(avg_fft[:len(raw_data)//2]))\n",
"\n",
"sinc_fft = fft(np.array(filtered)*window)\n",
"plt.plot(f_raw, abs(sinc_fft[:len(raw_data)//2]))\n",
"plt.xscale('log')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e09d63f9",
"metadata": {},
"outputs": [],
"source": [
"print(np.std(filtered_avg_low/4096*2500))\n",
"print(np.std(filtered_avg/4096*2500))\n",
"print(np.std(filtered/4096*2500))\n",
"\n",
"print('Min',min(filtered_avg/4096*2500), 'Max', max(filtered_avg)/4096*2500)\n",
"print('Min',min(filtered)/4096*2500*gain_corr, 'Max', max(filtered)/4096*2500*gain_corr)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1 +0,0 @@
Subproject commit c369231e42ecd67bf4d1a72a54b165dcee3b6bdb

@ -14,3 +14,12 @@ reflow-controller.includes
*.includes
*.config
*.files
*.user.*
*.user
# VSCODE and CLANGD sepcific excludes
.vscode/
build/
.cache/
compile_commands.json

145
stm-firmware/CMakeLists.txt Normal file

@ -0,0 +1,145 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_CROSSCOMPILING 1)
cmake_minimum_required(VERSION 3.18)
set(CMAKE_TOOLCHAIN_FILE "arm-none-eabi-gcc.cmake")
project(reflow-controller)
if(NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(ColorBold "${Esc}[1m")
set(Red "${Esc}[31m")
set(Green "${Esc}[32m")
set(Yellow "${Esc}[33m")
set(Blue "${Esc}[34m")
set(Magenta "${Esc}[35m")
set(Cyan "${Esc}[36m")
set(White "${Esc}[37m")
set(BoldRed "${Esc}[1;31m")
set(BoldGreen "${Esc}[1;32m")
set(BoldYellow "${Esc}[1;33m")
set(BoldBlue "${Esc}[1;34m")
set(BoldMagenta "${Esc}[1;35m")
set(BoldCyan "${Esc}[1;36m")
set(BoldWhite "${Esc}[1;37m")
endif()
find_package(Git)
if (GIT_FOUND)
message("Git found")
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --always --tags --dirty
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message("${BoldGreen}Git based version number: ${GIT_DESCRIBE}${ColorReset}")
else (GIT_FOUND)
message("${BoldRed}No git installation found. It is highly recommended using git to generate the version number")
message(FATAL_ERROR "Git is required")
endif (GIT_FOUND)
find_program(PATCHELFCRC patchelfcrc)
if (PATCHELFCRC)
message("patchelfcrc found: ${PATCHELFCRC}")
else(PATCHELFCRC)
message(FATAL_ERROR "${BoldRed}Patchelfcrc not found. Cannot patch CRC checksum into ELF file: patchelfcrc: command not found! See: https://git.shimatta.de/mhu/patchelfcrc${ColorReset}")
endif (PATCHELFCRC)
set(ELFFILE ${PROJECT_NAME}.elf)
set(HEXFILE ${PROJECT_NAME}.hex)
set(MAPFILE ${PROJECT_NAME}.map)
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/stm32f407vet6_flash.ld)
add_compile_options(-Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter)
add_compile_options(-mlittle-endian -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles -Wimplicit-fallthrough=3 -Wsign-compare)
add_definitions(-DBASE64_LOOKUP_TABLE_SECTION=\".ccm.bss\" -DSHELLMATTA_HELP_ALIAS=\"?\" -DHSE_VALUE=8000000UL -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4)
add_subdirectory(doxygen)
add_subdirectory(updater/ram-code)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUGBUILD)
add_compile_options(-O0 -g)
add_link_options(-Wl,-Map=${MAPFILE})
ELSE()
add_compile_options(-O3 -g)
add_link_options(-Wl,--gc-sections)
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
if (UART_ON_DEBUG_HEADER)
add_definitions(-DUART_ON_DEBUG_HEADER)
message("${BoldRed}UART forced to debug header${ColorReset}")
endif (UART_ON_DEBUG_HEADER)
add_subdirectory(base64-lib)
add_subdirectory(linklist-lib)
aux_source_directory("." MAIN_SOURCES)
aux_source_directory("config-parser" CFG_PARSER_SRCS)
aux_source_directory("ui" UI_SRCS)
aux_source_directory("fatfs" FAT_SRCS)
aux_source_directory("fatfs/shimatta_sdio_driver" SDIO_SRCS)
aux_source_directory("boot" BOOT_SRCS)
aux_source_directory("setup" SETUP_SRCS)
aux_source_directory("stm-periph" STM_PERIPH_SRCS)
aux_source_directory("settings" SETTINGS_SRCS)
aux_source_directory("safety" SAFETY_SRCS)
aux_source_directory("shellmatta/src" SHELLMATTA_SRCS)
aux_source_directory("updater" UPDATER_SRCS)
aux_source_directory("temp-profile" PROFILE_SRCS)
set(GEN_VERSION_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/include/generated-version")
add_custom_target(
generate-version-header
COMMAND mkdir -p ${GEN_VERSION_HEADER_PATH} && bash "${CMAKE_CURRENT_SOURCE_DIR}/create_version_header.sh" "${GEN_VERSION_HEADER_PATH}/version.h"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating version number using git"
)
add_executable(${ELFFILE} ${MAIN_SOURCES} ${CFG_PARSER_SRCS} ${UI_SRCS}
${FAT_SRCS} ${SDIO_SRCS} ${BOOT_SRCS} ${SETUP_SRCS}
${STM_PERIPH_SRCS} ${SETTINGS_SRCS} ${SAFETY_SRCS}
${SHELLMATTA_SRCS} ${UPDATER_SRCS} ${PROFILE_SRCS}
)
add_dependencies(${ELFFILE} updater-ram-code-header-blob generate-version-header)
target_include_directories(${ELFFILE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/shellmatta/api ${CMAKE_CURRENT_SOURCE_DIR}/config-parser/include)
target_link_options(${ELFFILE} PRIVATE -mlittle-endian -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles -T${LINKER_SCRIPT} -Wl,--print-memory-usage)
target_link_libraries(${ELFFILE} base64-lib linklist-lib)
target_include_directories(${ELFFILE} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/updater/ram-code/include/" "${CMAKE_CURRENT_BINARY_DIR}/include/")
add_custom_command(
TARGET ${ELFFILE}
POST_BUILD
COMMAND ${PATCHELFCRC} --little-endian --verbose --granularity word --start-magic 0xa8be53f9 --end-magic 0xffa582ff -O .flashcrc -p crc-32-mpeg -S .text -S .data -S .ccmdata -S .vectors "${CMAKE_CURRENT_BINARY_DIR}/${ELFFILE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Running Flash CRC Patcher"
)
set(HEX_PATH "${CMAKE_CURRENT_BINARY_DIR}/${HEXFILE}")
add_custom_target(update-image ALL DEPENDS ${HEX_PATH} "${HEX_PATH}.sha")
add_custom_command(
DEPENDS ${ELFFILE}
OUTPUT ${HEX_PATH}
COMMAND ${CMAKE_OBJCOPY} -O ihex ${ELFFILE} ${HEX_PATH}
)
add_custom_command(
DEPENDS ${HEX_PATH}
OUTPUT "${HEX_PATH}.sha"
COMMAND sha256sum "${HEX_PATH}" | cut -d " " -f 1 > "${HEX_PATH}.sha"
)

@ -1,199 +0,0 @@
################################Shimatta Makefile####################################
#CPU: STM32F407VET6
#Compiler: arm-none-eabi
#####################################################################################
#Add Files and Folders below#########################################################
CFILES = main.c syscalls.c setup/system_stm32f4xx.c systick.c
ASFILES = boot/startup_stm32f4xx.S
INCLUDEPATH = -Iinclude
OBJDIR_BASE = obj
TARGET_BASE = reflow-controller
LIBRARYPATH = -L. -Lmathlib
LIBRARIES = -larm_cortexM4lf_math -lm
DEFINES = -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4 -DHSE_VALUE=8000000UL
MAPFILE_BASE = memory-mapping
export GIT_VER = $(shell git describe --always --dirty --tags)
DEFINES += -DGIT_VER=$(GIT_VER)
ifneq ($(VERBOSE),true)
QUIET=@
else
QUIET=
endif
##Custom Files###
CFILES += adc-meas.c
# Shellmatta
CFILES += shellmatta/src/shellmatta.c shellmatta/src/shellmatta_autocomplete.c shellmatta/src/shellmatta_escape.c shellmatta/src/shellmatta_history.c shellmatta/src/shellmatta_utils.c shellmatta/src/shellmatta_opt.c shell.c
INCLUDEPATH += -Ishellmatta/api
DEFINES += -DSHELLMATTA_HELP_ALIAS=\"?\"
# RCC Manager
CFILES += stm-periph/clock-enable-manager.c
CFILES += stm-periph/uart.c stm-periph/dma-ring-buffer.c
CFILES += digio.c
CFILES += stm-periph/unique-id.c
CFILES += calibration.c
CFILES += temp-converter.c
CFILES += rotary-encoder.c button.c
CFILES += stack-check.c
CFILES += ui/lcd.c ui/menu.c reflow-menu.c
#CFILES += onewire-temp-sensors.c
CFILES += fatfs/diskio.c fatfs/ff.c fatfs/ffsystem.c fatfs/ffunicode.c fatfs/shimatta_sdio_driver/shimatta_sdio.c
CFILES += pid-controller.c oven-driver.c
CFILES += settings/settings.c settings/settings-sd-card.c
CFILES += safety-adc.c
DEBUG_DEFINES = -DDEBUGBUILD
RELEASE_DEFINES =
###################################################################################
ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE=arm-none-eabi-
endif
CC=$(CROSS_COMPILE)gcc
OBJCOPY=$(CROSS_COMPILE)objcopy
OBJDUMP=$(CROSS_COMPILE)objdump
SIZE=$(CROSS_COMPILE)size
CFLAGS_RELEASE = -O3 -g
CFLAGS_DEBUG = -O0 -g
LFLAGS_RELEASE = -Wl,--gc-sections
LFLAGS_DEBUG =
CFLAGS =
LFLAGS =
ifneq ($(DEBUGBUILD),true)
DEFINES += $(RELEASE_DEFINES)
CFLAGS += $(CFLAGS_RELEASE)
LFLAGS += $(LFLAGS_RELEASE)
target = $(TARGET_BASE)-release
OBJDIR = $(OBJDIR_BASE)/release
MAPFILE = $(MAPFILE_BASE)-release
else
DEFINES += $(DEBUG_DEFINES)
target = $(TARGET_BASE)-debug
CFLAGS += $(CFLAGS_DEBUG)
LFLAGS += $(LFLAGS_DEBUG)
OBJDIR = $(OBJDIR_BASE)/debug
MAPFILE = $(MAPFILE_BASE)-debug
endif
LFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
LFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 --disable-newlib-supplied-syscalls -nostartfiles
LFLAGS += -Tstm32f407vet6_flash.ld -Wl,-Map=$(MAPFILE).map
CFLAGS += -c -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -nostartfiles
CFLAGS += -Wall -Wextra -Wold-style-declaration -Wuninitialized -Wmaybe-uninitialized -Wunused-parameter -Wimplicit-fallthrough=3 -Wsign-compare
####################################################################################
OBJ = $(CFILES:%.c=$(OBJDIR)/%.c.o)
ASOBJ += $(ASFILES:%.S=$(OBJDIR)/%.S.o)
default: $(target).elf
all: debug release
release:
$(QUIET)$(MAKE) DEBUGBUILD=false
debug:
$(QUIET)$(MAKE) DEBUGBUILD=true
%.bin: %.elf
$(QUIET)$(OBJCOPY) -O binary $^ $@
%.hex: %.elf
$(QUIET)$(OBJCOPY) -O ihex $^ $@
#Linking
$(target).elf: $(OBJ) $(ASOBJ)
@echo [LD] $@
$(QUIET)$(CC) $(LFLAGS) $(LIBRARYPATH) -o $@ $^ $(LIBRARIES)
$(QUIET)$(SIZE) $@
@echo "Built Version $(GIT_VER)"
#Compiling
$(OBJ):
@echo [CC] $@
$(eval OUTPATH=$(dir $@))
@mkdir -p $(OUTPATH)
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.c.o=%.c)
$(ASOBJ):
@echo [AS] $@
$(eval OUTPATH=$(dir $@))
@mkdir -p $(OUTPATH)
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.S.o=%.S)
.PHONY: qtproject-legacy qtproject qtproject-debug clean mrproper objcopy disassemble program program-debug
program-debug:
$(QUIET)$(MAKE) DEBUGBUILD=true program
program: $(target).elf
./program-device.sh $<
disassemble: $(target).elf
$(QUIET)$(OBJDUMP) -D -s $< > $(target).lss
objcopy: $(target).bin $(target).hex
mrproper: clean
@echo "Purging project files..."
$(QUIET)rm -f $(target).pro $(target).creator $(target).files $(target).cflags $(target).cxxflags $(target).includes $(target).config
clean:
@echo -n "Cleaning up derived files for "
ifneq ($(DEBUGBUILD),true)
@echo "RELEASE build"
else
@echo "DEBUG build"
endif
$(QUIET)rm -f $(target).elf $(target).bin $(target).hex $(OBJ) $(ASOBJ) $(mapfile).map $(CFILES:%.c=$(OBJDIR)/%.c.d) $(ASFILES:%.S=$(OBJDIR)/%.S.d)
$(QUIET)rm -rf $(OBJDIR)/*
ifneq ($(DEBUGBUILD),true)
$(QUIET)$(MAKE) DEBUGBUILD=true clean
endif
qtproject-legacy:
echo -e "TEMPLATE = app\nCONFIG -= console app_bundle qt" > $(target).pro
echo -e "SOURCES += $(CFILES) $(ASFILES)" >> $(target).pro
echo -ne "INCLUDEPATH += " >> $(target).pro
echo "$(INCLUDEPATH)" | sed "s!-I!./!g" >> $(target).pro
echo -ne "HEADERS += " >> $(target).pro
find -name "*.h" | tr "\\n" " " >> $(target).pro
echo -ne "\nDEFINES += " >> $(target).pro
echo "$(DEFINES)" | sed "s/-D//g" >> $(target).pro
qtproject-debug:
@echo "Generating debug build project"
$(QUIET)$(MAKE) DEBUGBUILD=true qtproject
qtproject:
$(QUIET)rm -f $(target).files $(target).cflags $(target).config $(target).creator $(target).includes $(target).creator.user
@echo "Generating source file list"
$(QUIET)echo "$(CFILES)" | tr ' ' '\n' > $(target).files
@echo -n "Appending found header files from folders "
@echo `echo $(INCLUDEPATH) | sed "s/-I//g"`
$(QUIET)for dir in `echo $(INCLUDEPATH) | sed "s/-I//g"`; do \
find `echo "$${dir}"` -name "*.h" >> $(target).files; \
done
@echo "Generating $(target).cflags"
$(QUIET)echo "" > $(target).cflags
@echo "Generating $(target).includes"
$(QUIET)echo $(INCLUDEPATH) | sed "s/-I/,/g" | tr , '\n' | sed "/^$$/d" > $(target).includes;
@echo "Generating $(target).config"
$(QUIET)echo $(DEFINES) | sed "s/-D/,#define /g" | tr , '\n' | sed "/^$$/d" > $(target).config
@echo "Generating $(target).creator"
$(QUIET)echo "[GENERAL]" > $(target).creator
-include $(CFILES:%.c=$(OBJDIR)/%.c.d) $(ASFILES:%.S=$(OBJDIR)/%.S.d)

@ -1,4 +1,4 @@
/* Reflow Oven Controller
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
@ -18,44 +18,53 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file adc-meas.c
* @brief Implementation of the PT1000 measurement ADC and filtering functions
*/
#include <reflow-controller/adc-meas.h>
#include <stm32/stm32f4xx.h>
#include <cmsis/core_cm4.h>
#include <stm-periph/stm32-gpio-macros.h>
#include <stdlib.h>
#include <stm-periph/clock-enable-manager.h>
#include <helper-macros/helper-macros.h>
#include <stm-periph/rcc-manager.h>
#include <reflow-controller/safety/safety-controller.h>
static float pt1000_offset;
static float pt1000_sens_dev;
static bool calibration_active;
static float filter_alpha;
static volatile float pt1000_res_raw_lf;
static volatile bool filter_ready;
static volatile enum adc_pt1000_error pt1000_error = ADC_PT1000_INACTIVE;
static volatile int * volatile streaming_flag_ptr = NULL;
static uint32_t filter_startup_cnt;
static volatile float adc_pt1000_raw_reading_hf;
static float IN_SECTION(.ccm.bss) pt1000_offset;
static float IN_SECTION(.ccm.bss) pt1000_sens_dev;
static bool IN_SECTION(.ccm.bss) calibration_active;
static float IN_SECTION(.ccm.bss) filter_alpha;
/**
* @brief Filtered PT1000 resistance value.
* @note This value is not yet calibrated.
* Use @ref adc_pt1000_get_current_resistance to get this value with calibration.
*/
static volatile float IN_SECTION(.ccm.bss) pt1000_res_raw_lf;
static volatile int * volatile streaming_flag_ptr;
static volatile float IN_SECTION(.ccm.bss) adc_pt1000_raw_reading_hf;
static volatile uint16_t dma_sample_buffer[ADC_PT1000_DMA_AVG_SAMPLES];
static volatile uint32_t adc_watchdog_counter = 0UL;
static volatile uint32_t IN_SECTION(.ccm.bss) adc_watchdog_counter;
volatile float * volatile stream_buffer = NULL;
volatile float * volatile stream_buffer;
volatile uint32_t stream_count;
volatile uint32_t stream_pos;
#define ADC_TO_RES(adc) ((float)(adc) / 4096.0f * 2500.0f)
static inline void adc_pt1000_stop_sample_frequency_timer()
static inline void adc_pt1000_stop_sample_frequency_timer(void)
{
TIM2->CR1 &= ~TIM_CR1_CEN;
rcc_manager_disable_clock(&RCC->APB1ENR, BITMASK_TO_BITNO(RCC_APB1ENR_TIM2EN));
}
static inline void adc_pt1000_setup_sample_frequency_timer()
static inline void adc_pt1000_setup_sample_frequency_timer(void)
{
rcc_manager_enable_clock(&RCC->APB1ENR, BITMASK_TO_BITNO(RCC_APB1ENR_TIM2EN));
/* Divide 42 MHz peripheral clock by 42 */
TIM2->PSC = (42UL-1UL);
/* Divide 2*42 MHz peripheral clock by 42 */
TIM2->PSC = (84UL-1UL);
/* Reload value */
TIM2->ARR = ADC_PT1000_SAMPLE_CNT_DELAY;
@ -68,13 +77,15 @@ static inline void adc_pt1000_setup_sample_frequency_timer()
}
static inline void adc_pt1000_disable_adc()
static inline void adc_pt1000_disable_adc(void)
{
ADC_PT1000_PERIPH->CR2 &= ~ADC_CR2_ADON;
DMA2_Stream0->CR = 0;
pt1000_error |= ADC_PT1000_INACTIVE;
safety_controller_set_crc_monitor(ERR_CRC_MON_MEAS_ADC, SAFETY_CRC_MON_MEAS_ADC_PW);
safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_OFF, MEAS_ADC_SAFETY_FLAG_KEY);
safety_controller_enable_timing_mon(ERR_TIMING_MEAS_ADC, false);
rcc_manager_disable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(RCC_APB2ENR_ADC3EN));
rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(ADC_PT1000_PORT_RCC_MASK));
}
@ -90,7 +101,7 @@ static inline void adc_pt1000_disable_adc()
* After that, the moving average filter is fed with the values.
*
*/
static inline void adc_pt1000_enable_dma_stream()
static inline void adc_pt1000_enable_dma_stream(void)
{
/* Enable peripheral clock for DMA2 */
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA2EN));
@ -115,7 +126,7 @@ static inline void adc_pt1000_enable_dma_stream()
DMA_SxCR_CIRC | DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_EN | ((ADC_PT1000_CHANNEL & 0x7)<<25);
}
static inline void adc_pt1000_disable_dma_stream()
static inline void adc_pt1000_disable_dma_stream(void)
{
/* Disable the stream */
DMA2_Stream0->CR = 0;
@ -127,7 +138,7 @@ static inline void adc_pt1000_disable_dma_stream()
NVIC_DisableIRQ(DMA2_Stream0_IRQn);
}
void adc_pt1000_setup_meas()
void adc_pt1000_setup_meas(void)
{
rcc_manager_enable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(RCC_APB2ENR_ADC3EN));
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(ADC_PT1000_PORT_RCC_MASK));
@ -154,7 +165,8 @@ void adc_pt1000_setup_meas()
ADC_PT1000_PERIPH->SQR3 = (ADC_PT1000_CHANNEL<<0);
ADC_PT1000_PERIPH->CR1 = ADC_CR1_OVRIE | ADC_CR1_AWDEN | ADC_CR1_AWDIE;
ADC_PT1000_PERIPH->CR2 = ADC_CR2_EXTEN_0 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_PT1000_PERIPH->CR2 = ADC_CR2_EXTEN_0 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 |
ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
adc_pt1000_set_moving_average_filter_param(ADC_PT1000_FILTER_WEIGHT);
adc_pt1000_set_resistance_calibration(0, 0, false);
@ -166,14 +178,19 @@ void adc_pt1000_setup_meas()
adc_pt1000_setup_sample_frequency_timer();
pt1000_error &= ~ADC_PT1000_INACTIVE;
safety_controller_ack_flag_with_key(ERR_FLAG_MEAS_ADC_OFF, MEAS_ADC_SAFETY_FLAG_KEY);
streaming_flag_ptr = NULL;
adc_watchdog_counter = 0UL;
stream_buffer = NULL;
safety_controller_set_crc_monitor(ERR_CRC_MON_MEAS_ADC, SAFETY_CRC_MON_MEAS_ADC_PW);
}
void adc_pt1000_set_moving_average_filter_param(float alpha)
{
filter_alpha = alpha;
filter_ready = false;
filter_startup_cnt = ADC_FILTER_STARTUP_CYCLES;
safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_UNSTABLE, MEAS_ADC_SAFETY_FLAG_KEY);
}
void adc_pt1000_set_resistance_calibration(float offset, float sensitivity_deviation, bool active)
@ -181,22 +198,27 @@ void adc_pt1000_set_resistance_calibration(float offset, float sensitivity_devia
pt1000_offset = offset;
pt1000_sens_dev = sensitivity_deviation;
calibration_active = active;
if (!calibration_active)
safety_controller_report_error_with_key(ERR_FLAG_UNCAL, MEAS_ADC_SAFETY_FLAG_KEY);
else
safety_controller_ack_flag_with_key(ERR_FLAG_UNCAL, MEAS_ADC_SAFETY_FLAG_KEY);
}
void adc_pt1000_get_resistance_calibration(float *offset, float *sensitivity_deviation, bool *active)
{
if (!offset || !sensitivity_deviation || !active)
return;
*offset = pt1000_offset;
*sensitivity_deviation = pt1000_sens_dev;
*active = calibration_active;
if (offset)
*offset = pt1000_offset;
if (sensitivity_deviation)
*sensitivity_deviation = pt1000_sens_dev;
if (active)
*active = calibration_active;
}
static inline float adc_pt1000_apply_calibration(float raw_resistance)
{
if (calibration_active)
return pt1000_res_raw_lf * (1.0f + pt1000_sens_dev) + pt1000_offset;
return (raw_resistance - pt1000_offset) * (1.0f + pt1000_sens_dev);
else
return raw_resistance;
@ -205,18 +227,23 @@ static inline float adc_pt1000_apply_calibration(float raw_resistance)
int adc_pt1000_get_current_resistance(float *resistance)
{
int ret_val = 0;
bool flag = true;
if (!resistance)
return -1001;
*resistance = adc_pt1000_apply_calibration(pt1000_res_raw_lf);
if (adc_pt1000_check_error()) {
if (safety_controller_get_flags_by_mask(ERR_FLAG_MEAS_ADC_OFF | ERR_FLAG_MEAS_ADC_OVERFLOW |
ERR_FLAG_MEAS_ADC_WATCHDOG | ERR_FLAG_TIMING_MEAS_ADC)) {
ret_val = -100;
goto return_value;
}
if (!filter_ready) {
(void)safety_controller_get_flag(ERR_FLAG_MEAS_ADC_UNSTABLE, &flag, false);
if (flag) {
ret_val = 2;
goto return_value;
}
@ -260,25 +287,15 @@ void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, fl
resistance_dest[i] = ADC_TO_RES(raw_source[i]);
}
enum adc_pt1000_error adc_pt1000_check_error()
{
return pt1000_error;
}
void adc_pt1000_clear_error()
{
pt1000_error &= ~ADC_PT1000_OVERFLOW & ~ADC_PT1000_WATCHDOG_ERROR;
}
void adc_pt1000_disable()
void adc_pt1000_disable(void)
{
adc_pt1000_disable_adc();
adc_pt1000_stop_sample_frequency_timer();
adc_pt1000_disable_dma_stream();
filter_ready = false;
pt1000_res_raw_lf = 0.0f;
pt1000_error |= ADC_PT1000_INACTIVE;
safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_OFF, MEAS_ADC_SAFETY_FLAG_KEY);
safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_UNSTABLE, MEAS_ADC_SAFETY_FLAG_KEY);
if (streaming_flag_ptr) {
*streaming_flag_ptr = -3;
@ -288,13 +305,39 @@ void adc_pt1000_disable()
static inline __attribute__((optimize("O3"))) void adc_pt1000_filter(float adc_prefiltered_value)
{
if (!filter_ready && --filter_startup_cnt <= 0)
filter_ready = true;
float alpha;
float res;
static uint8_t old_state = 0;
static uint32_t stable_sample_counter = 0;
pt1000_res_raw_lf = (1.0f-filter_alpha) * pt1000_res_raw_lf + filter_alpha * ADC_TO_RES(adc_prefiltered_value);
res = ADC_TO_RES(adc_prefiltered_value);
if (ABS(res - pt1000_res_raw_lf) >= ADC_PT1000_FILTER_UNSTABLE_DIFF) {
stable_sample_counter = 0;
alpha = ADC_PT1000_FILTER_WEIGHT_FAST;
if (old_state != 1) {
safety_controller_report_error_with_key(ERR_FLAG_MEAS_ADC_UNSTABLE,
MEAS_ADC_SAFETY_FLAG_KEY);
old_state = 1;
}
} else {
alpha = filter_alpha;
if (old_state != 2) {
stable_sample_counter++;
if (stable_sample_counter >= ADC_PT1000_FILTER_STABLE_SAMPLE_COUNT) {
safety_controller_ack_flag_with_key(ERR_FLAG_MEAS_ADC_UNSTABLE,
MEAS_ADC_SAFETY_FLAG_KEY);
old_state = 2;
}
}
}
pt1000_res_raw_lf = (1.0f - alpha) * pt1000_res_raw_lf +
alpha * res;
safety_controller_report_timing(ERR_TIMING_MEAS_ADC);
}
static inline __attribute__((optimize("O3"))) float adc_pt1000_dma_avg_pre_filter()
static inline __attribute__((optimize("O3"))) float adc_pt1000_dma_avg_pre_filter(void)
{
unsigned int i;
uint32_t sum = 0;
@ -328,7 +371,7 @@ void ADC_IRQHandler(void)
if (adc1_sr & ADC_SR_OVR) {
ADC_PT1000_PERIPH->SR &= ~ADC_SR_OVR;
pt1000_error |= ADC_PT1000_OVERFLOW;
safety_controller_report_error(ERR_FLAG_MEAS_ADC_OVERFLOW);
/* Disable ADC in case of overrrun*/
adc_pt1000_disable();
}
@ -337,7 +380,7 @@ void ADC_IRQHandler(void)
ADC_PT1000_PERIPH->SR &= ~ADC_SR_AWD;
adc_watchdog_counter++;
if (adc_watchdog_counter >= ADC_PT1000_WATCHDOG_SAMPLE_COUNT)
pt1000_error |= ADC_PT1000_WATCHDOG_ERROR;
safety_controller_report_error(ERR_FLAG_MEAS_ADC_WATCHDOG);
}
}
@ -356,16 +399,16 @@ static void append_stream_buffer(float val)
}
void DMA2_Stream0_IRQHandler()
void DMA2_Stream0_IRQHandler(void)
{
uint32_t lisr;
float adc_val;
lisr = DMA2->LISR;
lisr = DMA2->LISR & (0x3F);
DMA2->LIFCR = lisr;
if (lisr & DMA_LISR_TCIF0) {
/* Samples Transfered */
/* Samples transferred */
adc_val = adc_pt1000_dma_avg_pre_filter();
adc_pt1000_raw_reading_hf = adc_val;
@ -379,8 +422,7 @@ void DMA2_Stream0_IRQHandler()
adc_pt1000_filter(adc_val);
}
if (lisr & DMA_LISR_TEIF0) {
if (lisr & DMA_LISR_TEIF0)
adc_pt1000_disable();
}
}

@ -0,0 +1,28 @@
if(MINGW OR CYGWIN OR WIN32)
set(UTIL_SEARCH_CMD where)
elseif(UNIX OR APPLE)
set(UTIL_SEARCH_CMD which)
endif()
set(TOOLCHAIN_PREFIX arm-none-eabi-)
execute_process(
COMMAND ${UTIL_SEARCH_CMD} ${TOOLCHAIN_PREFIX}gcc
OUTPUT_VARIABLE BINUTILS_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
get_filename_component(ARM_TOOLCHAIN_DIR ${BINUTILS_PATH} DIRECTORY)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool")
set(CMAKE_SIZE_UTIL ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}size CACHE INTERNAL "size tool")
set(CMAKE_FIND_ROOT_PATH ${BINUTILS_PATH})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

@ -0,0 +1 @@
Subproject commit 251e90abf349d05bdb0d63afa86c478d8b0ebb98

@ -0,0 +1,126 @@
#include "startup-tests.h"
uint32_t startup_test_perform_ccm_ram_check(void)
{
const void *ccmram_base = (void *)0x10000000UL;
const uint32_t ccmram_size = 64U * 1024UL;
volatile uint32_t *word_ptr;
uint32_t target_val;
uint32_t idx;
uint32_t ret = 0UL;
/* Perform inversion test with 0x55 and 0xAA, Part 1 */
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
word_ptr[idx] = idx & 1 ? 0x55AA55AAUL : 0xAA55AA55UL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
target_val = idx & 1 ? 0x55AA55AAUL : 0xAA55AA55UL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
/* Perform inversion test with 0x55 and 0xAA, Part 2 */
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
word_ptr[idx] = idx & 1 ? 0xAA55AA55UL : 0x55AA55AAUL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
target_val = idx & 1 ? 0xAA55AA55UL : 0x55AA55AAUL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
/* Perform static test with 0xFF */
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
word_ptr[idx] = 0xFFFFFFFFUL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
target_val = 0xFFFFFFFFUL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
/* Perform static test with 0x00 */
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
word_ptr[idx] = 0x0UL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ccmram_base; idx < ccmram_size / 4U; idx++) {
target_val = 0x0UL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
exit_ret_address:
return ret;
}
uint32_t startup_test_perform_system_ram_check()
{
const void *ram_base = (void *)0x20000000UL;
const uint32_t ram_size = 128U * 1024UL;
volatile uint32_t *word_ptr;
uint32_t target_val;
uint32_t idx;
uint32_t ret = 0UL;
/* Perform inversion test with 0x55 and 0xAA, Part 1 */
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
word_ptr[idx] = idx & 1 ? 0x55AA55AAUL : 0xAA55AA55UL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
target_val = idx & 1 ? 0x55AA55AAUL : 0xAA55AA55UL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
/* Perform inversion test with 0x55 and 0xAA, Part 2 */
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
word_ptr[idx] = idx & 1 ? 0xAA55AA55UL : 0x55AA55AAUL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
target_val = idx & 1 ? 0xAA55AA55UL : 0x55AA55AAUL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
/* Perform static test with 0xFF */
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
word_ptr[idx] = 0xFFFFFFFFUL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
target_val = 0xFFFFFFFFUL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
/* Perform static test with 0x00 */
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
word_ptr[idx] = 0x0UL;
}
for (idx = 0, word_ptr = (volatile uint32_t *)ram_base; idx < ram_size / 4U; idx++) {
target_val = 0x0UL;
if (target_val != word_ptr[idx]) {
ret = (uint32_t)&word_ptr[idx];
goto exit_ret_address;
}
}
exit_ret_address:
return ret;
}

@ -0,0 +1,25 @@
#ifndef _STARTUP_TESTS_H_
#define _STARTUP_TESTS_H_
#include <stdint.h>
/**
* @brief Do a RAM check of the CCM RAM.
*
* Loop over the whole CCM memory area and check it.
*
* @return 0 if successful. Else the defect address is returned.
* @warning This will completely corrupt this memory!
* You have to ensure to set it to sane values afterwards!
*/
uint32_t startup_test_perform_ccm_ram_check(void);
/**
* @brief Do a RAM check of the stnadard SRAM regions
* @return 0 if successful. If an error is found, the faulty address is returned
* @warning This completely destroys all content in the memory!
* @warning Ensure that the stack pointer is moved to a different memory reagion (CCM RAM)!
*/
uint32_t startup_test_perform_system_ram_check(void);
#endif /* _STARTUP_TESTS_H_ */

@ -0,0 +1,401 @@
/*
* STM32F4 Startup Code for STM32F407 devices
* Copyright (C) 2017 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of 'STM32F4 code template'.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this template. If not, see <http://www.gnu.org/licenses/>.
* ------------------------------------------------------------------------
*/
#include <stdint.h>
#include "startup-tests.h"
/* C++ library init */
# if defined(__cplusplus)
extern "C" {
extern void __libc_init_array(void);
}
#endif
/* Defines for weak default handlers */
#define WEAK __attribute__((weak))
#define ALIAS(func) __attribute__ ((weak, alias (#func)))
/* Define for section mapping */
#define SECTION(sec) __attribute__((section(sec)))
/* Handler prototypes */
#if defined(_cplusplus)
extern "C" {
#endif
/* Interrupt Defualt handler */
WEAK void __int_default_handler(void);
/* Core Interrupts */
void Reset_Handler(void);
void NMI_Handler(void) ALIAS(__int_default_handler);
void HardFault_Handler(void) ALIAS(__int_default_handler);
void MemManage_Handler(void) ALIAS(__int_default_handler);
void BusFault_Handler(void) ALIAS(__int_default_handler);
void UsageFault_Handler(void) ALIAS(__int_default_handler);
void SVC_Handler(void) ALIAS(__int_default_handler);
void DebugMon_Handler(void) ALIAS(__int_default_handler);
void PendSV_Handler(void) ALIAS(__int_default_handler);
void SysTick_Handler(void) ALIAS(__int_default_handler);
/* Peripheral Interrupts (by default mapped onto Default Handler) */
void WWDG_IRQHandler(void) ALIAS(__int_default_handler);
void PVD_IRQHandler(void) ALIAS(__int_default_handler);
void TAMP_STAMP_IRQHandler(void) ALIAS(__int_default_handler);
void RTC_WKUP_IRQHandler(void) ALIAS(__int_default_handler);
void FLASH_IRQHandler(void) ALIAS(__int_default_handler);
void RCC_IRQHandler(void) ALIAS(__int_default_handler);
void EXTI0_IRQHandler(void) ALIAS(__int_default_handler);
void EXTI1_IRQHandler(void) ALIAS(__int_default_handler);
void EXTI2_IRQHandler(void) ALIAS(__int_default_handler);
void EXTI3_IRQHandler(void) ALIAS(__int_default_handler);
void EXTI4_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream0_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream1_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream2_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream3_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream4_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream5_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream6_IRQHandler(void) ALIAS(__int_default_handler);
void ADC_IRQHandler(void) ALIAS(__int_default_handler);
void CAN1_TX_IRQHandler(void) ALIAS(__int_default_handler);
void CAN1_RX0_IRQHandler(void) ALIAS(__int_default_handler);
void CAN1_RX1_IRQHandler(void) ALIAS(__int_default_handler);
void CAN1_SCE_IRQHandler(void) ALIAS(__int_default_handler);
void EXTI9_5_IRQHandler(void) ALIAS(__int_default_handler);
void TIM1_BRK_TIM9_IRQHandler(void) ALIAS(__int_default_handler);
void TIM1_UP_TIM10_IRQHandler(void) ALIAS(__int_default_handler);
void TIM1_TRG_COM_TIM11_IRQHandler(void) ALIAS(__int_default_handler);
void TIM1_CC_IRQHandler(void) ALIAS(__int_default_handler);
void TIM2_IRQHandler(void) ALIAS(__int_default_handler);
void TIM3_IRQHandler(void) ALIAS(__int_default_handler);
void TIM4_IRQHandler(void) ALIAS(__int_default_handler);
void I2C1_EV_IRQHandler(void) ALIAS(__int_default_handler);
void I2C1_ER_IRQHandler(void) ALIAS(__int_default_handler);
void I2C2_EV_IRQHandler(void) ALIAS(__int_default_handler);
void I2C2_ER_IRQHandler(void) ALIAS(__int_default_handler);
void SPI1_IRQHandler(void) ALIAS(__int_default_handler);
void SPI2_IRQHandler(void) ALIAS(__int_default_handler);
void USART1_IRQHandler(void) ALIAS(__int_default_handler);
void USART2_IRQHandler(void) ALIAS(__int_default_handler);
void USART3_IRQHandler(void) ALIAS(__int_default_handler);
void EXTI15_10_IRQHandler(void) ALIAS(__int_default_handler);
void RTC_Alarm_IRQHandler(void) ALIAS(__int_default_handler);
void OTG_FS_WKUP_IRQHandler(void) ALIAS(__int_default_handler);
void TIM8_BRK_TIM12_IRQHandler(void) ALIAS(__int_default_handler);
void TIM8_UP_TIM13_IRQHandler(void) ALIAS(__int_default_handler);
void TIM8_TRG_COM_TIM14_IRQHandler(void) ALIAS(__int_default_handler);
void TIM8_CC_IRQHandler(void) ALIAS(__int_default_handler);
void DMA1_Stream7_IRQHandler(void) ALIAS(__int_default_handler);
void FSMC_IRQHandler(void) ALIAS(__int_default_handler);
void SDIO_IRQHandler(void) ALIAS(__int_default_handler);
void TIM5_IRQHandler(void) ALIAS(__int_default_handler);
void SPI3_IRQHandler(void) ALIAS(__int_default_handler);
void UART4_IRQHandler(void) ALIAS(__int_default_handler);
void UART5_IRQHandler(void) ALIAS(__int_default_handler);
void TIM6_DAC_IRQHandler(void) ALIAS(__int_default_handler);
void TIM7_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream0_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream1_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream2_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream3_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream4_IRQHandler(void) ALIAS(__int_default_handler);
void ETH_IRQHandler(void) ALIAS(__int_default_handler);
void ETH_WKUP_IRQHandler(void) ALIAS(__int_default_handler);
void CAN2_TX_IRQHandler(void) ALIAS(__int_default_handler);
void CAN2_RX0_IRQHandler(void) ALIAS(__int_default_handler);
void CAN2_RX1_IRQHandler(void) ALIAS(__int_default_handler);
void CAN2_SCE_IRQHandler(void) ALIAS(__int_default_handler);
void OTG_FS_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream5_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream6_IRQHandler(void) ALIAS(__int_default_handler);
void DMA2_Stream7_IRQHandler(void) ALIAS(__int_default_handler);
void USART6_IRQHandler(void) ALIAS(__int_default_handler);
void I2C3_EV_IRQHandler(void) ALIAS(__int_default_handler);
void I2C3_ER_IRQHandler(void) ALIAS(__int_default_handler);
void OTG_HS_EP1_OUT_IRQHandler(void) ALIAS(__int_default_handler);
void OTG_HS_EP1_IN_IRQHandler(void) ALIAS(__int_default_handler);
void OTG_HS_WKUP_IRQHandler(void) ALIAS(__int_default_handler);
void OTG_HS_IRQHandler(void) ALIAS(__int_default_handler);
void DCMI_IRQHandler(void) ALIAS(__int_default_handler);
void CRYP_IRQHandler(void) ALIAS(__int_default_handler);
void HASH_RNG_IRQHandler(void) ALIAS(__int_default_handler);
void FPU_IRQHandler(void) ALIAS(__int_default_handler);
extern int main(void);
extern void SystemInit(void);
extern void __ld_top_of_stack(void);
#if defined(_cplusplus)
extern "C" }
#endif
void (* const vector_table[])(void) SECTION(".vectors") = {
&__ld_top_of_stack,
/* Core Interrupts */
Reset_Handler,
NMI_Handler,
HardFault_Handler,
MemManage_Handler,
BusFault_Handler,
UsageFault_Handler,
0,
0,
0,
0,
SVC_Handler,
DebugMon_Handler,
0,
PendSV_Handler,
SysTick_Handler,
/* Peripheral Interrupts */
WWDG_IRQHandler,
PVD_IRQHandler,
TAMP_STAMP_IRQHandler,
RTC_WKUP_IRQHandler,
FLASH_IRQHandler,
RCC_IRQHandler,
EXTI0_IRQHandler,
EXTI1_IRQHandler,
EXTI2_IRQHandler,
EXTI3_IRQHandler,
EXTI4_IRQHandler,
DMA1_Stream0_IRQHandler,
DMA1_Stream1_IRQHandler,
DMA1_Stream2_IRQHandler,
DMA1_Stream3_IRQHandler,
DMA1_Stream4_IRQHandler,
DMA1_Stream5_IRQHandler,
DMA1_Stream6_IRQHandler,
ADC_IRQHandler,
CAN1_TX_IRQHandler,
CAN1_RX0_IRQHandler,
CAN1_RX1_IRQHandler,
CAN1_SCE_IRQHandler,
EXTI9_5_IRQHandler,
TIM1_BRK_TIM9_IRQHandler,
TIM1_UP_TIM10_IRQHandler,
TIM1_TRG_COM_TIM11_IRQHandler,
TIM1_CC_IRQHandler,
TIM2_IRQHandler,
TIM3_IRQHandler,
TIM4_IRQHandler,
I2C1_EV_IRQHandler,
I2C1_ER_IRQHandler,
I2C2_EV_IRQHandler,
I2C2_ER_IRQHandler,
SPI1_IRQHandler,
SPI2_IRQHandler,
USART1_IRQHandler,
USART2_IRQHandler,
USART3_IRQHandler,
EXTI15_10_IRQHandler,
RTC_Alarm_IRQHandler,
OTG_FS_WKUP_IRQHandler,
TIM8_BRK_TIM12_IRQHandler,
TIM8_UP_TIM13_IRQHandler,
TIM8_TRG_COM_TIM14_IRQHandler,
TIM8_CC_IRQHandler,
DMA1_Stream7_IRQHandler,
FSMC_IRQHandler,
SDIO_IRQHandler,
TIM5_IRQHandler,
SPI3_IRQHandler,
UART4_IRQHandler,
UART5_IRQHandler,
TIM6_DAC_IRQHandler,
TIM7_IRQHandler,
DMA2_Stream0_IRQHandler,
DMA2_Stream1_IRQHandler,
DMA2_Stream2_IRQHandler,
DMA2_Stream3_IRQHandler,
DMA2_Stream4_IRQHandler,
ETH_IRQHandler,
ETH_WKUP_IRQHandler,
CAN2_TX_IRQHandler,
CAN2_RX0_IRQHandler,
CAN2_RX1_IRQHandler,
CAN2_SCE_IRQHandler,
OTG_FS_IRQHandler,
DMA2_Stream5_IRQHandler,
DMA2_Stream6_IRQHandler,
DMA2_Stream7_IRQHandler,
USART6_IRQHandler,
I2C3_EV_IRQHandler,
I2C3_ER_IRQHandler,
OTG_HS_EP1_OUT_IRQHandler,
OTG_HS_EP1_IN_IRQHandler,
OTG_HS_WKUP_IRQHandler,
OTG_HS_IRQHandler,
DCMI_IRQHandler,
CRYP_IRQHandler,
HASH_RNG_IRQHandler,
FPU_IRQHandler
};
static void __init_section(unsigned int *src_start, unsigned int *dest_start, unsigned int *dest_end) {
unsigned int *get, *put;
put = dest_start;
get = src_start;
while ((unsigned int)put < (unsigned int)dest_end) {
*(put++) = *(get++);
}
}
static void __fill_zero(unsigned int *start, unsigned int *end) {
while ((unsigned int) start < (unsigned int)end) {
*(start++) = 0x00000000;
}
}
extern unsigned int __ld_load_data;
extern unsigned int __ld_sdata_ccm;
extern unsigned int __ld_edata_ccm;
extern unsigned int __ld_load_ccm_data;
extern unsigned int __ld_sdata_ccm;
extern unsigned int __ld_edata_ccm;
extern unsigned int __ld_sbss_ccm;
extern unsigned int __ld_ebss_ccm;
extern unsigned int __ld_sdata;
extern unsigned int __ld_edata;
extern unsigned int __ld_sbss;
extern unsigned int __ld_ebss;
extern unsigned int __ld_sheap;
extern unsigned int __ld_eheap;
#ifdef CPACR
#undef CPACR
#endif
#define CPACR (*((volatile uint32_t *)0xE000ED88))
void __attribute__((noreturn)) Reset_Handler(void) {
/* Stack is already initialized by hardware */
/* The first thing we do here, is to initialize the FPU
* When this code is compiled optimized with hardfpu abi,
* GCC tends to generate FPU instructions for data copying
*/
CPACR |= (0xF << 20);
/**
* Prepare RAM etc for the System Init function. This ensures, the RAM tests execute at max speed.
*/
/* Copy .data section */
__init_section(&__ld_load_data, &__ld_sdata, &__ld_edata);
/* Fill bss with zero */
__fill_zero(&__ld_sbss, &__ld_ebss);
/* Fill Heap with zero */
__fill_zero(&__ld_sheap, &__ld_eheap);
/* Fill static CCM memory with zeroes */
__fill_zero(&__ld_sbss_ccm, &__ld_ebss_ccm);
/* Init CCM RAM data section */
__init_section(&__ld_load_ccm_data, &__ld_sdata_ccm, &__ld_edata_ccm);
/* Set clocks, waitstates, ART operation etc. */
SystemInit();
if (startup_test_perform_ccm_ram_check()) {
/* Hang forever in case of an error. We cannot handle this (yet?) */
while (1);
}
/* Move the stack and the stack pointer to CCMRAM
* This allows us to perform a RAM test on the main RAM.
*/
__asm__ __volatile__ (
"mov r2, sp\n" /* Move stack pointer to register 2 */
"sub r2, %[stacktop], r2\n" /* Subtract stackpointer from top of ram => byte usage */
"mov r3, sp\n" /* Init r3 with first word address to copy (stack pointer) */
"sub r4, %[ccmtop], r2\n" /* Init r4 with first address to copy to! This will be the new stack pointer! */
"mov r5, r4\n" /* R5 will be the new stackpointer after we are finished copying */
"copyloop:\n"
"cmp r3, %[stacktop]\n" /* Check if we still have word to copy. If not => finish */
"beq finish\n"
"ldr.w r6, [r3, #0]\n" /* Load word from [r3] and store into [r4] */
"str.w r6, [r4, #0]\n"
"add r3, #4\n" /* Increment pointers */
"add r4, #4\n"
"b copyloop\n" /* go back to loop head */
"finish:\n"
"mov sp, r5\n" /* Set the new stack pointer to the beginning of the copied area */
:
: [stacktop]"r"(&__ld_top_of_stack), [ccmtop]"r"(0x10000000UL + (64U * 1024UL))
: "memory", "r2", "r3", "r4", "r5", "r6");
if (startup_test_perform_system_ram_check()) {
while (1);
}
/* Move the stack back to system ram */
__asm__ __volatile__ (
"mov r2, sp\n" /* Move stack pointer to register 2 */
"sub r2, %[ccmtop], r2\n" /* Subtract stackpointer from top of ccmram => byte usage */
"mov r3, sp\n" /* Init r3 with first word address to copy (stack pointer) */
"sub r4, %[stacktop], r2\n" /* Init r4 with first address to copy to! This will be the new stack pointer! */
"mov r5, r4\n" /* R5 will be the new stackpointer after we are finished copying */
"copyloop_2:\n"
"cmp r3, %[ccmtop]\n" /* Check if we still have word to copy. If not => finish */
"beq finish_2\n"
"ldr.w r6, [r3, #0]\n" /* Load word from [r3] and store into [r4] */
"str.w r6, [r4, #0]\n"
"add r3, #4\n" /* Increment pointers */
"add r4, #4\n"
"b copyloop_2\n" /* go back to loop head */
"finish_2:\n"
"mov sp, r5\n" /* Set the new stack pointer to the beginning of the copied area */
:
: [stacktop]"r"(&__ld_top_of_stack), [ccmtop]"r"(0x10000000UL + (64U * 1024UL))
: "memory", "r2", "r3", "r4", "r5", "r6");
/**
* RAM tests destroyed our values. So we have to copy them again...
*/
/* Copy .data section */
__init_section(&__ld_load_data, &__ld_sdata, &__ld_edata);
/* Fill bss with zero */
__fill_zero(&__ld_sbss, &__ld_ebss);
/* Fill Heap with zero */
__fill_zero(&__ld_sheap, &__ld_eheap);
/* Fill static CCM memory with zeroes */
__fill_zero(&__ld_sbss_ccm, &__ld_ebss_ccm);
/* Init CCM RAM data section */
__init_section(&__ld_load_ccm_data, &__ld_sdata_ccm, &__ld_edata_ccm);
/* C++ init function */
#if defined(__cplusplus)
__libc_init_array();
#endif
/* Call main */
main();
/* Catch return from main() */
while(1);
}
WEAK void __int_default_handler(void)
{
while(1);
}

@ -1,519 +0,0 @@
/**
******************************************************************************
* @file startup_stm32f4xx.s
* @author MCD Application Team
* @version V1.0.0
* @date 30-September-2011
* @brief STM32F4xx Devices vector table for Atollic TrueSTUDIO toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Configure the clock system and the external SRAM mounted on
* STM324xG-EVAL board to be used as data memory (optional,
* to be enabled by user)
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M4 processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
.syntax unified
.cpu cortex-m4
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2], #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
//bl __libc_init_array
/* Call the application's entry point.*/
/* Enable FPU hard */
LDR.W R0, =0xE000ED88
LDR R1, [R0]
ORR R1, R1, #(0xF << 20)
STR R1, [R0]
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
* @param None
* @retval None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* External Interrupts */
.word WWDG_IRQHandler /* Window WatchDog */
.word PVD_IRQHandler /* PVD through EXTI Line detection */
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_IRQHandler /* EXTI Line0 */
.word EXTI1_IRQHandler /* EXTI Line1 */
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
.word CAN1_TX_IRQHandler /* CAN1 TX */
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
.word FSMC_IRQHandler /* FSMC */
.word SDIO_IRQHandler /* SDIO */
.word TIM5_IRQHandler /* TIM5 */
.word SPI3_IRQHandler /* SPI3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
.word TIM7_IRQHandler /* TIM7 */
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
.word ETH_IRQHandler /* Ethernet */
.word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */
.word CAN2_TX_IRQHandler /* CAN2 TX */
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */
.word CAN2_SCE_IRQHandler /* CAN2 SCE */
.word OTG_FS_IRQHandler /* USB OTG FS */
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
.word USART6_IRQHandler /* USART6 */
.word I2C3_EV_IRQHandler /* I2C3 event */
.word I2C3_ER_IRQHandler /* I2C3 error */
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word DCMI_IRQHandler /* DCMI */
.word CRYP_IRQHandler /* CRYP crypto */
.word HASH_RNG_IRQHandler /* Hash and Rng */
.word FPU_IRQHandler /* FPU */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_IRQHandler
.thumb_set PVD_IRQHandler,Default_Handler
.weak TAMP_STAMP_IRQHandler
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Stream0_IRQHandler
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
.weak DMA1_Stream1_IRQHandler
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler
.weak DMA1_Stream2_IRQHandler
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler
.weak DMA1_Stream3_IRQHandler
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
.weak DMA1_Stream4_IRQHandler
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler
.weak DMA1_Stream5_IRQHandler
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler
.weak DMA1_Stream6_IRQHandler
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
.weak CAN1_TX_IRQHandler
.thumb_set CAN1_TX_IRQHandler,Default_Handler
.weak CAN1_RX0_IRQHandler
.thumb_set CAN1_RX0_IRQHandler,Default_Handler
.weak CAN1_RX1_IRQHandler
.thumb_set CAN1_RX1_IRQHandler,Default_Handler
.weak CAN1_SCE_IRQHandler
.thumb_set CAN1_SCE_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_TIM9_IRQHandler
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
.weak TIM1_UP_TIM10_IRQHandler
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_TIM11_IRQHandler
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak OTG_FS_WKUP_IRQHandler
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
.weak TIM8_BRK_TIM12_IRQHandler
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
.weak TIM8_UP_TIM13_IRQHandler
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_TIM14_IRQHandler
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak DMA1_Stream7_IRQHandler
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
.weak FSMC_IRQHandler
.thumb_set FSMC_IRQHandler,Default_Handler
.weak SDIO_IRQHandler
.thumb_set SDIO_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak TIM6_DAC_IRQHandler
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Stream0_IRQHandler
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
.weak DMA2_Stream1_IRQHandler
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler
.weak DMA2_Stream2_IRQHandler
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler
.weak DMA2_Stream3_IRQHandler
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler
.weak DMA2_Stream4_IRQHandler
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
.weak ETH_IRQHandler
.thumb_set ETH_IRQHandler,Default_Handler
.weak ETH_WKUP_IRQHandler
.thumb_set ETH_WKUP_IRQHandler,Default_Handler
.weak CAN2_TX_IRQHandler
.thumb_set CAN2_TX_IRQHandler,Default_Handler
.weak CAN2_RX0_IRQHandler
.thumb_set CAN2_RX0_IRQHandler,Default_Handler
.weak CAN2_RX1_IRQHandler
.thumb_set CAN2_RX1_IRQHandler,Default_Handler
.weak CAN2_SCE_IRQHandler
.thumb_set CAN2_SCE_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak DMA2_Stream5_IRQHandler
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
.weak DMA2_Stream6_IRQHandler
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler
.weak DMA2_Stream7_IRQHandler
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler
.weak USART6_IRQHandler
.thumb_set USART6_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak OTG_HS_EP1_OUT_IRQHandler
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_HS_EP1_IN_IRQHandler
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_HS_WKUP_IRQHandler
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
.weak OTG_HS_IRQHandler
.thumb_set OTG_HS_IRQHandler,Default_Handler
.weak DCMI_IRQHandler
.thumb_set DCMI_IRQHandler,Default_Handler
.weak CRYP_IRQHandler
.thumb_set CRYP_IRQHandler,Default_Handler
.weak HASH_RNG_IRQHandler
.thumb_set HASH_RNG_IRQHandler,Default_Handler
.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

@ -23,16 +23,16 @@
#include <reflow-controller/adc-meas.h>
#include <stm-periph/uart.h>
#include <helper-macros/helper-macros.h>
#include <arm_math.h>
#include <stdlib.h>
#include <float.h>
#include <reflow-controller/safety/safety-controller.h>
enum calibration_shell_state {CAL_START = 0, CAL_WAIT_RES1, CAL_MEAS_RES1, CAL_WAIT_RES2, CAL_MEAS_RES2};
void calibration_calculate(float low_measured, float low_setpoint, float high_measured, float high_setpoint,
float *sens_deviation, float *sens_corrected_offset)
float *sens_deviation, float *offset)
{
if (!sens_deviation || !sens_corrected_offset)
if (!sens_deviation || !offset)
return;
float delta_y;
@ -45,11 +45,9 @@ void calibration_calculate(float low_measured, float low_setpoint, float high_me
sens_corr_mult = delta_x / delta_y;
*sens_deviation = sens_corr_mult - 1.0f;
*sens_corrected_offset = low_setpoint - low_measured * sens_corr_mult;
*offset = (high_setpoint * low_measured - low_setpoint * high_measured) / (high_setpoint - low_setpoint);
}
float *calibration_acquire_data_start(uint32_t count, volatile int *flag)
{
int status;
@ -74,14 +72,77 @@ free_mem:
return NULL;
}
static int calibration_poll_data_acquisition(float *mem_array, uint32_t count, volatile int *flag, float *mu, float *max_dev)
static float calculate_mean(float *values, uint32_t count)
{
uint32_t loop_cnt = (count + 7) / 8;
uint32_t remainder = count % 8;
float sum = 0;
switch (remainder) {
case 0: do { sum += *values++; /* FALLTHRU */
case 7: sum += *values++; /* FALLTHRU */
case 6: sum += *values++; /* FALLTHRU */
case 5: sum += *values++; /* FALLTHRU */
case 4: sum += *values++; /* FALLTHRU */
case 3: sum += *values++; /* FALLTHRU */
case 2: sum += *values++; /* FALLTHRU */
case 1: sum += *values++;
} while (--loop_cnt > 0);
}
return sum / (float)count;
}
static float calculate_standard_deviation(float *values, uint32_t count, float mean)
{
uint32_t loop_cnt = (count + 7) / 8;
uint32_t remainder = count % 8;
float sum = 0;
float res;
switch (remainder) {
case 0: do {
sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
case 7: sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
case 6: sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
case 5: sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
case 4: sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
case 3: sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
case 2: sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
case 1: sum += (*values - mean) * (*values - mean);
values++;
/* FALLTHRU */
} while (--loop_cnt > 0);
}
sum /= (float)count;
/* Compute the square root using the FPU.
* The constraint 't' tells GCC to use a floating point register
*/
__asm__ __volatile__("vsqrt.f32 %0, %1" : "=t"(res) : "t"(sum));
return res;
}
static int calibration_poll_data_acquisition(float *mem_array, uint32_t count, volatile int *flag, float *mu, float *std_dev)
{
int ret_val = 0;
float min_val = FLT_MAX;
float max_val = -FLT_MAX;
uint32_t i;
if (!flag || !mem_array || !mu || !max_dev)
if (!flag || !mem_array || !mu || !std_dev)
return -1000;
if (*flag == 0) {
@ -98,19 +159,9 @@ static int calibration_poll_data_acquisition(float *mem_array, uint32_t count, v
/* Convert the stream memory to Ohm readings */
adc_pt1000_convert_raw_value_array_to_resistance(NULL, mem_array, count);
/* Do not compute std-deviation. Too imprecise
* arm_std_f32(stream_mem, count, sigma);
*/
arm_mean_f32(mem_array, count, mu);
/* Find min and max values of array */
for (i = 0U; i < count; i++) {
min_val = MIN(min_val, mem_array[i]);
max_val = MAX(max_val, mem_array[i]);
}
/* Compute maximum deviation range */
*max_dev = max_val - min_val;
/* Do not compute std-deviation. Too imprecise */
*mu = calculate_mean(mem_array, count);
*std_dev = calculate_standard_deviation(mem_array, count, *mu);
ret_free_mem:
free(mem_array);
@ -121,6 +172,8 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
{
(void)arg;
(void)len;
bool error_occured;
const enum safety_flag meas_adc_err_mask = ERR_FLAG_MEAS_ADC_OFF | ERR_FLAG_MEAS_ADC_WATCHDOG;
/* This stores the current state of the calibration process */
static enum calibration_shell_state cal_state = CAL_START;
@ -134,12 +187,18 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
static volatile int flag;
char *stdin_data;
uint32_t stdin_len;
bool cal_active;
switch (cal_state) {
case CAL_START:
/* Clear errors of PT1000 reading */
adc_pt1000_clear_error();
safety_controller_ack_flag(ERR_FLAG_MEAS_ADC_WATCHDOG);
safety_controller_ack_flag(ERR_FLAG_OVERTEMP);
adc_pt1000_get_resistance_calibration(&offset, &sens_dev, &cal_active);
if (cal_active) {
shellmatta_printf(shell, "Already calibrated.\r\n\tOffset: %f\r\n\tSens: %f\r\n", offset, sens_dev);
shellmatta_printf(shell, "Press CTRL-C to abort new calibration.\r\n");
}
shellmatta_printf(shell, "Starting calibration: Insert 1000 Ohm calibration resistor and press ENTER\r\n");
cal_state = CAL_WAIT_RES1;
ret_val = SHELLMATTA_CONTINUE;
@ -154,7 +213,8 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
cal_state = CAL_MEAS_RES1;
ret_val = SHELLMATTA_BUSY;
shellmatta_printf(shell, "Measurement...\r\n");
adc_pt1000_clear_error();
safety_controller_ack_flag(ERR_FLAG_MEAS_ADC_WATCHDOG);
safety_controller_ack_flag(ERR_FLAG_OVERTEMP);
data_buffer = calibration_acquire_data_start(512UL, &flag);
break;
} else if (stdin_data[i] == '\x03') {
@ -178,9 +238,10 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
ret_val = SHELLMATTA_BUSY;
cal_state = CAL_MEAS_RES1;
} else if (res == 0) {
shellmatta_printf(shell, "R=%.2f, Noise peak-peak: %.2f\r\n", mu, dev);
if (adc_pt1000_check_error() != ADC_PT1000_NO_ERR) {
shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error());
shellmatta_printf(shell, "R=%.2f, Std-Dev: %.2f\r\n", mu, dev);
error_occured = safety_controller_get_flags_by_mask(meas_adc_err_mask);
if (error_occured) {
shellmatta_printf(shell, "Error in resistance measurement");
ret_val = SHELLMATTA_OK;
cal_state = CAL_START;
} else {
@ -189,7 +250,7 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
cal_state = CAL_WAIT_RES2;
}
} else {
shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error());
shellmatta_printf(shell, "Error in resistance measurement");
ret_val = SHELLMATTA_OK;
cal_state = CAL_START;
}
@ -204,7 +265,8 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
cal_state = CAL_MEAS_RES2;
ret_val = SHELLMATTA_BUSY;
shellmatta_printf(shell, "Measurement...\r\n");
adc_pt1000_clear_error();
safety_controller_ack_flag(ERR_FLAG_MEAS_ADC_WATCHDOG);
safety_controller_ack_flag(ERR_FLAG_OVERTEMP);
data_buffer = calibration_acquire_data_start(512UL, &flag);
break;
} else if (stdin_data[i] == '\x03') {
@ -228,17 +290,18 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
ret_val = SHELLMATTA_BUSY;
cal_state = CAL_MEAS_RES2;
} else if (res == 0) {
shellmatta_printf(shell, "R=%.2f, Noise peak-peak: %.2f\r\n", mu2, dev2);
if (adc_pt1000_check_error() != ADC_PT1000_NO_ERR) {
shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error());
shellmatta_printf(shell, "R=%.2f, Std-Dev: %.2f\r\n", mu2, dev2);
error_occured = safety_controller_get_flags_by_mask(meas_adc_err_mask);
if (error_occured) {
shellmatta_printf(shell, "Error in resistance measurement");
ret_val = SHELLMATTA_OK;
cal_state = CAL_START;
} else {
ret_val = SHELLMATTA_OK;
cal_state = CAL_START;
if (dev > CALIBRATION_MAX_PEAK_PEAK_NOISE_OHM ||
dev2 > CALIBRATION_MAX_PEAK_PEAK_NOISE_OHM) {
if (dev > CALIBRATION_MAX_NOISE_OHM ||
dev2 > CALIBRATION_MAX_NOISE_OHM) {
shellmatta_printf(shell, "Calibration failed! Too much noise. Check your hardware.\r\n");
break;
}
@ -250,7 +313,7 @@ shellmatta_retCode_t calibration_sequence_shell_cmd(shellmatta_handle_t shell, c
adc_pt1000_set_resistance_calibration(offset, sens_dev, true);
}
} else {
shellmatta_printf(shell, "Error in resistance measurement: %d", adc_pt1000_check_error());
shellmatta_printf(shell, "Error in resistance measurement");
ret_val = SHELLMATTA_OK;
cal_state = CAL_START;
}

@ -0,0 +1,226 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup config-parser
* @{
*/
#include <config-parser/config-parser.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Config parser magic value used to check sanity of passed structs
*/
#define CONFIG_PARSER_MAGIC 0x464a6e2bUL
/**
* @brief Config parser type casting macro
*/
#define CONFIG_PARSER(p) ((struct config_parser *)(p))
/**
* @brief Check if the supplied pointer is a valid @ref config_parser_handle_t
*
* If the pointer is invalid, the function using this macro will return with
* CONFIG_PARSER_PARAM_ERR
*/
#define config_parser_check_handle(handle) do { \
if (!(handle) || \
((struct config_parser *)(handle))->magic != CONFIG_PARSER_MAGIC) \
return CONFIG_PARSER_PARAM_ERR; \
} while (0)
config_parser_handle_t config_parser_open_file(struct config_parser *config_parser, bool write, const char *file_name,
char *working_buffer, size_t buff_size)
{
FRESULT res;
if (!config_parser || !file_name || !working_buffer)
return NULL;
config_parser->magic = CONFIG_PARSER_MAGIC;
config_parser->write = write;
config_parser->buffer = working_buffer;
config_parser->buff_size = buff_size;
res = f_open(&config_parser->file, file_name, (write ? FA_CREATE_ALWAYS | FA_WRITE : FA_READ));
if (res != FR_OK)
return NULL;
return (config_parser_handle_t)config_parser;
}
/**
* @brief Token delimiters for the config parser.
*/
static const char * const token_delim = " \t";
/**
* @brief Parse a value in the configuration
* @param entry Entry to parse the value in to
* @param value_start_token char pointer holding the value. Must be null-terminated
* @return 0 if successful
*/
static int parse_value(struct config_parser_entry *entry, char *value_start_token)
{
char *dot;
char *endptr;
/* Check if token is a float number */
dot = strstr(value_start_token, ".");
if (dot) {
/* Try parsing as float */
entry->value.float_val = strtof(value_start_token, &endptr);
if (endptr == value_start_token)
return -1;
entry->type = CONFIG_PARSER_TYPE_FLOAT;
goto exit;
}
if (value_start_token[0] != '-') {
/* Try parsing as ul */
entry->value.uint_val = strtoul(value_start_token, &endptr, 0);
if (endptr == value_start_token)
return -1;
entry->type = CONFIG_PARSER_TYPE_UINT;
goto exit;
} else {
/* Try parsing as int */
entry->value.int_val = strtod(value_start_token, &endptr);
if (endptr == value_start_token)
return -1;
entry->type = CONFIG_PARSER_TYPE_INT;
}
exit:
return 0;
}
enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, struct config_parser_entry *entry,
bool force_float)
{
struct config_parser *p;
char *token;
int token_round = 0;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);
if (!entry)
return CONFIG_PARSER_PARAM_ERR;
p->buffer[0] = '\0';
if (f_gets(p->buffer, (int)p->buff_size, &p->file) == NULL)
return CONFIG_PARSER_IOERR;
token = strtok(p->buffer, token_delim);
while (token != NULL) {
/* Check for comment */
if (token[0] == '#') {
if (token_round == 0)
return CONFIG_PARSER_LINE_COMMENT;
break;
}
switch (token_round) {
case 0: /* KEY */
entry->name = token;
break;
case 1: /* = Symbol */
if (strcmp(token, "="))
return CONFIG_PARSER_LINE_MALFORM;
break;
case 2: /* VALUE */
if (parse_value(entry, token))
return CONFIG_PARSER_LINE_MALFORM;
break;
default:
return CONFIG_PARSER_LINE_MALFORM;
}
token_round++;
token = strtok(NULL, token_delim);
}
if (force_float) {
if (entry->type == CONFIG_PARSER_TYPE_INT)
entry->value.float_val = (float)entry->value.int_val;
if (entry->type == CONFIG_PARSER_TYPE_UINT)
entry->value.float_val = (float)entry->value.uint_val;
entry->type = CONFIG_PARSER_TYPE_FLOAT;
}
return CONFIG_PARSER_OK;
}
enum config_parser_ret config_parser_reset_to_start(config_parser_handle_t handle)
{
FRESULT res;
struct config_parser *p;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);
res = f_rewind(&p->file);
if (res != FR_OK)
return CONFIG_PARSER_IOERR;
return CONFIG_PARSER_OK;
}
enum config_parser_ret config_parser_write_entry(config_parser_handle_t handle, const struct config_parser_entry *entry)
{
(void)entry;
config_parser_check_handle(handle);
return CONFIG_PARSER_OK;
}
enum config_parser_ret config_parser_close_file(config_parser_handle_t handle)
{
struct config_parser *p;
FRESULT res;
config_parser_check_handle(handle);
p = CONFIG_PARSER(handle);
res = f_close(&p->file);
return (res == FR_OK ? CONFIG_PARSER_OK : CONFIG_PARSER_IOERR);
}
bool config_parser_ret_is_abort_condition(enum config_parser_ret return_val)
{
if (return_val == CONFIG_PARSER_END_REACHED ||
return_val == CONFIG_PARSER_GENERIC_ERR ||
return_val == CONFIG_PARSER_IOERR ||
return_val == CONFIG_PARSER_PARAM_ERR)
return true;
return false;
}
/** @} */

@ -0,0 +1,145 @@
/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file config-parser.h
* @brief Header file for the key-value pair config parser
* @addtogroup config-parser
* @{
*/
#ifndef _CONFIG_PARSER_H_
#define _CONFIG_PARSER_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <fatfs/ff.h>
/**
* @brief Confi parser instance struct
*/
struct config_parser {
uint32_t magic; /**< @brief Magic value. Checked by each function to verify if the passed pointer is valid */
bool write; /**< @brief File opened in write / read mode */
FIL file; /**< @brief FatFS file */
char *buffer; /**< @brief Working buffer */
size_t buff_size; /** @brief Size of the working buffer config_parser::buffer */
};
/**
* @brief handle type for the config parser. Never dereference this pointer directly!
*/
typedef void * config_parser_handle_t;
/**
* @brief Differnet value types a config entry can hold
*/
enum config_parser_value_type {
CONFIG_PARSER_TYPE_UINT = 0,
CONFIG_PARSER_TYPE_INT,
CONFIG_PARSER_TYPE_FLOAT,
};
/**
* @brief Error return code of config parser functions
*/
enum config_parser_ret {
CONFIG_PARSER_OK = 0, /**< @brief Operation succeeded */
CONFIG_PARSER_PARAM_ERR, /**< @brief Function parameter error */
CONFIG_PARSER_GENERIC_ERR, /**< @brief Generic unspecified error */
CONFIG_PARSER_IOERR, /**< @brief I/O Error while file handling */
CONFIG_PARSER_LINE_COMMENT, /**< @brief The parser encountered a line starting with a comment. */
CONFIG_PARSER_LINE_TOO_LONG, /**< @brief The read line is too long for the parser to process. */
CONFIG_PARSER_LINE_MALFORM, /**< @brief Malfoirmed line. Line is neither a commenbt nor a key=value string */
CONFIG_PARSER_END_REACHED, /**< @brief The config parser has reached the end of the file */
CONFIG_PARSER_WRONG_MODE, /**< @brief Read or write requested on config parser instance that is opened in a different mode */
};
/**
* @brief Represents a configuration key-value-pair used by the config parser
*/
struct config_parser_entry {
const char *name; /**< @brief Pointer to the name of the config entry (key) */
enum config_parser_value_type type; /**< @brief Type of the value held by this struct */
union {
uint32_t uint_val;
int32_t int_val;
float float_val;
} value; /**< @brief Value of the config entry. For correct processing, config_parser_entry::type has to be taken into account */
};
/**
* @brief Open a config file
* @param config_parser Struict holding the config parser isntance. Will be filled by this function
* @param write Open the config file for writing (true) or reading (false)
* @param file_name File name to open
* @param working_buffer A working buffer used by the config parser to process the file.
* @param buff_size Size of \p working_buffer. Must be large enough to hold a full line of the config file
* @return Config parser error
*/
config_parser_handle_t config_parser_open_file(struct config_parser *config_parser, bool write, const char *file_name,
char *working_buffer, size_t buff_size);
/**
* @brief Parse the current line in the config file.
* @param handle Config parser handle
* @param[out] entry Entry read from config file.
* @warning \p entry is only valid as long as no other function was called on the same \p handle. If necessary, the values
* have to be copied
* @return Config parser error
*/
enum config_parser_ret config_parser_get_line(config_parser_handle_t handle, struct config_parser_entry *entry, bool force_float);
/**
* @brief Reset the config parser instance to the beginning of the config file
* @param handle Config parser
* @return Config parser error
*/
enum config_parser_ret config_parser_reset_to_start(config_parser_handle_t handle);
/**
* @brief Write a config entry to a config file
* @param handle Handle to the config parser. This must be opened in write mode.
* @param entry
* @return Config parser error
* @warning This function is currently not implemented and will return with a success!
*/
enum config_parser_ret config_parser_write_entry(config_parser_handle_t handle, const struct config_parser_entry *entry);
/**
* @brief Close a config parser handle
* @param handle Config parser
* @return Config parser error
*/
enum config_parser_ret config_parser_close_file(config_parser_handle_t handle);
/**
* @brief Check if the \p return_val is a abort condition to stop parsing a file.
*
* This function will return true if a disk error occured or the end of file is reached.
*
* @param return_val
* @return
*/
bool config_parser_ret_is_abort_condition(enum config_parser_ret return_val);
#endif /* _CONFIG_PARSER_H_ */
/** @} */

@ -6,7 +6,7 @@ import pathlib
license_header = """/* Reflow Oven Controller
*
* Copyright (C) 2020 Mario Hüttel <mario.huettel@gmx.net>
* Copyright (C) 2022 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
@ -37,7 +37,7 @@ cpath = os.path.join(project_dir, sys.argv[1]+'.c')
hfile = sys.argv[1]+'.h'
hpath = os.path.join(module_include_dir, hfile)
h_define = '__'+hfile.replace('.', '_').replace('-', '_').replace('/', '_').upper()+'__'
h_define = '_'+hfile.replace('.', '_').replace('-', '_').replace('/', '_').upper()+'_'
if os.path.exists(cpath) or os.path.exists(hpath):
print("File already exists! Abort!")

@ -0,0 +1,15 @@
#!/bin/bash
if [[ -z $1 ]]; then
# Exit with error in case no output file is specified
exit -1
fi
firmware_version=`git describe --tags --always --dirty`
commit=`git rev-parse HEAD`
echo "#ifndef _VERSION_GENERATED_H_" > $1
echo "#define _VERSION_GENERATED_H_" >> $1
echo "#define GIT_VERSION_STRING \"$firmware_version\"" >> $1
echo "#define GIT_FULL_COMMIT \"$commit\"" >> $1
echo "#endif /* _VERSION_GENERATED_H_ */" >> $1

@ -18,9 +18,14 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup digio
* @{
*/
#include <reflow-controller/digio.h>
#include <stm32/stm32f4xx.h>
#include <stm-periph/clock-enable-manager.h>
#include <stm-periph/rcc-manager.h>
#include <stm-periph/stm32-gpio-macros.h>
#include <helper-macros/helper-macros.h>
@ -47,17 +52,10 @@ static void digio_setup_pin_int(uint8_t bit_no, uint8_t in_out, uint8_t alt_func
}
void digio_setup_default_all()
void digio_init(void)
{
unsigned int i;
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(DIGIO_RCC_MASK));
for (i = 0; i < COUNT_OF(digio_pins); i++) {
digio_setup_pin_int(digio_pins[i], digio_default_io[i], digio_default_altfunc[i]);
if (digio_default_io[i] == 1)
digio_set(i, 0);
}
digio_set_default_values();
}
void digio_setup_pin(uint8_t num, uint8_t in_out, uint8_t alt_func)
@ -69,12 +67,22 @@ void digio_setup_pin(uint8_t num, uint8_t in_out, uint8_t alt_func)
void digio_set(uint8_t num, int val)
{
uint8_t pin;
if (num >= COUNT_OF(digio_pins))
return;
pin = digio_pins[num];
/* Check if port is an output. If not, do noting. */
if ((DIGIO_PORT->MODER & (0x3<<pin)) != OUTPUT(pin)) {
return;
}
if (val)
DIGIO_PORT->ODR |= (1<<digio_pins[num]);
DIGIO_PORT->ODR |= (1<<pin);
else
DIGIO_PORT->ODR &= ~(1<<digio_pins[num]);
DIGIO_PORT->ODR &= ~(1<<pin);
}
int digio_get(uint8_t num)
@ -90,7 +98,7 @@ int digio_get(uint8_t num)
static const uint8_t led_pins[] = {LED_PINS};
void led_setup()
void led_setup(void)
{
unsigned int i;
@ -119,7 +127,12 @@ int led_get(uint8_t num)
return ((LED_PORT->ODR & (1<<led_pins[num])) ? 1 : 0);
}
/**
* @brief Initialize the timer for the beeper to generate the output frequency
*
* TIM7 is used as the frequency generating timer. If @ref LOUDSPEAKER_MULTIFREQ
* is 0, the timer is unused and this function does nothing.
*/
static void loudspeaker_freq_timer_init(void)
{
#if LOUDSPEAKER_MULTIFREQ
@ -132,7 +145,7 @@ static void loudspeaker_freq_timer_init(void)
#endif
}
void loudspeaker_setup()
void loudspeaker_setup(void)
{
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(LOUDSPEAKER_RCC_MASK));
@ -143,10 +156,17 @@ void loudspeaker_setup()
loudspeaker_set(0U);
}
/**
* @brief Start the beeper
* @param val frequency value of the speaker in 'Timer relaod values'
* @note If @ref LOUDSPEAKER_MULTIFREQ isn't set,
* the speaker output will be set to high and no frequency is generated.
* The value of @p val is ignored in this case
*/
static void loudspeaker_start_beep(uint16_t val)
{
#if LOUDSPEAKER_MULTIFREQ
TIM7->ARR = val;
TIM7->ARR = (val == 1 ? LOUDSPEAKER_MULTIFREQ_DEFAULT : val);
TIM7->CNT = 0UL;
TIM7->CR1 |= TIM_CR1_CEN;
#else
@ -155,6 +175,9 @@ static void loudspeaker_start_beep(uint16_t val)
#endif
}
/**
* @brief Stop the beeping of the loudspeaker
*/
static void loudspeaker_stop_beep(void)
{
#if LOUDSPEAKER_MULTIFREQ
@ -172,19 +195,24 @@ void loudspeaker_set(uint16_t val)
{
loudspeaker_val = val;
if (!val) {
if (!val)
loudspeaker_stop_beep();
} else {
else
loudspeaker_start_beep(val);
}
}
uint16_t loudspeaker_get()
uint16_t loudspeaker_get(void)
{
return loudspeaker_val;
}
#if LOUDSPEAKER_MULTIFREQ
/**
* @brief Timer7 IRQ Handler
*
* This IRQ Handler is used by the loudspeaker to synthesize the output frequency.
* If @ref LOUDSPEAKER_MULTIFREQ is 0, TIM7 and this interrupt will not be used.
*/
void TIM7_IRQHandler(void)
{
TIM7->SR = 0UL;
@ -192,3 +220,16 @@ void TIM7_IRQHandler(void)
LOUDSPEAKER_PORT->ODR ^= (1<<LOUDSPEAKER_PIN);
}
#endif
/** @} */
void digio_set_default_values()
{
unsigned int i;
for (i = 0; i < COUNT_OF(digio_pins); i++) {
digio_setup_pin_int(digio_pins[i], digio_default_io[i], digio_default_altfunc[i]);
if (digio_default_io[i] == 1)
digio_set(i, 0);
}
}

@ -0,0 +1,40 @@
find_package(Doxygen)
if(NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(ColorBold "${Esc}[1m")
set(Red "${Esc}[31m")
set(Green "${Esc}[32m")
set(Yellow "${Esc}[33m")
set(Blue "${Esc}[34m")
set(Magenta "${Esc}[35m")
set(Cyan "${Esc}[36m")
set(White "${Esc}[37m")
set(BoldRed "${Esc}[1;31m")
set(BoldGreen "${Esc}[1;32m")
set(BoldYellow "${Esc}[1;33m")
set(BoldBlue "${Esc}[1;34m")
set(BoldMagenta "${Esc}[1;35m")
set(BoldCyan "${Esc}[1;36m")
set(BoldWhite "${Esc}[1;37m")
endif()
if (DOXYGEN_FOUND)
add_custom_target(documentation DEPENDS doxygen doxygen-pdf)
add_custom_target(doxygen
COMMAND ./build-doxygen.sh "${PROJECT_BINARY_DIR}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating documentation with Doxygen")
add_custom_target(
doxygen-pdf
COMMAND make
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/latex"
DEPENDS doxygen
)
else (DOXYGEN_FOUND)
message("${BoldMagenta}Doxygen needs to be installed to generate the doxygen documentation${ColorReset}")
message("${BoldMagenta}doxygen, documentation, doxygen-latex targets will not be available${ColorReset}")
endif (DOXYGEN_FOUND)

@ -1,4 +1,4 @@
# Doxyfile 1.8.17
# Doxyfile 1.9.2
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@ -93,14 +93,6 @@ ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all generated output in the proper direction.
# Possible values are: None, LTR, RTL and Context.
# The default value is: None.
OUTPUT_TEXT_DIRECTION = None
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
@ -186,7 +178,7 @@ STRIP_FROM_INC_PATH =
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
SHORT_NAMES = YES
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
@ -227,6 +219,14 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
# By default Python docstrings are displayed as preformatted text and doxygen's
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
# doxygen's special commands can be used and the contents of the docstring
# documentation blocks is shown as doxygen documentation.
# The default value is: YES.
PYTHON_DOCSTRING = YES
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
@ -250,25 +250,19 @@ TAB_SIZE = 8
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# "sideeffect=@par Side Effects:^^"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines (in the resulting output). You can put ^^ in the value part of an
# alias to insert a newline as if a physical newline was in the original file.
# When you need a literal { or } or , in the value part of an alias you have to
# escape them by means of a backslash (\), this can lead to conflicts with the
# commands \{ and \} for these it is advised to use the version @{ and @} or use
# a double escape (\\{ and \\})
# "Side Effects:". Note that you cannot put \n's in the value part of an alias
# to insert newlines (in the resulting output). You can put ^^ in the value part
# of an alias to insert a newline as if a physical newline was in the original
# file. When you need a literal { or } or , in the value part of an alias you
# have to escape them by means of a backslash (\), this can lead to conflicts
# with the commands \{ and \} for these it is advised to use the version @{ and
# @} or use a double escape (\\{ and \\})
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
@ -310,18 +304,21 @@ OPTIMIZE_OUTPUT_SLICE = NO
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
# tries to guess whether the code is fixed or free formatted code, this is the
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
# .inc files as Fortran files (default is PHP), and .f files as C (default is
# Fortran), use: inc=Fortran f=C.
# default for Fortran type files). For instance to make doxygen treat .inc files
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
# use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
# the files are not read by doxygen. When specifying no_extension you should add
# * to the FILE_PATTERNS.
#
# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
@ -455,6 +452,19 @@ TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
# during processing. When set to 0 doxygen will based this on the number of
# cores available in the system. You can set it explicitly to a value larger
# than 0 to get more control over the balance between CPU load and processing
# speed. At this moment only the input processing can be done using multiple
# threads. Since this is still an experimental feature the default is set to 1,
# which effectively disables parallel processing. Please report any issues you
# encounter. Generating dot graphs in parallel is controlled by the
# DOT_NUM_THREADS setting.
# Minimum value: 0, maximum value: 32, default value: 1.
NUM_PROC_THREADS = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@ -518,6 +528,13 @@ EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
# If this flag is set to YES, the name of an unnamed parameter in a declaration
# will be determined by the corresponding definition. By default unnamed
# parameters remain unnamed in the output.
# The default value is: YES.
RESOLVE_UNNAMED_PARAMS = YES
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
@ -555,11 +572,18 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# (including Cygwin) ands Mac users are advised to set this option to NO.
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
# able to match the capabilities of the underlying filesystem. In case the
# filesystem is case sensitive (i.e. it supports files in the same directory
# whose names only differ in casing), the option must be set to YES to properly
# deal with such files in case they appear in the input. For filesystems that
# are not case sensitive the option should be be set to NO to properly deal with
# output files written for symbols that only differ in casing, such as for two
# classes, one named CLASS and the other named Class, and to also support
# references to files without having to specify the exact matching casing. On
# Windows (including Cygwin) and MacOS, users should typically set this option
# to NO, whereas on Linux or other Unix flavors it should typically be set to
# YES.
# The default value is: system dependent.
CASE_SENSE_NAMES = NO
@ -578,6 +602,12 @@ HIDE_SCOPE_NAMES = YES
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
# will show which file needs to be included to use the class.
# The default value is: YES.
SHOW_HEADERFILE = YES
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
@ -735,7 +765,8 @@ FILE_VERSION_FILTER =
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
# will be used as the name of the layout file. See also section "Changing the
# layout of pages" for information.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
@ -781,24 +812,35 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# potential errors in the documentation, such as documenting some parameters in
# a documented function twice, or documenting parameters that don't exist or
# using markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
# function parameter documentation. If set to NO, doxygen will accept that some
# parameters have no documentation without warning.
# The default value is: YES.
WARN_IF_INCOMPLETE_DOC = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation. If
# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
# value. If set to NO, doxygen will only warn about wrong parameter
# documentation, but not about the absence of documentation. If EXTRACT_ALL is
# set to YES then this flag will automatically be disabled. See also
# WARN_IF_INCOMPLETE_DOC
# The default value is: NO.
WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
# at the end of the doxygen process doxygen will return with a non-zero status.
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
# The default value is: NO.
WARN_AS_ERROR = NO
@ -834,8 +876,8 @@ INPUT = ../
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
# possible encodings.
# documentation (see:
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
@ -848,12 +890,14 @@ INPUT_ENCODING = UTF-8
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# Note the list of default checked file patterns might differ from the list of
# default file extension mappings.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
# *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.c \
@ -919,8 +963,13 @@ RECURSIVE = YES
EXCLUDE = ../include/stm32 \
../include/arm_math.h \
../include/cmsis \
../shellmatta/test
../include/cmsis/ \
../shellmatta/test/ \
../linklist-lib/test \
../base64-lib/test \
../shellmatta/doc/main.dox \
../updater/ram-code \
./
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@ -1128,13 +1177,6 @@ VERBATIM_HEADERS = YES
ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
@ -1234,7 +1276,7 @@ HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# this color. Hue is specified as an angle on a color-wheel, see
# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
@ -1244,7 +1286,7 @@ HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# in the HTML output. For a value of 0 the output will use gray-scales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
@ -1305,10 +1347,11 @@ HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# environment (see:
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
# create a documentation set, doxygen will generate a Makefile in the HTML
# output directory. Running make will produce the docset in that directory and
# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
# genXcode/_index.html for more information.
@ -1350,8 +1393,12 @@ DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
# on Windows. In the beginning of 2021 Microsoft took the original page, with
# a.o. the download links, offline the HTML help workshop was already many years
# in maintenance mode). You can download the HTML help workshop from the web
# archives at Installation executable (see:
# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@ -1381,7 +1428,7 @@ CHM_FILE =
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@ -1426,7 +1473,8 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
@ -1434,8 +1482,8 @@ QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
# folders).
# Folders (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
@ -1443,16 +1491,16 @@ QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# Filters (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
# filters).
# Filters (see:
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
@ -1464,9 +1512,9 @@ QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# The QHG_LOCATION tag can be used to specify the location (absolute path
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
@ -1509,16 +1557,28 @@ DISABLE_INDEX = NO
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# further fine tune the look of the index (see "Fine-tuning the output"). As an
# example, the default style sheet generated by doxygen has an example that
# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
# Since the tree basically has the same information as the tab index, you could
# consider setting DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
# area (value NO) or if it should extend to the full height of the window (value
# YES). Setting this to YES gives a layout similar to
# https://docs.readthedocs.io with more room for contents, but less room for the
# project logo, title, and description. If either GENERATOR_TREEVIEW or
# DISABLE_INDEX is set to NO, this option has no effect.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
FULL_SIDEBAR = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
@ -1543,6 +1603,17 @@ TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
# the HTML output. These images will generally look nicer at scaled resolutions.
# Possible values are: png (the default) and svg (looks nicer but requires the
# pdf2svg or inkscape tool).
# The default value is: png.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FORMULA_FORMAT = png
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
@ -1580,11 +1651,29 @@ FORMULA_MACROFILE =
USE_MATHJAX = YES
# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
# Note that the different versions of MathJax have different requirements with
# regards to the different settings, so it is possible that also other MathJax
# settings have to be changed when switching between the different MathJax
# versions.
# Possible values are: MathJax_2 and MathJax_3.
# The default value is: MathJax_2.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_VERSION = MathJax_2
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/latest/output.html) for more details.
# the MathJax output. For more details about the output format see MathJax
# version 2 (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
# (see:
# http://docs.mathjax.org/en/latest/web/components/output.html).
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# compatibility. This is the name for Mathjax version 2, for MathJax version 3
# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
# is the name for Mathjax version 3, for MathJax version 2 this will be
# translated into HTML-CSS) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
@ -1597,22 +1686,29 @@ MATHJAX_FORMAT = HTML-CSS
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from https://www.mathjax.org before deployment.
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
# MathJax from https://www.mathjax.org before deployment. The default value is:
# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# for MathJax version 2 (see
# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# For example for MathJax version 3 (see
# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
# MATHJAX_EXTENSIONS = ams
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# (see:
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
@ -1659,7 +1755,8 @@ SERVER_BASED_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/).
# Xapian (see:
# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
@ -1672,8 +1769,9 @@ EXTERNAL_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: https://xapian.org/). See the section "External Indexing and
# Searching" for details.
# Xapian (see:
# https://xapian.org/). See the section "External Indexing and Searching" for
# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
@ -1782,29 +1880,31 @@ PAPER_TYPE = a4
EXTRA_PACKAGES = amsmath
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
# chapter. If it is left blank doxygen will generate a standard header. See
# section "Doxygen usage" for information on how to let doxygen write the
# default header to a separate file.
# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
# the generated LaTeX document. The header should contain everything until the
# first chapter. If it is left blank doxygen will generate a standard header. It
# is highly recommended to start with a default header using
# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
# and then modify the file new_header.tex. See also section "Doxygen usage" for
# information on how to generate the default header that doxygen normally uses.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# Note: Only use a user-defined header if you know what you are doing!
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. The following
# commands have a special meaning inside the header (and footer): For a
# description of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See
# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
# the generated LaTeX document. The footer should contain everything after the
# last chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# special commands can be used inside the footer. See also section "Doxygen
# usage" for information on how to generate the default footer that doxygen
# normally uses. Note: Only use a user-defined footer if you know what you are
# doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
@ -1837,9 +1937,11 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
# files. Set this option to YES, to get a higher quality PDF documentation.
#
# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@ -1847,8 +1949,7 @@ USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used
# when generating formulas in HTML.
# if errors occur, instead of asking the user for help.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@ -1861,16 +1962,6 @@ LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = YES
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
@ -1951,16 +2042,6 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
@ -2013,7 +2094,7 @@ MAN_LINKS = NO
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
GENERATE_XML = YES
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
@ -2057,15 +2138,6 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
@ -2078,6 +2150,10 @@ DOCBOOK_PROGRAMLISTING = NO
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to Sqlite3 output
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
@ -2133,7 +2209,7 @@ ENABLE_PREPROCESSING = YES
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = NO
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
@ -2141,7 +2217,7 @@ MACRO_EXPANSION = NO
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
@ -2173,7 +2249,8 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
PREDEFINED = __attribute__(x)= \
IN_SECTION(x)=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@ -2350,10 +2427,32 @@ UML_LOOK = NO
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
# tag is set to YES, doxygen will add type and arguments for attributes and
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
# will not generate fields with class member information in the UML graphs. The
# class diagrams will look similar to the default class diagrams but using UML
# notation for the relationships.
# Possible values are: NO, YES and NONE.
# The default value is: NO.
# This tag requires that the tag UML_LOOK is set to YES.
DOT_UML_DETAILS = NO
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
# to display on a single line. If the actual line length exceeds this threshold
# significantly it will wrapped across multiple lines. Some heuristics are apply
# to avoid ugly line breaks.
# Minimum value: 0, maximum value: 1000, default value: 17.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_WRAP_THRESHOLD = 17
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
@ -2543,9 +2642,11 @@ DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
#
# Note: This setting is not only used for dot files but also for msc temporary
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES

@ -11,10 +11,17 @@ cd "$DIR"
export PROJECT_NUMBER=`git describe --always --tags --dirty`
if [ $# != 1 ]; then
configfile="Doxyconfig"
if [[ -z "$1" ]]; then
export OUTPUT_DIRECTORY="./output"
else
export OUTPUT_DIRECTORY="$1"
fi
doxygen Doxyconfig
if [[ -n "$2" ]]; then
configfile="$2"
fi
doxygen "$configfile"

@ -0,0 +1,24 @@
FatFs License
FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files.
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module Rx.xx /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 20xx, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/
Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license.

@ -1,5 +1,5 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2019 */
/* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
@ -12,14 +12,8 @@
#include "shimatta_sdio_driver/shimatta_sdio.h"
/* Definitions of physical drive number for each drive */
#define DEV_SD 0 /* Example: Map MMC/SD card to physical drive 0*/
/*
DSTATUS SDIO_status();
DSTATUS SDIO_initialize();
DRESULT SDIO_disk_read(BYTE *buff, DWORD sector, UINT count);
DRESULT SDIO_disk_write(const BYTE *buff, DWORD sector, UINT count);
DRESULT SDIO_disk_ioctl(BYTE cmd, void* buff);
*/
#define DEV_SD 0
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
@ -116,4 +110,3 @@ DRESULT disk_ioctl (
return RES_PARERR;
}

File diff suppressed because it is too large Load Diff

@ -1,170 +1,208 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2018 */
/* A Sample Code of User Provided OS Dependent Functions for FatFs */
/*------------------------------------------------------------------------*/
#include <fatfs/ff.h>
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
#if FF_USE_LFN == 3 /* Use dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/* Allocate/Free a Memory Block */
/*------------------------------------------------------------------------*/
#include <stdlib.h> /* with POSIX API */
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
return malloc((size_t)msize); /* Allocate a new memory block */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
void* mblock /* Pointer to the memory block to free (no effect if null) */
)
{
free(mblock); /* Free the memory block with POSIX API */
free(mblock); /* Free the memory block */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/* Definitions of Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
*/
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
#define OS_TYPE 0 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t* sobj /* Pointer to return the created sync object */
)
{
/* Win32 */
*sobj = CreateMutex(NULL, FALSE, NULL);
return (int)(*sobj != INVALID_HANDLE_VALUE);
#if OS_TYPE == 0 /* Win32 */
#include <windows.h>
static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
#elif OS_TYPE == 1 /* uITRON */
#include "itron.h"
#include "kernel.h"
static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 2 /* uc/OS-II */
#include "includes.h"
static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */
/* FreeRTOS */
// *sobj = xSemaphoreCreateMutex();
// return (int)(*sobj != NULL);
#elif OS_TYPE == 3 /* FreeRTOS */
#include "FreeRTOS.h"
#include "semphr.h"
static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
/* CMSIS-RTOS */
// *sobj = osMutexCreate(&Mutex[vol]);
// return (int)(*sobj != NULL);
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
/* Win32 */
return (int)CloseHandle(sobj);
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// vSemaphoreDelete(sobj);
// return 1;
/* CMSIS-RTOS */
// return (int)(osMutexDelete(sobj) == osOK);
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
FF_SYNC_t sobj /* Sync object to wait */
)
{
/* Win32 */
return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
/* CMSIS-RTOS */
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* Win32 */
ReleaseMutex(sobj);
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
/* FreeRTOS */
// xSemaphoreGive(sobj);
/* CMSIS-RTOS */
// osMutexRelease(sobj);
}
#elif OS_TYPE == 4 /* CMSIS-RTOS */
#include "cmsis_os.h"
static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#endif
/*------------------------------------------------------------------------*/
/* Create a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to create a new mutex
/ or semaphore for the volume. When a 0 is returned, the f_mount function
/ fails with FR_INT_ERR.
*/
int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
Mutex[vol] = CreateMutex(NULL, FALSE, NULL);
return (int)(Mutex[vol] != INVALID_HANDLE_VALUE);
#elif OS_TYPE == 1 /* uITRON */
T_CMTX cmtx = {TA_TPRI,1};
Mutex[vol] = acre_mtx(&cmtx);
return (int)(Mutex[vol] > 0);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
Mutex[vol] = OSMutexCreate(0, &err);
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
Mutex[vol] = xSemaphoreCreateMutex();
return (int)(Mutex[vol] != NULL);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDef(cmsis_os_mutex);
Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex));
return (int)(Mutex[vol] != NULL);
#endif
}
/*------------------------------------------------------------------------*/
/* Delete a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to delete a mutex or
/ semaphore of the volume created with ff_mutex_create function.
*/
void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
CloseHandle(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
del_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err);
#elif OS_TYPE == 3 /* FreeRTOS */
vSemaphoreDelete(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDelete(Mutex[vol]);
#endif
}
/*------------------------------------------------------------------------*/
/* Request a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on enter file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0);
#elif OS_TYPE == 1 /* uITRON */
return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err));
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK);
#endif
}
/*------------------------------------------------------------------------*/
/* Release a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leave file functions to unlock the volume.
*/
void ff_mutex_give (
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
ReleaseMutex(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
unl_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OSMutexPost(Mutex[vol]);
#elif OS_TYPE == 3 /* FreeRTOS */
xSemaphoreGive(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexRelease(Mutex[vol]);
#endif
}
#endif /* FF_FS_REENTRANT */

@ -1,13 +1,13 @@
/*------------------------------------------------------------------------*/
/* Unicode handling functions for FatFs R0.13+ */
/* Unicode Handling Functions for FatFs R0.13 and Later */
/*------------------------------------------------------------------------*/
/* This module will occupy a huge memory in the .rodata section when the */
/* FatFs is configured for LFN with DBCS. If the system has a Unicode */
/* library for the code conversion, this module should be modified to use */
/* it to avoid silly memory consumption. */
/*------------------------------------------------------------------------*/
/* This module will occupy a huge memory in the .const section when the /
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
/ utilitiy for the code conversion, this module should be modified to use /
/ that function to avoid silly memory consumption. /
/-------------------------------------------------------------------------*/
/*
/ Copyright (C) 2014, ChaN, all right reserved.
/ Copyright (C) 2022, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -25,7 +25,7 @@
#include <fatfs/ff.h>
#if FF_USE_LFN /* This module will be blanked if non-LFN configuration */
#if FF_USE_LFN != 0 /* This module will be blanked if in non-LFN configuration */
#define MERGE2(a, b) a ## b
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
@ -15214,8 +15214,8 @@ static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* SBCS fixed code page */
/* OEM <==> Unicode Conversions for Static Code Page Configuration with */
/* SBCS Fixed Code Page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
@ -15225,7 +15225,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
)
{
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
const WCHAR* p = CVTBL(uc, FF_CODE_PAGE);
if (uni < 0x80) { /* ASCII? */
@ -15247,7 +15247,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
)
{
WCHAR c = 0;
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
const WCHAR* p = CVTBL(uc, FF_CODE_PAGE);
if (oem < 0x80) { /* ASCII? */
@ -15267,8 +15267,8 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for static code page configuration */
/* DBCS fixed code page */
/* OEM <==> Unicode Conversions for Static Code Page Configuration with */
/* DBCS Fixed Code Page */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE >= 900
@ -15277,7 +15277,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
const WCHAR* p;
WCHAR c = 0, uc;
UINT i = 0, n, li, hi;
@ -15313,7 +15313,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
const WCHAR* p;
WCHAR c = 0;
UINT i = 0, n, li, hi;
@ -15346,7 +15346,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
/*------------------------------------------------------------------------*/
/* OEM <==> Unicode conversions for dynamic code page configuration */
/* OEM <==> Unicode Conversions for Dynamic Code Page Configuration */
/*------------------------------------------------------------------------*/
#if FF_CODE_PAGE == 0
@ -15360,7 +15360,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
const WCHAR* p;
WCHAR c = 0, uc;
UINT i, n, li, hi;
@ -15412,7 +15412,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
WORD cp /* Code page for the conversion */
)
{
const WCHAR *p;
const WCHAR* p;
WCHAR c = 0;
UINT i, n, li, hi;
@ -15458,14 +15458,14 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */
/*------------------------------------------------------------------------*/
/* Unicode up-case conversion */
/* Unicode Up-case Conversion */
/*------------------------------------------------------------------------*/
DWORD ff_wtoupper ( /* Returns up-converted code point */
DWORD uni /* Unicode code point to be up-converted */
)
{
const WORD *p;
const WORD* p;
WORD uc, bc, nc, cmd;
static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */
/* Basic Latin */
@ -15590,4 +15590,4 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */
}
#endif /* #if FF_USE_LFN */
#endif /* #if FF_USE_LFN != 0 */

@ -139,7 +139,8 @@ static int sdio_switch_appmode_cmd55()
return -1;
}
enum acmd41_ret sdio_init_card_acmd41(uint8_t HCS){
enum acmd41_ret sdio_init_card_acmd41(uint8_t HCS)
{
uint32_t response;
int retry = 0x20;
if (sdio_switch_appmode_cmd55())
@ -184,12 +185,13 @@ static int sdio_send_csd_cmd9(uint16_t rca, uint32_t *response_buffer) {
* @param blklen Log2 of block length (9 in case of 512 byte block)
* @param buff Buffer to send
*/
static void sdio_write_buffer(uint32_t dlen, uint32_t log_blklen, const unsigned char *buff)
static int sdio_write_buffer(uint32_t dlen, uint32_t log_blklen, const unsigned char *buff)
{
uint32_t count;
int byte_count;
int byte_max;
uint32_t fifo;
uint32_t status_reg;
SDIO->DLEN = dlen;
@ -212,6 +214,8 @@ static void sdio_write_buffer(uint32_t dlen, uint32_t log_blklen, const unsigned
fifo |= (((uint32_t)*(buff++)) << 24) & 0xFF000000;
}
/* Wait as long as FIFO is full */
while (SDIO->STA & SDIO_STA_TXFIFOF);
@ -221,6 +225,14 @@ static void sdio_write_buffer(uint32_t dlen, uint32_t log_blklen, const unsigned
/* Wait for TX to complete */
while (SDIO->STA & SDIO_STA_TXACT);
status_reg = SDIO->STA;
if (status_reg & (SDIO_STA_DTIMEOUT | SDIO_STA_TXUNDERR | SDIO_STA_DCRCFAIL)) {
SDIO->DCTRL = 0UL;
return -1;
}
return 0;
}
static int sdio_send_write_block_cmd24(uint32_t addr)
@ -417,6 +429,26 @@ static int sdio_send_go_idle_cmd0() {
return 0;
}
static int sdio_send_stop_transmission_cmd12()
{
int res;
uint32_t response;
sdio_send_cmd(12, 0, SHORT_ANS);
res = sdio_get_response(12, SHORT_ANS, &response);
return res;
}
static int sdio_send_write_multiple_blocks_cmd25(uint32_t address)
{
int res;
uint32_t response;
sdio_send_cmd(25, address, SHORT_ANS);
res = sdio_get_response(25, SHORT_ANS, &response);
return res;
}
static enum cmd8_ret sdio_send_iface_condition_cmd8()
{
uint32_t response;
@ -606,11 +638,25 @@ DSTATUS sdio_initialize(){
return 0;
}
void sdio_stop_clk()
{
SDIO->POWER = 0UL;
}
DRESULT sdio_disk_read(BYTE *buff, DWORD sector, UINT count){
uint32_t addr;
uint32_t sdio_status;
uint32_t fifo;
uint32_t counter;
int err;
union sdio_status_conv status;
do {
err = sdio_check_status_register_cmd13(card_info.rca, &status.value);
if (err)
return RES_ERROR;
} while (status.statusstruct.CURRENT_STATE != CURRENT_STATE_TRAN);
addr = (card_info.type == SD_V2_HC ? (sector) : (sector*512));
for (; count > 0; count--) {
@ -633,7 +679,8 @@ DRESULT sdio_disk_read(BYTE *buff, DWORD sector, UINT count){
SDIO->DCTRL = (BLOCKSIZE<<4) | SDIO_DCTRL_DTDIR | /*SDIO_DCTRL_DMAEN |*/ SDIO_DCTRL_DTEN;
/* Init Transfer */
if (sdio_send_read_block_cmd17(addr)) {
err = sdio_send_read_block_cmd17(addr);
if (err) {
return RES_ERROR;
}
@ -703,38 +750,51 @@ DRESULT sdio_disk_write(const BYTE *buff, DWORD sector, UINT count)
union sdio_status_conv status;
uint32_t buff_offset = 0;
int ret;
UINT count_backup = count;
uint32_t retry_counter = 512;
if (sdio_check_write_protection())
return RES_WRPRT;
addr = (card_info.type == SD_V2_HC ? (sector) : (sector * 512));
while (count) {
do {
ret = sdio_check_status_register_cmd13(card_info.rca, &status.value);
} while (status.statusstruct.CURRENT_STATE == CURRENT_STATE_PRG ||
status.statusstruct.CURRENT_STATE == CURRENT_STATE_RCV ||
!ret);
ret = sdio_check_status_register_cmd13(card_info.rca, &status.value);
if (ret)
return RES_ERROR;
if (status.statusstruct.CURRENT_STATE == CURRENT_STATE_STBY) {
if (sdio_send_select_card_cmd7(card_info.rca))
return RES_ERROR;
}
do {
sdio_check_status_register_cmd13(card_info.rca, &status.value);
} while (status.statusstruct.READY_FOR_DATA != 1);
ret = sdio_send_write_block_cmd24(addr);
if (ret) {
if (status.statusstruct.CURRENT_STATE == CURRENT_STATE_STBY) {
if (sdio_send_select_card_cmd7(card_info.rca))
return RES_ERROR;
}
sdio_write_buffer(512, 9, &buff[buff_offset]);
buff_offset += 512;
addr += (card_info.type == SD_V2_HC ? 1 : 512);
count--;
}
return RES_OK;
while (1) {
ret = sdio_check_status_register_cmd13(card_info.rca, &status.value);
if (ret)
return RES_ERROR;
if (status.statusstruct.CURRENT_STATE == CURRENT_STATE_TRAN)
break;
if (--retry_counter == 0)
return RES_ERROR;
sdio_wait_ms(1);
}
if (count > 1)
ret = sdio_send_write_multiple_blocks_cmd25(addr);
else if (count == 1)
ret = sdio_send_write_block_cmd24(addr);
else
ret = RES_PARERR;
if (ret)
return RES_ERROR;
ret = 0;
ret = sdio_write_buffer((count * 512UL), 9, &buff[buff_offset]);
if (count_backup > 1)
(void)sdio_send_stop_transmission_cmd12();
return (ret ? RES_ERROR : RES_OK);
}

@ -21,7 +21,7 @@ DRESULT sdio_disk_ioctl(BYTE cmd, void* buff);
DWORD get_fattime();
int sdio_check_inserted();
void sdio_stop_clk();
//Defines for Card Status in struct _CardStatus
#define CURRENT_STATE_IDLE 0

@ -3,6 +3,8 @@
#include <stm32/stm32f4xx.h>
#define SDIO_CLOCK_FREQ 42000000UL
//General Definitions
//Blocksize: 512 = 2^9 => 9
#define BLOCKSIZE 9 //9
@ -12,11 +14,14 @@
//4 bit: 4
#define BUSWIDTH 4 //4
//Initial Transfer CLK (ca. 400kHz)
#define INITCLK 130 //120
#define INITCLK 140UL //120
//Working CLK (Maximum)
#define WORKCLK 50 //0
#define WORKCLK 30UL //0
//Data Timeout in CLK Cycles
#define DTIMEOUT 0x3000 //150
#define DATA_TIMEOUT_MS 250UL // 250
#define DTIMEOUT (((SDIO_CLOCK_FREQ / (WORKCLK+2))) * DATA_TIMEOUT_MS / 1000UL)
//DMA Stream used for TX and RX DMA2 Stream 3 or 6 possible
// Currently not used due to possible misalignment of the data buffer.
//#define DMASTREAM DMA2_Stream6

@ -0,0 +1,84 @@
/* Reflow Oven Controller
*
* Copyright (C) 2021 Mario Hüttel <mario.huettel@gmx.net>
*
* This file is part of the Reflow Oven Controller Project.
*
* The reflow oven controller is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The Reflow Oven Control Firmware is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the reflow oven controller project.
* If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup hw-version-detect
* @{
*/
#include <reflow-controller/hw-version-detect.h>
#include <stm-periph/rcc-manager.h>
#include <stm32/stm32f4xx.h>
#if HW_REV_DETECT_PIN_LOW > HW_REV_DETECT_PIN_HIGH
#error Configuration error for Hardware derection pins. Lowest position must be less than the highest pin position.
#endif
enum hw_revision get_pcb_hardware_version(void)
{
uint8_t current_pin;
uint16_t port_bitmask = 0U; /* Use uint16_t because a port can have 16 IOs max. */
const uint16_t highest_bit_mask = (1 << (HW_REV_DETECT_PIN_HIGH - HW_REV_DETECT_PIN_LOW));
static enum hw_revision revision = HW_REV_NOT_DETECTED;
/* If the revision has been previously detected,
* just return it and don't do the whole detection stuff
*/
if (revision != HW_REV_NOT_DETECTED)
return revision;
rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(HW_REV_DETECT_RCC_FIELD));
/* Setup the pins as input with pull up */
for (current_pin = HW_REV_DETECT_PIN_LOW; current_pin <= HW_REV_DETECT_PIN_HIGH; current_pin++) {
HW_REV_DETECT_GPIO->MODER &= MODER_DELETE(current_pin);
HW_REV_DETECT_GPIO->PUPDR &= PUPDR_DELETE(current_pin);
HW_REV_DETECT_GPIO->PUPDR |= PULLUP(current_pin);
}
/* Loop again and read in the pin mask.
* Because we use GND-Shorts on the pins to detect the version, the pins are read inverted.
*/
for (current_pin = HW_REV_DETECT_PIN_LOW; current_pin <= HW_REV_DETECT_PIN_HIGH; current_pin++) {
port_bitmask >>= 1;
port_bitmask |= (HW_REV_DETECT_GPIO->IDR & (1 << current_pin)) ? 0x0 : highest_bit_mask;
}
/* Resolve the read in bitmask to a hardware version */
switch (port_bitmask) {
case 0U:
revision = HW_REV_V1_2;
break;
case 1U:
revision = HW_REV_V1_3;
break;
case 2U:
revision = HW_REV_V1_3_1;
break;
default:
revision = HW_REV_ERROR;
}
rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(HW_REV_DETECT_RCC_FIELD));
return revision;
}
/** @} */

File diff suppressed because it is too large Load Diff

@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.14 /
/ FatFs - Generic FAT Filesystem module R0.15 /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/ Copyright (C) 2022, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -20,7 +20,7 @@
#ifndef FF_DEFINED
#define FF_DEFINED 86606 /* Revision ID */
#define FF_DEFINED 80286 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@ -35,10 +35,14 @@ extern "C" {
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Main development platform */
#if defined(_WIN32) /* Windows VC++ (for development only) */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#include <float.h>
#define isnan(v) _isnan(v)
#define isinf(v) (!_finite(v))
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
@ -48,6 +52,7 @@ typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
@ -58,53 +63,6 @@ typedef WORD WCHAR; /* UTF-16 character type */
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size and LBA variables */
#if FF_FS_EXFAT
@ -127,14 +85,57 @@ typedef DWORD LBA_t;
/* Type of path name strings on FatFs API (TCHAR) */
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Associated physical drive */
BYTE pdrv; /* Volume hosting physical drive */
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
BYTE wflag; /* win[] status (b0:dirty) */
BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
@ -147,9 +148,6 @@ typedef struct {
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
@ -163,10 +161,10 @@ typedef struct {
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD fsize; /* Number of sectors per FAT */
LBA_t volbase; /* Volume base sector */
LBA_t fatbase; /* FAT base sector */
LBA_t dirbase; /* Root directory base sector/cluster */
LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
LBA_t database; /* Data base sector */
#if FF_FS_EXFAT
LBA_t bitbase; /* Allocation bitmap base sector */
@ -181,7 +179,7 @@ typedef struct {
typedef struct {
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
WORD id; /* Hosting volume's mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
@ -250,7 +248,7 @@ typedef struct {
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
@ -298,8 +296,10 @@ typedef enum {
/*--------------------------------------------------------------*/
/* FatFs Module Application Interface */
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
@ -336,6 +336,8 @@ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
/* Some API fucntions are implemented as macro */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
@ -345,46 +347,47 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* Additional Functions */
/*--------------------------------------------------------------*/
/* RTC function */
/* RTC function (provided by user) */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
DWORD get_fattime (void); /* Get current time */
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
/* LFN support functions (defined in ffunicode.c) */
#if FF_USE_LFN >= 1
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
/* O/S dependent functions (samples available in ffsystem.c) */
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#if FF_FS_REENTRANT /* Sync functions */
int ff_mutex_create (int vol); /* Create a sync object */
void ff_mutex_delete (int vol); /* Delete a sync object */
int ff_mutex_take (int vol); /* Lock sync object */
void ff_mutex_give (int vol); /* Unlock sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* Flags and Offset Address */
/*--------------------------------------------------------------*/
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01

@ -1,8 +1,8 @@
/*---------------------------------------------------------------------------/
/ FatFs Functional Configurations
/ Configurations of FatFs Module
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 86606 /* Revision ID */
#define FFCONF_DEF 80286 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
@ -25,15 +25,7 @@
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 1
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
#define FF_USE_FIND 1
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
@ -64,6 +56,30 @@
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
#define FF_USE_STRFUNC 1
#define FF_PRINT_LLI 0
#define FF_PRINT_FLOAT 0
#define FF_STRF_ENCODE 0
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion.
/
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
/ makes f_printf() support floating point argument. These features want C99 or later.
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
/ to be read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
@ -137,20 +153,7 @@
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
#define FF_FS_RPATH 2
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
@ -175,7 +178,7 @@
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/ not defined, a user defined volume string table needs to be defined as:
/ not defined, a user defined volume string table is needed as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/
@ -187,14 +190,14 @@
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
/ function will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ harddisk, but a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
@ -205,8 +208,8 @@
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
#define FF_MIN_GPT 0x100000000
/* Minimum number of sectors to switch GPT format to create partition in f_mkfs and
#define FF_MIN_GPT 0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
@ -228,7 +231,7 @@
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 0
#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
@ -237,10 +240,10 @@
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2019
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
#define FF_NORTC_YEAR 2022
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
@ -250,7 +253,7 @@
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ option, and f_getfree() function at the first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
@ -272,26 +275,21 @@
/ lock control is independent of re-entrancy. */
/* #include <somertos.h> // O/S definitions */
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t HANDLE
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/ to the same volume is under control of this featuer.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
/ function, must be added to the project. Samples are available in ffsystem.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
*/

@ -30,10 +30,15 @@
#define CONCAT(x,y) x##y
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
#define wordsize_of(x) ((sizeof(x) / 4U) / ((sizeof(x) % 4U) ? 0U : 1U))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define ABS(a) ((a) < 0 ? (-1*(a)) : (a))
#define is_power_of_two(num) ((num) && !((num) & ((num) - 1)))
#define IN_SECTION(sec) __attribute__((section(#sec)))
#endif /* __HELPER_MACROS_H__ */

Some files were not shown because too many files have changed in this diff Show More