-
Notifications
You must be signed in to change notification settings - Fork 0
/
wrapper.c
236 lines (202 loc) · 7.04 KB
/
wrapper.c
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
//
// wrapper.h - Small wrapper around driverlib for eCTF. This only exposes what
// we need (EEPROM, UART, and GPIO) and provides a few convenience functions.
//
#include <stdbool.h>
#include <stdint.h>
#include "driverlib/wrapper.h"
#include "driverlib/adc.c"
#include "driverlib/eeprom.c"
#include "driverlib/gpio.c"
#include "driverlib/pin_map.h"
#include "driverlib/uart.c"
#include "driverlib/sysctl.c"
#include "driverlib/timer.c"
#include "inc/tm4c123gh6pm.h"
#define HOST_UART ((uint32_t)UART0_BASE)
#define BOARD_UART ((uint32_t)UART1_BASE)
#define TEMP_SAMPLES 8
/**
* @brief Initialize the UART interfaces.
*
* UART 0 is used to communicate with the host computer.
*/
static void uart_init(void) {
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); // UART 0 for host interface
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // UART 0 is on GPIO Port A
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// Configure the UART for 115,200, 8-N-1 operation.
UARTConfigSetExpClk(
UART0_BASE, SysCtlClockGet(), 115200,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
}
/**
* @brief Set the up board link object.
*
* UART 1 is used to communicate between boards.
*/
static void setup_board_link(void) {
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB0_U1RX);
GPIOPinConfigure(GPIO_PB1_U1TX);
GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// Configure the UART for 115,200, 8-N-1 operation.
UARTConfigSetExpClk(
BOARD_UART, SysCtlClockGet(), 115200,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
while (UARTCharsAvail(BOARD_UART)) {
UARTCharGet(BOARD_UART);
}
}
/**
* @brief Initialize the ADC for temperature sampling.
*
* Temperature sensor is one factor used for entropy generation.
*/
static void adc_init(void) {
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0)) {}
// Disable oversample to increase noise
ADCHardwareOversampleConfigure(ADC0_BASE, 0);
ADCSequenceDisable(ADC0_BASE, 0);
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
// Sample TEMP_SAMPLES samples and interrupt on last sample
for (int i = 0; i < TEMP_SAMPLES - 1; ++i) {
ADCSequenceStepConfigure(ADC0_BASE, 0, i, ADC_CTL_TS | ADC_CTL_SHOLD_4);
}
ADCSequenceStepConfigure(ADC0_BASE, 0, TEMP_SAMPLES - 1, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END | ADC_CTL_SHOLD_4);
ADCSequenceEnable(ADC0_BASE, 0);
}
/**
* @brief Initialize the delay timer.
*
* The delay timer is used to create arbitrary delays in the program.
*/
static void delay_timer_init(void) {
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0)) {}
TimerConfigure(TIMER0_BASE, TIMER_CFG_ONE_SHOT);
TimerClockSourceSet(TIMER0_BASE, TIMER_CLOCK_SYSTEM);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
}
/**
* @brief Initialize the tick timer.
*
* The tick timer is used to keep track of the current system time and is
* used for entropy generation.
*/
static void tick_timer_init(void) {
SysCtlPeripheralEnable(SYSCTL_PERIPH_WTIMER0);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_WTIMER0)) {}
TimerConfigure(WTIMER0_BASE, TIMER_CFG_PERIODIC_UP);
TimerClockSourceSet(WTIMER0_BASE, TIMER_CLOCK_PIOSC);
TimerEnable(WTIMER0_BASE, TIMER_A);
}
/**
* @brief Initialize the system.
*
* This function initializes the system peripherals and sets up the board link.
*/
void init_system(void) {
// Set the clocking to run directly from the crystal.
SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_INT);
// Initialize the ADC temperature sensor
adc_init();
// Initialize the delay timer
delay_timer_init();
// Initialize the tick timer
tick_timer_init();
// Ensure EEPROM peripheral is enabled
SysCtlPeripheralEnable(SYSCTL_PERIPH_EEPROM0);
EEPROMInit();
// Initialize UART peripheral
uart_init();
// Initialize board link UART
setup_board_link();
}
bool uart_avail_host(void) { return UARTCharsAvail(HOST_UART); }
bool uart_avail_board(void) { return UARTCharsAvail(BOARD_UART); }
int32_t uart_readb_host(void) { return UARTCharGet(HOST_UART); }
int32_t uart_readb_board(void) { return UARTCharGet(BOARD_UART); }
void uart_writeb_host(uint8_t data) { UARTCharPut(HOST_UART, data); }
void uart_writeb_board(uint8_t data) { UARTCharPut(BOARD_UART, data); }
void eeprom_read(uint32_t *data, uint32_t address, uint32_t count) { EEPROMRead(data, address, count); }
void eeprom_write(uint32_t *data, uint32_t address, uint32_t count) { EEPROMProgram(data, address, count); }
bool read_sw_1(void) {
return GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4) == 0;
}
/**
* @brief Sample the temperature sensor.
*
* @param samples The array to store the samples in.
*/
void get_temp_samples(uint32_t* samples) {
ADCProcessorTrigger(ADC0_BASE, 0);
while (!ADCIntStatus(ADC0_BASE, 0, false)) {}
ADCIntClear(ADC0_BASE, 0);
ADCSequenceDataGet(ADC0_BASE, 0, samples);
}
/**
* @brief Sleep for a given number of microseconds. Program execution will
* resume after the given number of microseconds.
*
* @param us The number of microseconds to sleep for.
*/
void sleep_us(uint32_t us) {
uint32_t cycles = ((uint64_t)(us) * (uint64_t)(SysCtlClockGet())) / 3 / 1e6;
SysCtlDelay(cycles);
}
/**
* @brief Start a delay timer for a given number of microseconds. Program
* execution will continue after the timer has been started.
*
* @param us The number of microseconds to delay for.
*/
void start_delay_timer_us(uint32_t us) {
uint32_t cycles = ((uint64_t)(us) * (uint64_t)(SysCtlClockGet())) / 1e6;
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerLoadSet(TIMER0_BASE, TIMER_A, cycles);
TimerEnable(TIMER0_BASE, TIMER_A);
}
/**
* @brief Wait for the delay timer to finish, similar to sleep_us.
*
*/
void wait_delay_timer(void) {
while(!TimerIntStatus(TIMER0_BASE, false)) {}
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
}
// Based on TimerEnable
bool IsTimerEnabled(uint32_t ui32Base, uint32_t ui32Timer) {
// Check the arguments.
ASSERT(_TimerBaseValid(ui32Base));
ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
(ui32Timer == TIMER_BOTH));
// Check if the timer modules are enabled.
return (HWREG(ui32Base + TIMER_O_CTL) & (ui32Timer & (TIMER_CTL_TAEN |
TIMER_CTL_TBEN))) != 0;
}
/**
* @brief Get the remaining time on the delay timer.
*
* @return The remaining time on the delay timer in microseconds.
*/
uint32_t get_remaining_us_delay_timer(void) {
if (IsTimerEnabled(TIMER0_BASE, TIMER_A)) {
uint32_t curr_timer = TimerValueGet(TIMER0_BASE, TIMER_A);
return ((uint64_t)(curr_timer) * 1e6) / ((uint64_t)(SysCtlClockGet()));
} else {
return 0;
}
}
/**
* @brief Get the current tick timer value.
*
* @return The current tick timer value.
*/
uint64_t get_tick_timer(void) {
return TimerValueGet64(WTIMER0_BASE);
}