EE445M RTOS
Taken at the University of Texas Spring 2015
hardware.c
Go to the documentation of this file.
1 /* -*- mode: c; c-basic-offset: 4; -*- */
2 /* Standard Libs */
3 #include <stdint.h>
4 #include <stdbool.h>
5 
6 /* TI Includes */
7 #include "inc/hw_ints.h"
8 #include "inc/hw_memmap.h"
9 #include "inc/hw_nvic.h"
10 #include "inc/hw_types.h"
11 
12 /* Driverlib Includes */
13 #include "driverlib/debug.h"
14 #include "driverlib/fpu.h"
15 #include "driverlib/gpio.h"
16 #include "driverlib/interrupt.h"
17 #include "driverlib/pin_map.h"
18 #include "driverlib/sysctl.h"
19 #include "driverlib/rom.h"
20 
21 #include "libut/utlist.h"
22 #include "libhw/hardware.h"
23 
24 #include "libbuffer/buffer.h"
25 /* Supported devices */
26 #include "driverlib/uart.h"
27 #include "driverlib/timer.h"
28 
29 #include "libuart/uart.h"
30 #include "libtimer/timer.h"
31 #include "libbutton/button.h"
32 
33 /* Each driver is statically allocated */
37 
39 static uint8_t UART0_RX_BUFFER_SIZE = 0;
40 
42 static uint8_t UART0_TX_BUFFER_SIZE = 0;
43 
44 uint32_t ADC0_SEQ0_SAMPLES[4];
45 uint32_t ADC0_SEQ1_SAMPLES[4];
46 uint32_t ADC0_SEQ2_SAMPLES[4];
47 uint32_t ADC0_SEQ3_SAMPLES[4];
48 
50 
51 uint32_t jitter_begin;
52 uint32_t jitter_end;
53 
55 
57 }
58 
59 /* To satisfy our need for speed, we must avoid the branches and
60 * memory ready necessary for lazy initialization; that is to say the
61 * \hw_driver_init also executing \hw_channel_init or vice versa. */
62 void hw_driver_init(HW_TYPE type, hw_metadata metadata) {
63 
64  switch(type) {
65  case HW_UART:
67  (metadata.uart.channel - UART0_BASE) / 0x1000);
68  /* todo: parametrize - are they all on A? */
70  break;
71 
72  case HW_TIMER:
74  (metadata.timer.base - TIMER0_BASE) / 0x1000);
75  break;
76 
77  case HW_BUTTON:
78  /* TODO: parametrize to allow other buttons to be driven */
80  /* #need4speed: Buttons on the board are only used for input,
81  * we know how they're going to be used. Break the libhw
82  * convention and initialize these buttons so this code never
83  * has to be run again */
84  button_init(metadata);
85  break;
86 
87  default: postpone_death();
88  }
89 }
90 
91 /* Initialize internal data structures and call driver functions to
92  * initialize hardware relating to the specified channel in
93  * \metadata. */
94 void hw_channel_init(HW_TYPE type, hw_metadata metadata) {
95 
96  hw_iterator i;
97  hw_channel* channel = _hw_get_channel(type, metadata);
98  channel->full_slots = NULL;
99  for(i=0; i<HW_DRIVER_MAX_SUBSCRIPTIONS; ++i) {
100  CDL_PREPEND(channel->free_slots, &channel->isr_subscriptions[i]);
101  }
102 
103  switch(type) {
104  case HW_UART:
105  uart_init(metadata);
106  break;
107 
108  case HW_TIMER:
109  timer_add_interrupt(metadata);
110  break;
111 
112  case HW_BUTTON:
113  /* TODO: parametrize */
114  button_set_interrupt(metadata);
115  break;
116 
117  default: postpone_death();
118  }
119 }
120 
122  hw_metadata metadata,
123  void (*isr)(notification note),
124  bool single_shot) {
125 
126  hw_iterator i;
127  hw_channel* channel = _hw_get_channel(type, metadata);
128  _isr_subscription* new_subscrip = channel->free_slots;
129 
130  CDL_DELETE(channel->free_slots, new_subscrip);
131  CDL_PREPEND(channel->full_slots, new_subscrip);
132 
133  new_subscrip->single_shot_subscription = single_shot;
134  new_subscrip->slot = isr;
135 }
136 
138  hw_metadata metadata,
139  void (*isr)(notification note)) {
140 
141  hw_channel* channel = _hw_get_channel(type, metadata);
142  _isr_subscription* remove = channel->full_slots;
143 
144  while(remove->slot != isr) {++remove;}
145  CDL_DELETE(channel->full_slots, remove);
146  CDL_PREPEND(channel->free_slots, remove);
147 }
148 
149 void hw_notify(HW_TYPE type, hw_metadata metadata, notification note) {
150 
151  hw_iterator i=0;
152  hw_channel* channel = _hw_get_channel(type, metadata);
153  _isr_subscription* subscrip = channel->full_slots;
154  _isr_subscription* new_subscrip = NULL;
155 
156  /* TODO: make this a doubly linked list, not circular */
157  /* consider similar changes to os lib also */
158  while(subscrip && subscrip != new_subscrip) {
159  subscrip->slot(note);
160  new_subscrip = subscrip->next;
161  if (subscrip->single_shot_subscription) {
162  /* Cease fire! cease fire! */
163  subscrip->single_shot_subscription = false;
164  CDL_DELETE(channel->full_slots, subscrip);
165  CDL_PREPEND(channel->free_slots, subscrip);
166  }
167  subscrip = new_subscrip;
168  }
169 }
170 
171 /* todo: programatically generate this function too */
172 void hw_daemon(void) {
173  while (1) {
174  /* mind ordering of sem_checks */
175  /* fixme: one thread for each hardware device, so individual
176  * priorities can be assigned to the threads (which will
177  * handle simultaneous interrupts according to priority
178  * scheduler's interpretation of priority) */
181  /* todo: schedule */
183  hw_notify_uart(uart_metadata);
184  }
186  }
187 }
188 
189 void hw_notify_uart(hw_metadata uart_metadata) {
190 
191  notification note;
192  /* get-it-working: assume the dev knows which buffer to use */
193  uint8_t* buffer = UART0_RX_BUFFER;
194  while(!buffer_empty(UART0_RX_BUFFER)) {
197  hw_notify(HW_UART, uart_metadata, note);
198  }
199 }
200 
201 /* immaculate hashing function, much fast */
202 inline
204 
205  memory_address_t idx;
206  switch(type){
207  /* optimize: divide should be a shift */
208  case HW_UART: idx = (metadata.uart.channel - UART0_BASE) / 0x1000; break;
209  case HW_TIMER: idx = (metadata.timer.base - TIMER0_BASE) / 0x1000; break;
210  case HW_BUTTON: idx = (metadata.button.base - GPIO_PORTE_BASE)/ 0x1000; break;
211  /* Note: libhw won't allow for the use of ports higher than
212  * GPIO_PORTE without modification of the above indexing
213  * algorithm */
214  default: postpone_death();
215  }
216  return &(hw_driver_singleton(type)->channels[idx]);
217 }
218 
219 inline
221 
222  switch(type) {
223  case HW_UART: return &HW_UART_DRIVER;
224  case HW_TIMER: return &HW_TIMER_DRIVER;
225  case HW_BUTTON: return &HW_BUTTON_DRIVER;
226  default: postpone_death();
227  }
228  return NULL;
229 }
230 
231 /*----------------------------------------------------------------------------*
232  * Interrupt Service Routines *
233  *----------------------------------------------------------------------------*/
234 
238 void GPIOPortF_Handler(void) {
239 
241 
244  hw_notify(HW_BUTTON, button_metadata, note);
245 }
246 
247 
248 /* These ISRs were generated programatically -- see
249  * /bin/lisp/rtos-interrupt-generator.el */
250 
254 void UART0_Handler(void) {
255 
256  bool post;
257  uint8_t recv;
258  /* Get and clear the current interrupt sources */
259  uint32_t interrupts = UARTIntStatus(UART0_BASE, true);
260  UARTIntClear(UART0_BASE, interrupts);
261 
262  /* Are we being interrupted because the TX FIFO has space available? */
263  if(interrupts & UART_INT_TX) {
264  /* Move as many bytes as we can into the transmit FIFO */
265  /* TODO: */
266  /* uart_prime_transmit(UART0_BASE); */
267  }
268 
269  /* Are we being interrupted due to a received character? */
270  if(interrupts & (UART_INT_RX | UART_INT_RT)) {
271  /* Get all available chars from the UART */
272  while(UARTCharsAvail(UART0_BASE)) {
273  recv = (unsigned char) (UARTCharGetNonBlocking(UART0_BASE) & 0xFF);
274 
275  /* optional: check for '@echo_off */
276 
277  /* Handle backspace by erasing the last character in the
278  * buffer */
279  switch(recv) {
280  case 127:
281  case '\b':
282  /* If there are any chars to delete, delete the last text */
284  /* Erase previous characters on the user's terminal */
285  /* UARTCharPut(UART0_BASE, '\b'); */
286  /* UARTCharPut(UART0_BASE, ' '); */
287  /* UARTCharPut(UART0_BASE, '\b'); */
288 
289  /* Decrement the number of chars in the buffer */
291  /* Skip ahead to next buffered char */
292  continue;
293  }
294  /* if it is empty, somebody is watching so pass along
295  * the backspace */
296  break;
297 
298  case '\r':
299  case '\n':
300  if(recv == '\r') {
301  UART_LAST_WAS_CR = true;
302  }
303  else if (UART_LAST_WAS_CR) {
304  UART_LAST_WAS_CR = false;
305  /* Don't react twice to a single newline */
306  continue;
307  }
308  case 0x1b:
309  /* Regardless of the newline received, our convention
310  * is to mark end-of-lines in a buffer with the CR
311  * character. */
312  recv = '\r';
313 
314  /* Echo the received character to the newline */
315  UARTCharPut(UART0_BASE, '\n');
316  break;
317 
318  default: break;
319  }
320 
321  post = !buffer_full(UART0_RX_BUFFER);
322  /* If there is room in the RX FIFO, store the char there,
323  * else dump it. optional: a circular buffer might keep
324  * more up-to-date data, considering this is a RTOS */
325  /* this could be cleaned up with error-catching in the buffer library */
326  if(post) {
329  }
330  }
331  }
332 }
333 
334 
341 void TIMER0A_Handler(void) {
342 
344  notification_init(int, 1);
346  hw_notify(HW_TIMER, timer_metadata, note);
347 }
348 
355 void TIMER1A_Handler(void) {
356 
359  notification_init(int, 1);
361  hw_notify(HW_TIMER, timer_metadata, note);
362 }
363 
370 void TIMER2A_Handler(void) {
371 
373  notification_init(int, 1);
375  hw_notify(HW_TIMER, timer_metadata, note);
376 }
377 
378 void ADC0Seq0_Handler(void) {
379 
382  /* TODO: Conform to Notify */
383 }
384 
385 void ADC0Seq1_Handler(void) {
386 
389  /* TODO: Conform to Notify */
390 }
391 
392 void ADC0Seq2_Handler(void) {
393 
397  /* GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1) ^ GPIO_PIN_1); */
399  /* TODO: Conform to Notify */
400 }
401 
402 void ADC0Seq3_Handler(void) {
403 
406  /* GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_1) ^ GPIO_PIN_1); */
407  /* TODO: Conform to Notify */
408 }
#define UART_INT_RX
Definition: uart.h:69
static uint8_t UART0_RX_BUFFER_SIZE
Definition: hardware.c:39
void hw_notify(HW_TYPE type, hw_metadata metadata, notification note)
Definition: hardware.c:149
static hw_driver HW_TIMER_DRIVER
Definition: hardware.c:35
void GPIOPortF_Handler(void)
Definition: hardware.c:238
#define notification_init(_type, _value)
Definition: notify.h:45
static volatile semaphore_t HW_SEM_UART0
Definition: hardware.h:11
tcb_t * os_add_thread(task_t task)
Definition: os.c:72
bool single_shot_subscription
Definition: hardware.h:123
#define UART_INT_TX
Definition: uart.h:68
#define TIMER0_BASE
Definition: hw_memmap.h:81
#define button_metadata_init(_base, _pin, _interrupt)
Definition: button.h:23
bool UARTCharsAvail(uint32_t ui32Base)
Definition: uart.c:1087
#define TIMER2_BASE
Definition: hw_memmap.h:83
uint32_t jitter_begin
Definition: hardware.c:51
void hw_notify_uart(hw_metadata uart_metadata)
Definition: hardware.c:189
#define HWREG(x)
Definition: hw_types.h:48
uint32_t jitter_end
Definition: hardware.c:52
static hw_driver HW_UART_DRIVER
Definition: hardware.c:34
static uint8_t UART0_TX_BUFFER_SIZE
Definition: hardware.c:42
int8_t semaphore_t
#define GPIO_PORTE_BASE
Definition: hw_memmap.h:73
hw_uart_metadata uart
Definition: hardware.h:97
#define SYSCTL_PERIPH_GPIOF
Definition: sysctl.h:76
#define sem_post(sem)
uint8_t hw_iterator
Definition: hardware.h:105
void(* slot)(notification)
Definition: hardware.h:124
memory_address_t channel
Definition: hardware.h:56
void TIMER1A_Handler(void)
Definition: hardware.c:355
void ADC0Seq2_Handler(void)
Definition: hardware.c:392
#define TIMER_TIMA_TIMEOUT
Definition: timer.h:135
void UARTIntClear(uint32_t ui32Base, uint32_t ui32IntFlags)
Definition: uart.c:1581
#define NVIC_ST_CURRENT
Definition: hw_nvic.h:52
_isr_subscription * next
Definition: hardware.h:125
#define UART_DEFAULT_BAUD_RATE
Definition: uart.h:14
#define SYSCTL_PERIPH_UART0
Definition: sysctl.h:122
static uint8_t UART0_RX_BUFFER[BUFFER_MAX_LENGTH]
Definition: hardware.c:38
#define ADC0_BASE
Definition: hw_memmap.h:89
#define BUFFER_MAX_LENGTH
Definition: buffer.h:18
hw_button_metadata button
Definition: hardware.h:99
#define BUTTONS_BOTH
Definition: button.h:28
_isr_subscription * free_slots
Definition: hardware.h:132
int32_t ADCSequenceDataGet(uint32_t ui32Base, uint32_t ui32SequenceNum, uint32_t *pui32Buffer)
Definition: adc.c:824
memory_address_t base
Definition: hardware.h:63
int32_t UARTCharGetNonBlocking(uint32_t ui32Base)
Definition: uart.c:1143
#define HW_DRIVER_MAX_SUBSCRIPTIONS
Definition: hardware.h:116
#define sem_take(sem)
#define SYSCTL_PERIPH_GPIOA
Definition: sysctl.h:71
#define CDL_DELETE(head, del)
Definition: utlist.h:705
void ADC0Seq1_Handler(void)
Definition: hardware.c:385
uint32_t UARTIntStatus(uint32_t ui32Base, bool bMasked)
Definition: uart.c:1533
void TIMER0A_Handler(void)
Definition: hardware.c:341
#define postpone_death()
Definition: nexus.h:40
void hw_driver_init(HW_TYPE type, hw_metadata metadata)
Definition: hardware.c:62
#define buffer_last(buf)
Definition: buffer.h:55
hw_timer_metadata timer
Definition: hardware.h:98
#define INT_UART0
Definition: hw_ints.h:451
#define TIMER1_BASE
Definition: hw_memmap.h:82
uint32_t ADC0_SEQ3_SAMPLES[4]
Definition: hardware.c:47
void TimerIntClear(uint32_t ui32Base, uint32_t ui32IntFlags)
Definition: timer.c:1568
#define SYSCTL_PERIPH_TIMER0
Definition: sysctl.h:114
void SysCtlPeripheralEnable(uint32_t ui32Peripheral)
Definition: sysctl.c:841
#define uart_metadata_init(_baud_rate, _channel, _interrupt)
Definition: uart.h:29
void ADCIntClear(uint32_t ui32Base, uint32_t ui32SequenceNum)
Definition: adc.c:363
uint32_t ADC0_SEQ2_SAMPLES[4]
Definition: hardware.c:46
void timer_add_interrupt(hw_metadata metadata)
Definition: timer.c:18
hw_driver * hw_driver_singleton(HW_TYPE type)
Definition: hardware.c:220
void _hw_subscribe(HW_TYPE type, hw_metadata metadata, void(*isr)(notification note), bool single_shot)
Definition: hardware.c:121
_isr_subscription * full_slots
Definition: hardware.h:133
#define sem_guard(sem)
semaphore_t HW_ADC_SEQ2_SEM
Definition: hardware.c:49
HW_TYPE
Definition: hardware.h:46
#define buffer_add(buf, elt)
Definition: buffer.h:28
void ADC0Seq3_Handler(void)
Definition: hardware.c:402
void button_set_interrupt(hw_metadata metadata)
Definition: button.c:35
void TIMER2A_Handler(void)
Definition: hardware.c:370
#define timer_metadata_init(_base, _frequency, _interrupt, _periodic)
Definition: timer.h:21
#define os_surrender_context()
Definition: os.h:142
static hw_driver HW_BUTTON_DRIVER
Definition: hardware.c:36
#define buffer_empty(buf)
Definition: buffer.h:63
void hw_init_daemon()
Definition: hardware.c:54
void uart_init(hw_metadata metadata)
Definition: uart.c:39
#define buffer_full(buf)
Definition: buffer.h:59
#define UART0_BASE
Definition: hw_memmap.h:61
void button_init(hw_metadata metadata)
Definition: button.c:22
void hw_unsubscribe(HW_TYPE type, hw_metadata metadata, void(*isr)(notification note))
Definition: hardware.c:137
#define buffer_dec(buf)
Definition: buffer.h:39
memory_address_t base
Definition: hardware.h:73
int32_t memory_address_t
Definition: nexus.h:48
void UARTCharPut(uint32_t ui32Base, unsigned char ucData)
Definition: uart.c:1268
#define NULL
Definition: defines.h:32
void hw_channel_init(HW_TYPE type, hw_metadata metadata)
Definition: hardware.c:94
void GPIOIntClear(uint32_t ui32Port, uint32_t ui32IntFlags)
Definition: gpio.c:878
uint32_t ADC0_SEQ1_SAMPLES[4]
Definition: hardware.c:45
static bool UART_LAST_WAS_CR
Definition: uart.h:17
int32_t GPIOPinRead(uint32_t ui32Port, uint8_t ui8Pins)
Definition: gpio.c:1006
static uint8_t UART0_TX_BUFFER[BUFFER_MAX_LENGTH]
Definition: hardware.c:41
hw_channel * _hw_get_channel(HW_TYPE type, hw_metadata metadata)
Definition: hardware.c:203
char _char
Definition: notify.h:25
hw_channel channels[8]
Definition: hardware.h:138
void hw_daemon(void)
Definition: hardware.c:172
void UART0_Handler(void)
Definition: hardware.c:254
#define UART_INT_RT
Definition: uart.h:67
_isr_subscription isr_subscriptions[8]
Definition: hardware.h:131
#define GPIO_PORTF_BASE
Definition: hw_memmap.h:74
uint32_t ADC0_SEQ0_SAMPLES[4]
Definition: hardware.c:44
#define CDL_PREPEND(head, add)
Definition: utlist.h:671
void ADC0Seq0_Handler(void)
Definition: hardware.c:378