-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
178 lines (168 loc) · 13.4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<html>
<head>
<meta name="google-site-verification" content="EAeura2ckNWnpabEyeeJUebiLGTqKdGNyc5G0UxC12g" />
<meta name="keywords" content="STM32, HAL, peripheral, bitband, bit-band, C, alternative, safe, fast, small, F3" />
<style> body {font-family: verdana;} code {font-size: large;}</style>
</head>
<body>
<h2>ADMAUNALOA</h2>
<p>This project is a hardware abstraction (HAL) library for F3 micro-controller peripherals written in C.<br>
The advantages of this libary are:</p>
<ul>
<li>Faster execution</li>
<li>Smaller size</li>
<li>Interrupt and thread safe register manipulation</li>
<li>Type safe consistent API interface</li>
<li>It can co-exist with other HAL libraries</li>
</ul>
<p>Typical GPIO peripheral functions have up to 50% shorter execution time combined with a up to 40% smaller footprint.<br>
Bitband technology is used extensively and implicit.<br>
This library gives existing bare-metal projects a performance boost, it unleashes the full power of the peripherals hardware.<br></p>
<p><a href="https://github.com/admaunaloa/per_f3_c" rel="nofollow">REPOSITORY</a></p>
<h3><a id="user-content-bitband" class="anchor" aria-hidden="true" href="#bitband"></a>Bitband</h3>
<p>This technique is excellently explained by: <a href="http://www.martinhubacek.cz/arm/advanced-arm-cortex-tips/bit-banding---fast-and-safe-bit-manipulation" rel="nofollow">Martin Hubacek</a></p>
<h2><a id="user-content-usage" class="anchor" aria-hidden="true" href="#usage"></a>USAGE</h2>
<p>Three examples. The first two GPIO get and set, the third is an interrupt handler.</p>
<h3><a id="user-content-gpio-get" class="anchor" aria-hidden="true" href="#gpio-get"></a>GPIO GET</h3>
<div class="highlight highlight-source-c++"><pre> #<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>per_gpio.h<span class="pl-pds">"</span></span>
#<span class="pl-k">define</span> <span class="pl-en">bsp_user_button_1</span>() (&PER_GPIOC->Idr[PER_GPIO_PIN_13])
<span class="pl-c"><span class="pl-c">//</span> Get status of the button input</span>
<span class="pl-k">bool</span> button_state = per_gpio_in(bsp_user_button_1());</pre></div>
<h3><a id="user-content-gpio-set" class="anchor" aria-hidden="true" href="#gpio-set"></a>GPIO SET</h3>
<div class="highlight highlight-source-c++"><pre> #<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>per_gpio.h<span class="pl-pds">"</span></span>
#<span class="pl-k">define</span> <span class="pl-en">bsp_gpio_led_green</span>() (&PER_GPIOB->Odr[PER_GPIO_PIN_0])
<span class="pl-c"><span class="pl-c">//</span> Enable the green LED</span>
<span class="pl-en">per_gpio_set_out</span>(bsp_gpio_led_green(), true);</pre></div>
<h3><a id="user-content-irq" class="anchor" aria-hidden="true" href="#irq"></a>IRQ</h3>
<div class="highlight highlight-source-c++"><pre> #<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>per_tim_gp.h<span class="pl-pds">"</span></span>
<span class="pl-k">void</span> <span class="pl-en">TIM3_IRQHandler</span>(<span class="pl-k">void</span>)
{
<span class="pl-c"><span class="pl-c">//</span> Read and clear the Timer _ GeneralPurpose _ Update Interrupt Flag </span>
<span class="pl-k">if</span> (<span class="pl-c1">per_tim_gp_rdclr_uif</span>(<span class="pl-c1">per_tim_gp_3</span>()))
{
<span class="pl-c"><span class="pl-c">//</span> user code to handle interrupt reason</span>
<span class="pl-c"><span class="pl-c">//</span> ...</span>
}
}</pre></div>
<h3><a id="user-content-try-it-out" class="anchor" aria-hidden="true" href="#try-it-out"></a>TRY IT OUT</h3>
<ol>
<li>Copy the libraries F3, F334R8 and Bsp_example in an existing project, F334R8 supports most other types too,</li>
<li>Add the directories F3/inc F334R8/inc and Bsp_example to the include directories of the project/makefile.</li>
<li>Copy the lines of the GPIO get example above to an existing source file.</li>
<li>Modify PER_GPIOC and PER_GPIO_PIN_13 to a valid GPIO input.</li>
<li>Compile</li>
<li>Test</li>
</ol>
<h2><a id="user-content-syntax" class="anchor" aria-hidden="true" href="#syntax"></a>SYNTAX</h2>
<p>For each peripheral bit the possible get and set functions are provided.
The syntax is</p>
<ol>
<li><strong>per_</strong> Peripheral library prefix</li>
<li><strong><em>usart</em></strong> Peripheral type USART</li>
<li><strong>_ue</strong> Peripheral field name as in the manual. UE is Usart Enable.</li>
<li><strong>(...)</strong> Function</li>
</ol>
<p>Example:</p>
<div class="highlight highlight-source-c++"><pre> <span class="pl-k">bool</span> <span class="pl-en">per_usart_ue</span>(<span class="pl-c1">per_usart_t</span>* ) <span class="pl-c"><span class="pl-c">//</span> returns the value of the Usart Enable bit.</span>
void per_usart_set_ue(<span class="pl-c1">per_usart_t</span>* , <span class="pl-k">bool</span>) <span class="pl-c"><span class="pl-c">//</span> modifies the value of Usart Enable bit.</span></pre></div>
<p>The per_usart_t pointers are provided in a function format</p>
<div class="highlight highlight-source-c++"><pre> <span class="pl-c1">per_usart_t</span>* <span class="pl-en">per_usart_1</span>(<span class="pl-k">void</span>)
per_usart_t* per_usart_2(<span class="pl-k">void</span>)
... </pre></div>
<p>Enabling USART3 comes down to:</p>
<div class="highlight highlight-source-c++"><pre> <span class="pl-en">per_usart_set_ue</span>(per_usart_3(), true); </pre></div>
<p>This set UE example results in a minimal number of assembly instructions because
both functions are inlined and bitband is used. Both functions also make it
type-safe and they enable features such as zero-cost error checking.</p>
<h2><a id="user-content-development-status-apr-2021" class="anchor" aria-hidden="true" href="#development-status-apr-2021"></a>DEVELOPMENT STATUS (apr 2021)</h2>
<p>Supported peripherals</p>
<ul>
<li>100% GPIO</li>
</ul>
<p>Status generics</p>
<ul>
<li>100% BITBAND, LOGGING</li>
</ul>
<h2><a id="user-content-structure" class="anchor" aria-hidden="true" href="#structure"></a>STRUCTURE</h2>
<p>The library consists the following layers:</p>
<h3><a id="user-content-generic-type-definitions" class="anchor" aria-hidden="true" href="#generic-type-definitions"></a>generic type definitions</h3>
<p>In per_bit_f4.h generic field types are provided. The types are available per access rule and per bit size.
For example per_bit_rw1_t is a 1 bit size read and write peripheral field.</p>
<h3><a id="user-content-generic-functions-for-each-generic-type" class="anchor" aria-hidden="true" href="#generic-functions-for-each-generic-type"></a>generic functions for each generic type</h3>
<p>In per_bit_f4.h generic functions are provided. Each function accesses one specific field type.
For example per_bit_rw1_set(..., ...) sets one specific bit.</p>
<h3><a id="user-content-peripheral-specific-structure" class="anchor" aria-hidden="true" href="#peripheral-specific-structure"></a>peripheral specific structure</h3>
<p>Each peripheral has a specific structure defining all the internal fields with size, type and position. It is assembled from the generic types.
per_usart_f4.h shows an example of this.</p>
<div class="highlight highlight-source-c++"><pre> <span class="pl-k">typedef</span> <span class="pl-k">struct</span>
{
<span class="pl-c1">per_bit_rw1_t</span> Ue; <span class="pl-c"><span class="pl-c">//</span>/< USART enable</span>
<span class="pl-c1">per_bit_rw2_t</span> Stop; <span class="pl-c"><span class="pl-c">//</span>/< STOP bits</span>
<span class="pl-c1">per_bit_rw8_t</span> Psc; <span class="pl-c"><span class="pl-c">//</span>/< Pre-scaler value</span>
} <span class="pl-c1">per_usart_per_t</span>; </pre></div>
<p>Each single line defines six properties of the specific peripheral field for the compiler.</p>
<ul>
<li>The type <strong>per_bit_rw1_t</strong> provides both the bit size and the access rules.</li>
<li>The position in the containing struct provides the register address, the bit offset in the register and also the bitband address.</li>
<li>The name of the containing struct provides a small scope.</li>
</ul>
<p>Compare this with alternatives that require calculations with magic numbers and global scoped names.
These first three layers are very powerfull and they allow to define a complete new peripheral with minimal errors and in minimal time.</p>
<h3><a id="user-content-peripheral-field-specific-functions" class="anchor" aria-hidden="true" href="#peripheral-field-specific-functions"></a>peripheral field specific functions</h3>
<p>Each peripheral field has specific functions to access this field.<br>
If relevant an enum is provided to interpret the value of the field correctly.
per_usart_f4.h shows examples of this.</p>
<div class="highlight highlight-source-c++"><pre> <span class="pl-c"><span class="pl-c">//</span>/ USART enable get</span>
<span class="pl-k">static</span> per_inline <span class="pl-k">bool</span> <span class="pl-en">per_usart_ue</span>(<span class="pl-k">const</span> <span class="pl-c1">per_usart_t</span>* <span class="pl-k">const</span> usart)
{
<span class="pl-k">return</span> <span class="pl-c1">per_bit_rw1</span>(&usart-><span class="pl-smi">Per</span>-><span class="pl-smi">Ue</span>);
}
<span class="pl-c"><span class="pl-c">//</span>/ USART enable set</span>
<span class="pl-k">static</span> per_inline <span class="pl-k">void</span> <span class="pl-en">per_usart_set_ue</span>(<span class="pl-k">const</span> <span class="pl-c1">per_usart_t</span>* <span class="pl-k">const</span> usart, <span class="pl-k">bool</span> val)
{
<span class="pl-c1">per_bit_rw1_set</span>(&usart-><span class="pl-smi">Per</span>-><span class="pl-smi">Ue</span>, val);
}</pre></div>
<h3><a id="user-content-peripheral-variants" class="anchor" aria-hidden="true" href="#peripheral-variants"></a>peripheral variants</h3>
<p>Peripherals have variations that are handled by include files in the F3xxx/inc directory.
Variants are for example the UART and USART.
These variants are handled with a descriptor structure for each specific peripheral.<br>
This descriptor structure contains</p>
<ul>
<li>a pointer to the real peripheral structure</li>
<li>enums that define the variant</li>
<li>function pointers to get the base frequency</li>
<li>error logging enums</li>
</ul>
<p>The prevention of functions accessing non-suporting peripheral variants is done with a zero-cost check.
If the variant is correct the compiler will optimise it out, if(0), if the variant is wrong, if(1) the linker will report this non existing function.</p>
<div class="highlight highlight-source-c++"><pre> <span class="pl-k">if</span> (usart->Uart)
{
<span class="pl-c1">per_log_err_function_not_supported</span>();
}</pre></div>
<p>An example is F334/inc/per_usart.h.</p>
<h3><a id="user-content-peripheral-descriptor-functions" class="anchor" aria-hidden="true" href="#peripheral-descriptor-functions"></a>peripheral descriptor functions</h3>
<p>Access to the peripheral descriptors is done via functions that return this descriptor.<br>
This function interface is consistent for all peripherals and it is future proof, for simple GPIO it is implemented as a define, for complex peripherals it is implemented as a function.
For example <strong>per_usart_1()</strong>.</p>
<h2><a id="user-content-inline" class="anchor" aria-hidden="true" href="#inline"></a>inline</h2>
<p>All the layers are provided in header files and inline functions. This allows the compiler to resolve all constants and optimise this all to a minimum size executable with fast execution times.
The use of inline functions makes the API consistent and type safe.</p>
<h2><a id="user-content-debug-logging" class="anchor" aria-hidden="true" href="#debug-logging"></a>debug logging</h2>
<p>Runtime debug logging is provided in bsp_dep.c. This file contains a call-back function that is called from the per_... files in case of a runtime fault.
A default log implementation captures this errors. It is up to the user to adapt and extend this file.</p>
<h2><a id="user-content-dependencies" class="anchor" aria-hidden="true" href="#dependencies"></a>dependencies</h2>
<p>There are only a few external dependencies. All dependencies are accessed and wrapped via the per_dep.* and bsp_dep.* files.<br>
These files allow the user to adapt the library to other development enviroments.</p>
<h2><a id="user-content-exceptions" class="anchor" aria-hidden="true" href="#exceptions"></a>exceptions</h2>
<p>There are a few hardware peripheral registers that are better accessed by register instead of bitband.
The specific functions for this register handle this implicitly. Examples of this are TIMx_SR and USARTx_DR</p>
<h2><a id="user-content-compilation" class="anchor" aria-hidden="true" href="#compilation"></a>compilation</h2>
<p>The library can coexist with other HAL libraries. Just add the directories to the project.
Note: the F334R8 is also good for other F3 types, it provides all possible peripherals.
Add the include libraries: F3/inc, F334R8/inc, Nucleo/inc
If required, compile the files: per_bit.c, per_gpio.c, per_dep.c and bsp_dep.c</p>
<h2><a id="user-content-the-end" class="anchor" aria-hidden="true" href="#the-end"></a>THE END</h2>
<p>If you have any tips, remarks, questions or suggestions please send an email.<br>
Developing more efficient software can decrease energy consumption, decrease carbon footprint and help our planet :-)</p>
</body>
</html>