Browse Source

Init commit

- Import assignment 1 files and repo
 - Assignment 2 code
tags/v2.0
commit
0f28637aed
18 changed files with 1242 additions and 0 deletions
  1. +18
    -0
      .gitignore
  2. +9
    -0
      .gitmodules
  3. +121
    -0
      assignment_1/main.c
  4. +1
    -0
      assignment_1/report/config
  5. BIN
      assignment_1/report/images/RAM_layout.png
  6. +337
    -0
      assignment_1/report/images/RAM_layout.svg
  7. +1
    -0
      assignment_1/report/images/Untitled Diagram.drawio
  8. BIN
      assignment_1/report/images/isPalindrome.png
  9. BIN
      assignment_1/report/report.pdf
  10. +119
    -0
      assignment_1/report/report.tex
  11. +1
    -0
      assignment_2/Libraries/STM32CubeF4
  12. +1
    -0
      assignment_2/report/config
  13. BIN
      assignment_2/report/images/experiment-1.png
  14. BIN
      assignment_2/report/images/experiment-2.png
  15. +289
    -0
      assignment_2/src/NUCLEO_F401RE.c
  16. +137
    -0
      assignment_2/src/NUCLEO_F401RE.h
  17. +63
    -0
      assignment_2/src/assign2_impl.h
  18. +145
    -0
      assignment_2/src/main.c

+ 18
- 0
.gitignore View File

@@ -0,0 +1,18 @@
# General
doc/
hex/
micro2019/
deliver/

# Eclipse-Atollic related
.project
.cproject
.settings/
*.ld
Debug/
Release/

# Keil related
Keil/
*.gz
*.zip

+ 9
- 0
.gitmodules View File

@@ -0,0 +1,9 @@
[submodule "assignment_1/report/config"]
path = assignment_1/report/config
url = https://git.hoo2.net/hoo2/LaTeX_confing.git
[submodule "assignment_2/report/config"]
path = assignment_2/report/config
url = https://git.hoo2.net/hoo2/LaTeX_confing.git
[submodule "assignment_2/Libraries/STM32CubeF4"]
path = assignment_2/Libraries/STM32CubeF4
url = https://github.com/hoo2/STM32CubeF4.git

+ 121
- 0
assignment_1/main.c View File

@@ -0,0 +1,121 @@
/*!
* @file
* main.c
* @brief
* A palindrome implementation and testing application
* for A.U.TH. Microprocessors and peripherals Lab.
*
* Created on: May 1, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/
#include <stdint.h>

/*!
* The RAM address to use for palindrome result.
* @note:
* Select a RAM location above `__initial_sp`. See your startup_xx.s for details.
* Keil's RAM layout is:
*
* RAM: |<-Heap_Size-><-Stack_Size->|<- WASTED RAM SPACE ->|
* ^ ^ ^
* | | |
* Start:0x20000000 __initial_sp End of RAM
*
*/
#define RESULT 0x20001000

/*!
* String length calculation.
* @arg src{R0} Pointer to string
* @return {R0} String length, -1 if src is NULL
*/
__asm uint32_t strLength (const char* src) {
// R0: length, return value
// R1: src
// R2: v = *src
MOV R1, R0 // Get variable
CMP R1, #0 // if (src{R1} == NULL)
MOVEQ R0, #-1 // return -1;
BXEQ LR
MOV R0, #0 // length{R0} =0;
len_loop // do {
LDRB R2, [R1], #1 // v{R2} = *src++;
CMP R2, #0 // if(v)
ADDNE R0, R0, #1 // ++length{R0};
BNE len_loop // } while (v);
BX LR // return length;
}

/*!
* A string palindrome predicate.
* @note
* We use a simple O(n), no stack algorithm.
* @note
* This function also writes to RAM address @ref RESULT the return value (which is nasty).
* @arg src{R0} Pointer to string
* @return {R0} True if palindrome, false if not or src is NULL pointer
* @note
* We consider an empty string "" to be a palindrome, as we can see it the same way both
* from the front and the back.
*/
__asm uint32_t isPalindrome (const char* src) {
// R0: src[]
// R1: i
// R2: j
// R3: v1 = src[i]
// R4: v2 = src[j]
PUSH {R4, LR}
CMP R0, #0 // if (src{R0} == NULL)
BEQ pal_false // return false;
MOV R4, R0 // save R0
BL strLength // j{R2} = strLength(src) - 1
SUB R2, R0, #1
MOV R0, R4 // src{R0}
MOV R1, #0 // i{R1} =0;

pal_loop
CMP R1, R2 // while (i<j) {
BGE pal_true
LDRB R3, [R0, R1] // v1 = *src[i];
LDRB R4, [R0, R2] // v2 = *src[j];
CMP R3, R4 // if (v1 == v2) {
ADDEQ R1, R1, #1 // ++i;
SUBEQ R2, R2, #1 // --j;
BEQ pal_loop // // goto loop;
pal_false // } else
MOV R0, #0 // return *RESULT = 0;
LDR R1, =RESULT
STRB R0, [R1]
POP {R4, PC}
// }
pal_true
MOV R0, #1 // return *RESULT = 1;
LDR R1, =RESULT
STRB R0, [R1]
POP {R4, PC}
}

/*!
* Main routine.
* @note
* This routine plays the role of debuging-mode unit testing.
*/
int main(void) {
const char *s1 = "hello world!"; // Not a palindrome
const char *s2 = "aibohphobia"; // Aibophobia def= "Irational fear of palindromes", palindrome.
const char *s3 = ""; // Empty string, palindrome.
const char *s4 = 0; // NULL pointer. Out of scope, not palindrome

uint32_t res1 = isPalindrome (s1); // Test case 1
uint32_t res2 = isPalindrome (s2); // Test case 2
uint32_t res3 = isPalindrome (s3); // Test case 3
uint32_t res4 = isPalindrome (s4); // Test case 4
while (1); // Trap forever
//return 0; //!< comment out return, to suppress "statement is unreachable" warning.
//!^ @note:
//! **Weird** Keil's way for "statement is unreachable", suppresion.

}

+ 1
- 0
assignment_1/report/config

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

BIN
assignment_1/report/images/RAM_layout.png View File

Before After
Width: 1138  |  Height: 1757  |  Size: 47 KiB

+ 337
- 0
assignment_1/report/images/RAM_layout.svg View File

@@ -0,0 +1,337 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg8"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="RAM_layout.svg"
inkscape:export-filename="/home/hoo2/Software/AUTH/Micro/assignement_1/report/images/RAM_layout.svg.png"
inkscape:export-xdpi="600"
inkscape:export-ydpi="600">
<defs
id="defs2">
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4546"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(0.6) translate(0,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4522"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mstart-4"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path4546-8"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mstart-4-5"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path4546-8-2"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mstart-6"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path4546-4"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mstart-6-1"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path4546-4-4"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6)" />
</marker>
<marker
inkscape:stockid="Arrow2Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Mstart-6-1-1"
style="overflow:visible"
inkscape:isstock="true">
<path
inkscape:connector-curvature="0"
id="path4546-4-4-7"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="scale(0.6)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="162.42672"
inkscape:cy="791.2836"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-page="false"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g6178"
inkscape:export-xdpi="600"
inkscape:export-ydpi="600">
<rect
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
y="45.689461"
x="21.946363"
height="73.879112"
width="23.566633"
id="rect10" />
<g
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
id="g5613">
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)"
d="m 47.634183,46.875398 h 5.565965"
id="path4520"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4836"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
transform="matrix(0.26458333,0,0,0.26458333,2.286756,-2.1733631)"><flowRegion
id="flowRegion4838"><rect
id="rect4840"
width="107.85714"
height="61.07143"
x="197.14285"
y="153.23396" /></flowRegion><flowPara
id="flowPara4842"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial">End of RAM</flowPara></flowRoot> </g>
<g
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
id="g5613-9"
transform="translate(0,71.746594)">
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart-6)"
d="m 47.634183,46.875398 h 5.565965"
id="path4520-9"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4836-0"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
transform="matrix(0.26458333,0,0,0.26458333,2.286756,-2.1733631)"><flowRegion
id="flowRegion4838-8"><rect
id="rect4840-9"
width="107.85714"
height="61.07143"
x="197.14285"
y="153.23396" /></flowRegion><flowPara
id="flowPara4842-3"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial">0x20000000</flowPara></flowRoot> </g>
<path
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:connector-curvature="0"
id="path5765"
d="M 21.878451,112.45039 H 45.302185"
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<flowRoot
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
transform="matrix(0.26458333,0,0,0.26458333,-21.166366,67.028655)"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
id="flowRoot4836-0-6-7"
xml:space="preserve"><flowRegion
id="flowRegion4838-8-7-1"><rect
y="153.23396"
x="197.14285"
height="66.627274"
width="98.260719"
id="rect4840-9-7-2" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial"
id="flowPara4842-3-3-2">data</flowPara></flowRoot> <path
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:connector-curvature="0"
id="path5765-1"
d="M 21.949511,106.23637 H 45.302186"
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<flowRoot
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
transform="matrix(0.26458333,0,0,0.26458333,-20.665449,60.530144)"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
id="flowRoot4836-0-6-7-5"
xml:space="preserve"><flowRegion
id="flowRegion4838-8-7-1-0"><rect
y="153.23396"
x="197.14285"
height="66.627274"
width="98.260719"
id="rect4840-9-7-2-9" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial"
id="flowPara4842-3-3-2-0">bss</flowPara></flowRoot> <flowRoot
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
transform="matrix(0.26458333,0,0,0.26458333,-25.394187,54.279243)"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
id="flowRoot4836-0-6-7-5-3"
xml:space="preserve"><flowRegion
id="flowRegion4838-8-7-1-0-7"><rect
y="153.23396"
x="197.14285"
height="66.627274"
width="98.260719"
id="rect4840-9-7-2-9-4" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial"
id="flowPara4842-3-3-2-0-1">Heap_Size</flowPara></flowRoot> <flowRoot
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
transform="matrix(0.26458333,0,0,0.26458333,-25.498918,39.763973)"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
id="flowRoot4836-0-6-7-5-3-1"
xml:space="preserve"><flowRegion
id="flowRegion4838-8-7-1-0-7-3"><rect
y="153.23396"
x="197.14285"
height="66.627274"
width="98.260719"
id="rect4840-9-7-2-9-4-0" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial"
id="flowPara4842-3-3-2-0-1-3">Stack_Size</flowPara></flowRoot> <path
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:connector-curvature="0"
id="path5765-1-2"
d="M 21.949511,86.278273 H 45.302186"
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<g
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
id="g5915-5"
transform="translate(0,-17.859523)">
<path
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart-6-1-1)"
d="m 47.634183,105.0463 h 5.565965"
id="path4520-9-9-6"
inkscape:connector-curvature="0" />
<flowRoot
xml:space="preserve"
id="flowRoot4836-0-6-5"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
transform="matrix(0.26458333,0,0,0.26458333,2.286756,55.997509)"><flowRegion
id="flowRegion4838-8-7-4"><rect
id="rect4840-9-7-22"
width="107.85714"
height="61.07143"
x="197.14285"
y="153.23396" /></flowRegion><flowPara
id="flowPara4842-3-3-1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial">__initial_sp</flowPara></flowRoot> </g>
<flowRoot
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
transform="matrix(0.26458333,0,0,0.26458333,-21.392364,17.854437)"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
id="flowRoot4836-0-6-7-5-3-7"
xml:space="preserve"><flowRegion
id="flowRegion4838-8-7-1-0-7-2"><rect
y="153.23396"
x="197.14285"
height="66.627274"
width="98.260719"
id="rect4840-9-7-2-9-4-4" /></flowRegion><flowPara
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;font-family:Arial;-inkscape-font-specification:Arial"
id="flowPara4842-3-3-2-0-1-1">Free</flowPara></flowRoot> </g>
</g>
</svg>

+ 1
- 0
assignment_1/report/images/Untitled Diagram.drawio View File

@@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2020-05-03T15:08:08.336Z" agent="5.0 (X11)" etag="FJrRoutRW1H6xKy9lX6Y" version="13.0.6" type="device"><diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">7Vtbc+I2FP41zLSdYceSLyGPIZfdtjTT5to8KlgxzgqLlQWB/vpKtnyTDHgTwCQhM5lYx5IsnXO+7xxd0rFPx/OvDE1Gf1Efkw60/HnHPutACEDPFX+kZJFKPFsJAhb6qlIhuA7/w0poKek09HFcqcgpJTycVIVDGkV4yCsyxBh9qVZ7oqT61QkKsCG4HiJiSu9Dn49SaQ8eFfJvOAxG2ZeBd5y+GaOssppJPEI+fSmJ7POOfcoo5enTeH6KiVReppf73xf3ZPDd+/rHP/EPdNv/8+byrpt2dvEzTfIpMBzxV3c9H0b88f7h7vLqidyh2zk9WQy6wFFz44tMYdgX+lNFyviIBjRC5LyQ9hmdRj6W3VqiVNQZUDoRQiCEz5jzhXIGNOVUiEZ8TNRbPA/5v7L5F1eVHkpvzuaq56SwyAoRZ4tSI1l8KL8rmiWlrF06PzkpzR/WKFPVi+mUDfGKep7yacQCvLI/mLuMwBqmYyxGKRoyTBAPZ9XRIeX0QV6vMKx4ULb9CTs7Vpt2BiUrFzZfY2dQsXJh9P2xcz2iem+0s2r6Nw3FuKGliNjNLKho2O1Z1S7SgalWhbecMIYWpWoTWSFe8R1Y/U7GfhcN62fhoXDWdASF6+Y6aeTNq2wxQ2Sq9BmzoRDIZ1m0Lm8HA8Ph2YiOH6dCD/2XUcjx9QQlBn8Rca/qtjnRS796ohG/QOOQyAl+w2SGeThE6oXyfIFtu49IGESiMBT+hpnshjP6PQ86Scfik2EUiJJXlG4SMHWd3IebuuwMM47nJX8ynS5761aNBI5V+aWIiCBzsFEpGnqak22Mj0CrfPQR4g7Ikql1hPRWPmpq55WjLEG1Az0ixtv3w5l4DHiiq1QkISVzPKRm7v2YyuSqX8AuF2VNZ0DhXqhMcIDblyOSIvcs61UMPO24+jEh3tAQoDmE5zVD0Kkp92ywnp504gkIimPldTWcUyazbRGMDY++uBWKcYBrUozlmhTjbo1i7APFvJFiYNOcp1WKgQbFhDkgrQyBj0xHegn8zwWAORvgKOCjXwSUf5UTqyeLD4ZfPUGAvbYTBPuA3ubordWgZYJ3eTLd1rrUMrDbx0EYmbYnJJzEeD24lnh+U70uR8iRlkKDGoRYNQjZXnxz20TIq5b0VqetJf3ysNVk62ZX8a12lLB3YMKN27le00dt2rnRSinJbKCHxpL2VGYiFxvNspR3sgGyffZ2rIbsre+ybQ7VreY3H4G9e00XJ60mONA7sPeO7Lyrja5Voyyx9wx0ku3oGTwQcWmjSNsmqtuJBrtcaMJW0+gqQK2VAN16mvRWoqw/IYLaCZGtm3JDJ1dOz639zqZOolboTMvahKVkoqZvPHW7zyYT7HTjaPN4djwtsTo2t33dXa6K7aNW4fyavKq9g+4VcbRBwLWdNgMuMCMuw3zKROA7EeIra9Ue8G9X59e3g5tylQ8GTFs/l687j4E1yHS2FmjNvb4HHBuKF3rgWhKUaPCUEipymbOIRhKyTyEhmshIe6RWRYZETtSLcej7ZNkeYpUDtmUWqC9EoZn/1O2zw61Zxdx2+HxWcTSwuDXbAzu1ir1HSen7XDVm9zv3PIplw1wfxcD6KAYMp3nvUQxo6aVbQ5e7jWK2GcUu6Sejy/xudxbEemZusVu6NIPYpzOKrWUWrtt2DHMMo9QcaJxHfsPTi707AvZaPwK263YfSiq2MsctLq0R/MTNK2z6cmgufi0xF6uhbd4OrWRc+wksLTnMY9K6uzHbQ5a59K1B1h1iIXoUyoNWV6YSOAhjwV7x6vuPJVF3+c/yW1VrexUpTZLaJDe2m7YBaZuweQuYtlh6NGq2sNMWs6V3vswmjmoCm+vjEwMH2g2BA7aGHOew2pWX+/TLurDt9a5j5gqfLoHTs2q4vQROFIt/W0yPQop//rTP/wc=</diagram></mxfile>

BIN
assignment_1/report/images/isPalindrome.png View File

Before After
Width: 379  |  Height: 552  |  Size: 28 KiB

BIN
assignment_1/report/report.pdf View File


+ 119
- 0
assignment_1/report/report.tex View File

@@ -0,0 +1,119 @@
%
% Report description
%
% authors:
% Χρήστος Χουτουρίδης ΑΕΜ 8997
% cchoutou@ece.auth.gr


% Document configuration
\newcommand{\ClassName}{Μικροεπεξεργαστές και Περιφερειακά}
\newcommand{\DocTitle}{1η Εργασία}
\newcommand{\InstructorName}{Παπαευσταθίου Ιωάννης}
\newcommand{\InstructorMail}{ygp@ece.auth.gr}
\newcommand{\CurrentDate}{\today}

\input{config/AuthReportConfig.tex}

%\renewcommand{\AuthorName}{Χρήστος Χουτουρίδης}
%\renewcommand{\AuthorMail}{cchoutou@ece.auth.gr}
%\renewcommand{\AuthorAEM}{8997}

\setFancyHeadLR{\ClassName}{\DocTitle}
%\setFancyHeadLERO{\ClassName}{\DocTitle}

% Document
% =================
\begin{document}

\FirstPage

%\tableofcontents
%\listoffigures
%\listoftables

\section{Εισαγωγή}
Στην παρούσα εργασία το ζητούμενο είναι η υλοποίηση μιας ρουτίνας σε γλώσσα \eng{assemblly ARM,} που να ελέγχει αν ένα αλφαριθμητικό είναι παλίνδρομο, αλλά και η ενσωμάτωση αυτής σε ένα πρόγραμμα σε γλώσσα \eng{C.}
Για την εργασία χρησιμοποιήσαμε το εργαλείο \eng{Keil uVision} και μιας και δεν αντιμετωπίσαμε κάποιο ιδιαίτερο πρόβλημα, η αναφορά αυτή θα αναλωθεί κυρίως στην υλοποίηση και τον έλεγχο του προγράμματος.
Τον κώδικα της εργασίας αλλά και της παρούσας αναφοράς μπορείτε να βρείτε ακόμα στο προσωπικό \href{https://git.hoo2.net/hoo2/micro_assign_1}{αποθετήριο της εργασίας}.

\section{Παραδοτέα}
Στο παραδοτέο \eng{.zip} αρχείο μπορείτε να βρείτε:
\begin{itemize}
\item Το αρχείο \textbf{\eng{main.c}} που περιέχει όλο τον ζητούμενο κώδικα της εργασίας.
\item Το αρχείο \textbf{\eng{report.pdf}} που είναι παρούσα αναφορά.
\item Τον κατάλογο \textbf{\eng{Keil}} που περιέχει το \eng{project} στο \eng{Keil} που χρησιμοποιήσαμε.\\
Στο \eng{project} αυτό περιέχονται επιπλέων οι ρυθμίσεις καθώς και τα αρχεία από τη βιβλιοθήκη \eng{CMSIS} που χρειάστηκαν για την ορθή αρχικοποίηση και αλληλεπίδραση με τον επεξεργαστή.
\end{itemize}

\section{Υλοποίηση}
Η υλοποίηση του ελέγχου αν ένα αλφαριθμητικό είναι παλίνδρομο έγινε σε δύο συναρτήσεις, την \eng{\textit{isPalindrome()}} και την \eng{\textit{strLength()},} που λειτουργεί ως βοηθητική συνάρτηση.
Οι συναρτήσεις αυτές είναι υλοποιημένες σε γλώσσα \eng{assemblly} αλλά η κλήση τους από το κυρίως πρόγραμμα δεν διαφέρει καθόλου από την κλήση μιας οποιασδήποτε άλλης συνάρτησης σε γλώσσα \eng{C.}
Για τον λόγο αυτό δεν θα ασχοληθούμε περαιτέρω με το κύριο πρόγραμμα (συνάρτηση \eng{main).}

\subsection{Συνάρτηση \eng{\textit{isPalindrome()}}}
\WrapFigure{0.42}{r}{fig:isPalindrome}{isPalindrome.png}{Διάγραμμα ροής της συνάρτησης \eng{\textit{isPalindrome()}}}
Για τη συνάρτηση αυτή χρησιμοποιήσαμε ένα απλό \eng{O(n)} σειριακό αλγόριθμο, ο οποίος απαιτεί το μήκος του αλφαριθμητικού εισόδου προτού εισέλθει στον κύριο βρόχο επανάληψης.
Για να βρούμε το μήκος χρησιμοποιούμε μια ξεχωριστή συνάρτηση.
Αυτή την υλοποιήσαμε από την αρχή ώστε να μην χρειαστεί να χρησιμοποιηθεί η συνάρτηση \eng{\textit{strlen()}} της \eng{\textit{libc}.}

\par Όπως φαίνεται και στο διάγραμμα του σχήματος \ref{fig:isPalindrome}, στον κύριο βρόχο της συνάρτησης χρησιμοποιούμε δύο απαριθμητές \eng{i, j} χρησιμοποιώντας τους καταχωρητές \eng {R1, R2} αντίστοιχα και ένα δείκτη στη διεύθυνση του αλφαριθμητικού χρησιμοποιώντας τον καταχωρητή \eng{R0.}
Ο ένας δείκτης εκκινεί από την αρχή του αλφαριθμητικού και ο άλλος από το τέλος.
Σε κάθε επανάληψη διαβάζουμε από το αλφαριθμητικό τα \eng{src[i]} και \eng{src[j]} και ελέγχουμε αν είναι ίσα.
Αν δεν είναι τότε το αλφαριθμητικό δεν είναι παλίνδρομο.
Αν είναι τότε μεταθέτουμε το \eng{i} μία θέση δεξιά και το \eng{j} μία θέση αριστερά και επανεκτελούμε τον βρόχο.
Ο βρόχος συνεχίζει όσο το \eng{i} είναι μικρότερο από το \eng{j.}
Αν το \eng{i} γίνει ίσο ή μεγαλύτερο από το \eng{j,} τότε ο βρόχος τερματίζει.
Σε αυτή την περίπτωση το αλφαριθμητικό είναι παλίνδρομο.

\par Αν το αλφαριθμητικό έχει μηδενικό μήκος, τότε ο βρόχος δεν θα εκτελεστεί ούτε μία φορά και η συνάρτηση θα επιστρέψει ότι το αλφαριθμητικό είναι παλίνδρομο.
Έχουμε κάνει δηλαδή την θεώρηση ότι \textbf{\textit{τα μηδενικού μήκους αλφαριθμητικά είναι παλίνδρομα}}, καθώς είναι τα ίδια είτε τα κοιτάς από μπροστά είτε τα κοιτάς από πίσω.
Στην περίπτωση που η είσοδος της συνάρτησης είναι εκτός πεδίου ορισμού, δηλαδή ο \eng{NULL pointer,} τότε η συνάρτηση επιστρέφει ψευδές αποτέλεσμα.
Ο έλεγχος του δείκτη εισόδου γίνεται στην αρχή της συνάρτησης πριν καν γίνει η κλήση για το μήκος, προστατεύοντας έτσι κάποιο \eng{exception} από το \eng{dereference} του δείκτη στην εντολή \eng{LDR.}

\subsection{Συνάρτηση \eng{\textit{strLength()}}}
Η υλοποίηση της \eng{\textit{strLength()}} είναι επίσης ένας σειριακός αλγόριθμος.
Εδώ χρησιμοποιούμε τον καταχωρητή \eng{R1} ώς δείκτη στο αλφαριθμητικό και με αυτόν κάνουμε ανάγνωση της μνήμης, αυξάνοντάς τον ταυτόχρονα μετά από κάθε ανάγνωση.
Η συνάρτηση επιστρέφει τον αριθμό των αναγνώσεων που χρειάστηκαν μέχρι να λάβουμε το νούμερο '0', το οποίο σηματοδοτεί το τέλος του αλφαριθμητικού.

\par Ομοίως και εδώ κάνουμε έλεγχο της εισόδου ώστε αυτή να μην είναι ο \eng{NULL pointer.}
Φυσικά αυτό στη δική μας περίπτωση δεν είναι απαραίτητο καθώς υπάρχει ο αντίστοιχος έλεγχος στην \eng{\textit{isPalindrome()}} προτού την κλήση.
Παρόλα αυτά το θεωρούμε καλή πρακτική, καθώς αυτό καθιστά την \eng{\textit{strLength()}} πιο ολοκληρωμένη συνάρτηση και μια χρήση της στο μέλλον δεν θα προκαλέσει εκπλήξεις.

\subsection{Εγγραφή του αποτελέσματος στη μνήμη}
\WrapFigure{0.23}{l}{fig:ram_layout}{RAM_layout.png}{Διάταξη της μνήμης}
Η συνάρτηση \eng{\textit{isPalindrome()}} αφού εκτελεστεί, επιστρέφει μια τιμή στον \eng{caller.}
Στα ζητούμενα όμως της εργασίας ήταν η συνάρτηση αυτή να γράφει το αποτέλεσμα και σε μία θέση μνήμης της επιλογής μας.
Αυτό υπό κανονικές συνθήκες είναι ανεπίτρεπτο.
Για τα πλαίσια όμως της εργασίας προσπαθήσαμε να ανταπεξέλθουμε με ένα σχετικά ασφαλή τρόπο.

\par Όπως φαίνεται και στο σχήμα \ref{fig:ram_layout}, o συνδέτης \eng{(linker)} του εργαλείου \eng{keil} δεν τοποθετεί τον \eng{SP} στο τέλος της μνήμης.
Για την ακρίβεια, χρησιμοποιώντας δύο τιμές από το \eng{configuration} του \eng{startup} αρχείου για το μέγεθος του σωρού και της στοίβας, υπολογίζει τη τιμή \eng{\textit{\textbf{\_\_initial\_sp}}.}
Αυτή την τιμή χρησιμοποιεί έπειτα σαν πρώτο όρισμα στο \eng{vector table} και άρα αυτή την τιμή έχει ο \eng{SP} κατά την εκκίνηση.

\par Έχοντας αυτό σαν δεδομένο μπορούμε να επιλέξουμε μια τιμή στην ελεύθερη περιοχή, έχοντας πάντα στο μυαλό μας ότι αλλάζοντας τα δεδομένα του προγράμματος η τιμή αυτή μπορεί να αλλάξει.
Στη δική μας περίπτωση η επιλεγμένη τιμή ήταν το \eng{\textbf{0x20001000}.}
Φυσικά αυτή η τιμή μπορεί να αλλάξει εύκολα αλλάζοντας απλώς την τιμή από το \eng{\textbf{\#define RESULT}.}
Μάλιστα αυτό είναι και κάτι που προτρέπουμε κάνει ο οποιονδήποτε θέλει να τρέξει τον κώδικά μας, ώστε να βεβαιωθεί πως η τιμή αυτή είναι στην ασφαλή ζώνη.


\section{Έλεγχος}
Για τον έλεγχο της ορθότητας του κώδικα χρησιμοποιήσαμε τον \eng{debuger} του εργαλείου κάνοντας ταυτόχρονη χρήση του \eng{simulator.}
Καθώς η εκφώνηση ανέφερε την δημιουργία μιας \eng{main,} θεωρήσαμε ότι είναι ευκαιρία να χρησιμοποιήσουμε την \eng{main} για να επιτύχουμε ένα είδους \eng{debug-mode unit testing.}
Έτσι στο εσωτερικό της δηλώσαμε αλφαριθμητικά για έλεγχο και για αυτά καλέσαμε την \eng{\textit{isPalindrome()}.}
Έπειτα εκτελώντας τον \eng{debuger} καταφέραμε να κάνουμε την όποια αποσφαλμάτωση που χρειάστηκε.

\section{Επίλογος}
Θεωρούμε ότι η παρούσα εργασία ήταν μια καλή πρώτη επαφή με την μίξη κώδικα \eng{C - assemblly,} καθώς και των όποιων απαιτήσεων από μεριάς \eng{assemblly} ώστε αυτή να είναι συμβατή με το πρότυπο που ακολουθεί ο \eng{compiler (AAPCS).}
Η μόνη παραφωνία σε αυτή τη συνεργασία ήταν η επιλογή μιας ελεύθερης θέσης μνήμης για την επιστροφή του αποτελέσματος.
Αυτό γιατί μέχρι τη σύνταξη του παρόντος δεν βρήκαμε τρόπο να διαβάσουμε από διαφορετικό αρχείο(πχ το \eng{main.c}) την τιμή \eng{\_\_initial\_sp,} ώστε η επιλογή της θέσης να αυτοματοποιηθεί.

% References
% ============================
%\begin{thebibliography}{100}
%
%\bibitem{item}item...

%\end{thebibliography}

\end{document}

+ 1
- 0
assignment_2/Libraries/STM32CubeF4

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

+ 1
- 0
assignment_2/report/config

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

BIN
assignment_2/report/images/experiment-1.png View File

Before After
Width: 473  |  Height: 280  |  Size: 9.8 KiB

BIN
assignment_2/report/images/experiment-2.png View File

Before After
Width: 473  |  Height: 272  |  Size: 9.7 KiB

+ 289
- 0
assignment_2/src/NUCLEO_F401RE.c View File

@@ -0,0 +1,289 @@
/*!
* \file
* NUCLEO_F401RE.h
* \brief
* Nucleo F401RE port file. This file contain the implementation of driver
* calls for F401RE board.
*
* Created on: May 23, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/
#include "NUCLEO_F401RE.h"

/*
* =============== System ===============
*/

static clock_t volatile __ticks; //!< CPU time
static time_t volatile __now; //!< Time in UNIX seconds past 1-Jan-70
static clock_t volatile __sys_freq; //!< The CPU's time frequency (SysTick freq)

/*!
* \brief
* This is the SysTick ISR, micro-system time base service for CPU time.
* \note
* This service implements the SysTick callback function in order
* to provide micro system - os like functionalities to an application
* without RTOS
*/
void SysTick_Handler(void) {
// Time
++__ticks;
if ( !(__ticks % __sys_freq ) )
++__now; // Do not update __now when we have external time system
}


/*!
* \brief This function configures the source of the time base.
* The time source is configured to have 1ms time base with a dedicated
* Tick interrupt priority.
* \param sf Tick interrupt frequency.
* \retval HAL status
*/
__weak HAL_StatusTypeDef HAL_SysTick_Init(clock_t sf) {
SystemCoreClockUpdate ();

/* Configure the SysTick to have interrupt in sf time basis */
if (SysTick_Config (SystemCoreClock/sf) != 0)
return HAL_ERROR;
__sys_freq = sf;

/*Configure the SysTick IRQ priority */
NVIC_SetPriority (SysTick_IRQn, 3U);

/* Return function status */
return HAL_OK;
}

/*!
* Select the system frequency without calling the Setting functionality
* \param sf The desired value
* \return The desired value (enable chaining)
*/
__INLINE clock_t HAL_SelectSysTickFreq (clock_t sf){
return __sys_freq =sf;
}

/*!
* \brief Get the __sys_freq.
*/
__INLINE clock_t HAL_GetSysTickFreq (void){
return __sys_freq;
}


/*!
* \brief Reconfigure the SysTick and update __sys_freq
* \param sf Tick interrupt frequency (CPU time)
* \return status of the operation
* \arg 0 Success
* \arg 1 Fail
*/
int HAL_SetSysTickFreq (clock_t sf) {
/*Configure the SysTick to have interrupt in sf time basis*/
if (__sys_freq != sf) {
// Time base configuration
SystemCoreClockUpdate ();
if (SysTick_Config ( (SystemCoreClock>>3)/sf) != 0)
return 1;
else {
__sys_freq = sf;
return 0;
}
}
return 0;
}

// Take over control of SysTick from HAL library

//! disable HAL_InitTick implementation
HAL_StatusTypeDef
HAL_InitTick(uint32_t TickPriority) { return HAL_OK; }

//! Chain GetTick to our implementation
uint32_t HAL_GetTick(void) { return clock(); }

/*!
* \brief This function provides minimum delay (in CPU time) based
* on variable incremented.
* \param Delay specifies the delay time length, in CPU time.
* \note
* uint32_t is implicitly convertible to clock_t and vice versa.
*/
void HAL_Delay(uint32_t Delay) {
uint32_t tickstart = clock();

while((clock() - tickstart) < Delay)
;
}

/*
* ======== OS like Functionalities ============
*/


//! SysTick frequency getter
__INLINE clock_t get_freq (void) {
return __sys_freq;
}

//! SysTick frequency setter
//! \return True on failure
int set_freq (clock_t sf) {
return HAL_SetSysTickFreq (sf);
}

/*!
* \brief
* determines the processor time.
* \return
* the implementation's best approximation to the processor time
* used by the program since program invocation. The time in
* seconds is the value returned divided by the value of the macro
* CLK_TCK or CLOCKS_PER_SEC
*/
__INLINE clock_t clock (void) {
return (clock_t) __ticks;
}

/*!
* \brief
* Set the processor time used.
* \param c The new CPU time value
* \return
* The implementation's best approximation to the processor time
* used by the program since program invocation. The time in
* seconds is the value returned divided by the value of the macro
* CLK_TCK or CLOCKS_PER_SEC
*/
clock_t setclock (clock_t c) {
return __ticks = c;
}

/*!
* \brief
* determines the current calendar time. The encoding of the value is
* unspecified.
* \return
* The implementations best approximation to the current calendar
* time. If timer is not a null pointer, the return value
* is also assigned to the object it points to.
*/
time_t time (time_t *timer) {
if (timer)
*timer = (time_t)__now;
return (time_t)__now;
}

/*!
* \brief
* Sets the system's idea of the time and date. The time,
* pointed to by t, is measured in seconds since the Epoch, 1970-01-01
* 00:00:00 +0000 (UTC).
* \param t Pointer to new system's time and date.
* \return On success, zero is returned. On error, -1 is returned
*/
int settime (const time_t *t) {
if (t) {
__now = *t;
return 0;
}
else
return -1;
}


/*
* ============== Cycle count ==============
*/
/*!
* Initialize CPU cycle measurement functionality based on DBG
* \return The status of the operation
* \arg LLD_OK Success
* \arg LLD_ERROR Failure
*/
LLD_Status_en CYCLE_Init (void) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // enable trace
//DWT->LAR = 0xC5ACCE55; // <-- added unlock access to DWT (ITM, etc.)registers
DWT->CYCCNT = 0; // clear DWT cycle counter
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // enable DWT cycle counter
return LLD_OK;
}

//! CPU cycle getter
__INLINE clock_t CYCLE_Get (void) {
return (clock_t)DWT->CYCCNT;
}

/*
* =============== Digital I/O ===============
* BTN -- PC13
* LED -- PA5 (SB42 is in place) [SB29: PB13]
*/

//! Helper digital input pin getter
static __INLINE uint8_t _DINx (GPIO_TypeDef *port, uint32_t pin) {
return ((port->IDR & pin) != 0) ? 1:0;
}

//! Helper digital output pin setter
static __INLINE uint8_t _DOUTx (GPIO_TypeDef *port, uint32_t pin, uint8_t st) {
if (st) port->BSRR = (uint32_t)pin;
else port->BSRR = (uint32_t)pin << 16;
return st;
}

/*!
* Initialize GPIO port pins for Nucleo Board
* \return The status of the operation
* \arg LLD_OK Success
* \arg LLD_ERROR Failure
*/
LLD_Status_en Port_Init (void) {
GPIO_InitTypeDef GPIO_InitType;

// Enable Port clock
__HAL_RCC_GPIOA_CLK_ENABLE ();
__HAL_RCC_GPIOC_CLK_ENABLE ();

// BTN port configuration
GPIO_InitType.Mode = GPIO_MODE_INPUT;
GPIO_InitType.Pin = GPIO_PIN_13;
GPIO_InitType.Pull = GPIO_NOPULL;

HAL_GPIO_Init(GPIOC, &GPIO_InitType);

GPIO_InitType.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitType.Speed = GPIO_SPEED_LOW;
GPIO_InitType.Pin = GPIO_PIN_5;

HAL_GPIO_Init(GPIOA, &GPIO_InitType);

return LLD_OK;
}

//! Nucleo's user button reader
uint8_t BTN (void) {
return _DINx (GPIOC, GPIO_PIN_13);
}

//! Nucleo's LD2 led setter
void LED (uint8_t on) {
_DOUTx(GPIOA, GPIO_PIN_5, on);
}

/*! Low level driver init functionality
* \return The status of the operation
* \arg LLD_OK Success
* \arg LLD_ERROR Failure
*/
LLD_Status_en LLD_Init (clock_t sys_freq) {
HAL_Init();
HAL_SysTick_Init (sys_freq);
CYCLE_Init ();
Port_Init ();

return LLD_OK;
}

+ 137
- 0
assignment_2/src/NUCLEO_F401RE.h View File

@@ -0,0 +1,137 @@
/*!
* \file
* NUCLEO_F401RE.h
* \brief
* Nucleo F401RE port file. This file contain the implementation of driver
* calls for F401RE board.
*
* Created on: May 23, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/

#ifndef NUCLEO_F401RE_H_
#define NUCLEO_F401RE_H_

#include <stm32f4xx.h>
#include <stm32f4xx_hal.h>
#include <core_cm4.h>

/*
* ========= Data types ========
*/

//! Driver status return type
typedef enum {
LLD_OK = 0, //!< Indicate successful operation
LLD_ERROR //!< Indicate Error
}LLD_Status_en;

typedef uint8_t din_t;
//typedef int adc_t;

#define OFF (0)
#define ON (!OFF)
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif


/*
* =============== System ===============
*/
#if defined ( __GNUC__ ) && !defined (__CC_ARM)
#include <sys/types.h>
#endif
#include <limits.h>

/*
* Also defined in types.h
*/
#ifndef _CLOCK_T_
#define _CLOCK_T_ unsigned long /* clock() */
typedef _CLOCK_T_ clock_t; /*!< CPU time type */
#endif
#ifndef _TIME_T_
#define _TIME_T_ long /* time() */
typedef _TIME_T_ time_t; /*!< date/time in unix secs past 1-Jan-70 type for 68 years*/
#endif


/*
* Helper macros
*/
#define _CLOCK_T_MAX_VALUE_ (ULONG_MAX) //!< Helper macro for maximum signed CPU time calculations

/*!
* Calculate the positive time difference of _t2_ and _t1_, where
* _t1_, _t2_ are clock_t values
* \note
* _t2_ event comes is AFTER _t1_
*
* ex:
* 0 1 2 3 4 5 6 7 8 9
* ^ ^
* | |
* a b
*
* if : t1=a, t2=b then dt = b-a = t2 - t1
* if : t1=b, t2=a then dt = 9 - (b-a) + 1 = UMAX - (t1-t2) + 1
*
*/
#define _CLOCK_DIFF(_t2_, _t1_) ( ((_t2_)>(_t1_)) ? ((_t2_)-(_t1_)) : (_CLOCK_T_MAX_VALUE_ - ((_t1_) - (_t2_)) + 1) )

/*
* CPU time macros
*/
#define msec2CPUtime(_ms_) (((_ms_) * get_freq()) / 1000)
#define sec2CPUtime(_s_) ((_s_) * get_freq())

#define CPUtime2msec(_t_) (((_t_) * 1000) / get_freq())
#define CPUtime2sec(_t_) ((_t_) / get_freq())

HAL_StatusTypeDef HAL_SysTick_Init(clock_t sf);

clock_t HAL_SelectSysTickFreq (clock_t sf);
clock_t HAL_GetSysTickFreq (void);
int HAL_SetSysTickFreq (clock_t sf);

/*
* OS like Functionalities
*/
clock_t get_freq (void);
int set_freq (clock_t sf);

clock_t clock (void);
clock_t setclock (clock_t c);

time_t time (time_t *timer);
int settime (const time_t *t);


/*
* ============== Cycle count ==============
*/
LLD_Status_en CYCLE_Init (void);
clock_t CYCLE_Get (void);

/*
* =============== Digital I/O ===============
* BTN -- PC13
* LED -- PA5 (SB42 is in place) [SB29: PB13]
*/
LLD_Status_en Port_Init (void);

uint8_t BTN (void);
void LED (uint8_t on);


/*
* ============= Board Init ==============
*/
LLD_Status_en LLD_Init (clock_t sys_freq);

#endif /* NUCLEO_F401RE_H_ */

+ 63
- 0
assignment_2/src/assign2_impl.h View File

@@ -0,0 +1,63 @@
/*!
* \file
* assign2_impl.h
* \brief
* Assignment 2 application header
*
* Created on: May 23, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/

#ifndef ASSIGN2_IMPL_H_
#define ASSIGN2_IMPL_H_

#include "NUCLEO_F401RE.h"
#include <stdlib.h>
#include <math.h>

/*
* ============= User defines ===============
*/
#define SYSTICK_FREQ (1000) //!< 1000Hz => 1msec accuracy

#define MODE_LEADING_EDGE (1) //!< Start counting as soon as the led is switched on
#define MODE_TRAILING_EDGE (2) //!< Start counting as soon as the led is switched off (Motor sport style)

//! If there is no Pre-define MODE, select one here
#ifndef MODE
#define MODE MODE_TRAILING_EDGE
#endif

#define MEASUREMENTS (5) //!< The number of measurements for each experiment

//! elect the maximum waiting time before the visual trigger.
#define MAX_WAIT_TIME sec2CPUtime(10)

//! Select if we need cycle counting also.
#define CYCLE_COUNTING (1)

/*
* ============= Data types ===============
*/
//! Select the application wide accuracy of the floating point type.
typedef float fp_data_t; //!< floating point data alias.

/*!
* Statistical data structure
*/
typedef struct {
fp_data_t average; //!< The average response time of the experiment
fp_data_t median; //!< The median of the times
fp_data_t std_dev; //!< Standard deviation
} stats_t;

fp_data_t average (const clock_t *t, size_t n);
fp_data_t median (const clock_t *t, size_t n);
fp_data_t std_deviation (const clock_t* t, size_t n);

void leading (clock_t *out, size_t n);
void trailing (clock_t *out, size_t n);


#endif /* ASSIGN2_IMPL_H_ */

+ 145
- 0
assignment_2/src/main.c View File

@@ -0,0 +1,145 @@
/*!
* \file
* main.c
* \brief
* Main application file
*
* Created on: May 23, 2020
* Author: Christos Choutouridis AEM: 8997
* email : <cchoutou@ece.auth.gr>
*/
#include "assign2_impl.h"
/*
* Global data
*/
stats_t stats;
/*!
* Compare functionality for qsort
* \param a left hand site
* \param b right hand site
* \return stdlib requirements
* \arg -1 a<b
* \arg 0 a==b
* \arg 1 a>b
*/
static int cmpfunc (const void * a, const void * b) {
fp_data_t v = *(fp_data_t*)a - *(fp_data_t*)b;
return (v < 0) ? -1 : (v > 0) ? 1 : 0;
}
/*!
* Calculates and return the average of an array of measurements
* \param t Pointer to measurements
* \param n Size of measurements array
* \return The average
*/
fp_data_t average (const clock_t *t, size_t n) {
fp_data_t ret =0;
for (size_t i=0 ; i<n ; ++i)
ret += t[i];
return ret / n;
}
/*!
* Calculates and return the median of an array of measurements
* \param t Pointer to measurements
* \param n Size of measurements array
* \return The average
*/
fp_data_t median (const clock_t *t, size_t n) {
qsort ((void*)t, n, sizeof(t[0]), cmpfunc);
return (n % 2) ? t[n/2] : (t[n/2] + t[n/2 -1]) /2;
}
/*!
* Calculates and return the std. deviation of an array of measurements
* \param t Pointer to measurements
* \param n Size of measurements array
* \return The average
*/
fp_data_t std_deviation (const clock_t* t, size_t n) {
fp_data_t av = average (t, n);
fp_data_t s =0;
for (size_t i=0 ; i<n ; ++i) {
s += (t[i]-av)*(t[i]-av);
}
return sqrt (s/n);
}
/*!
* Leading edge trigger experiment
* \param out Pointer to array to store the measurements
* \param n Number of measurements
*/
void leading (clock_t *out, size_t n) {
srand(0);
rand();
LED (OFF);
for (size_t i =0 ; i<n ; ++i) {
clock_t t1, t2;
HAL_Delay(rand() % (MAX_WAIT_TIME + 1));
LED(ON);
t1 = clock ();
while (BTN())
;
t2 = clock ();
LED (OFF);
out[i] = CPUtime2msec(_CLOCK_DIFF(t2, t1));
}
}
/*!
* Trailing edge trigger experiment
* \param out Pointer to array to store the measurements
* \param n Number of measurements
*/
void trailing (clock_t *out, size_t n) {
srand(0);
rand();
LED (ON);
for (size_t i =0 ; i<n ; ++i) {
clock_t t1, t2;
HAL_Delay(rand() % (MAX_WAIT_TIME + 1));
LED(OFF);
t1 = clock ();
while (BTN())
;
t2 = clock ();
LED (ON);
out[i] = CPUtime2msec(_CLOCK_DIFF(t2, t1));
}
}
/*
* Main
*/
int main(void) {
clock_t times[MEASUREMENTS];
LLD_Init (SYSTICK_FREQ); // Initialize the board
// Experiment
#if MODE == MODE_LEADING_EDGE
leading (times, MEASUREMENTS);
#elif MODE == MODE_TRAILING_EDGE
trailing (times, MEASUREMENTS);
#endif
// Get statistical data
stats.average = average ((const clock_t*)times, MEASUREMENTS);
stats.median = median ((const clock_t*)times, MEASUREMENTS);
stats.std_dev = std_deviation((const clock_t*)times, MEASUREMENTS);
// Flash 10Hz to indicate the end of experiment
while (1) {
HAL_Delay(msec2CPUtime(50));
LED (ON);
HAL_Delay(msec2CPUtime(50));
LED (OFF);
}
}

Loading…
Cancel
Save