EE445M RTOS
Taken at the University of Texas Spring 2015
hardware.h File Reference
#include <stdbool.h>
#include "libnotify/notify.h"
#include "libstd/nexus.h"
#include "libos/semaphore.h"
Include dependency graph for hardware.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  hw_uart_metadata
 
struct  hw_timer_metadata
 
struct  hw_button_metadata
 
union  adc_trigger_metadata
 
struct  hw_adc_metadata
 
union  hw_metadata
 
struct  _isr_subscription
 
struct  hw_channel
 
struct  hw_driver
 

Macros

#define HW_DRIVER_MAX_CHANNELS   8
 
#define HW_DRIVER_MAX_SUBSCRIPTIONS   8
 
#define hw_init(type, metadata)
 
#define hw_init_and_subscribe(type, metadata, pseudo_isr)
 
#define hw_subscribe(type, metadata, isr)   _hw_subscribe(type, metadata, isr, false)
 
#define hw_subscribe_single_shot(type, metadata, isr)   _hw_subscribe(type, metadata, isr, true)
 

Typedefs

typedef uint8_t hw_iterator
 
typedef struct _isr_subscription _isr_subscription
 

Enumerations

enum  HW_TYPE { HW_UART, HW_TIMER, HW_BUTTON, HW_ADC }
 

Functions

uint32_t * get_adc_samples ()
 
void hw_init_daemon ()
 
void hw_driver_init (HW_TYPE, hw_metadata)
 
void hw_channel_init (HW_TYPE, hw_metadata)
 
void _hw_subscribe (HW_TYPE, hw_metadata, void(*isr)(notification note), bool)
 
void hw_unsubscribe (HW_TYPE, hw_metadata, void(*isr)(notification note))
 
hw_channel_hw_get_channel (HW_TYPE, hw_metadata)
 
hw_driverhw_driver_singleton (HW_TYPE)
 
void hw_notify (HW_TYPE, hw_metadata, notification)
 
void hw_notify_uart (hw_metadata uart_metadata)
 
void hw_daemon (void)
 

Variables

static volatile semaphore_t HW_SEM_UART0
 

Macro Definition Documentation

#define HW_DRIVER_MAX_CHANNELS   8

Typedef for an interrupt service routine, which can never accept arguments or return a value.

Maximum number of channels supported by each hardware peripheral

Definition at line 112 of file hardware.h.

#define HW_DRIVER_MAX_SUBSCRIPTIONS   8

Maximum number of subscribed threads each hardware driver is responsible for responding to

Definition at line 116 of file hardware.h.

Referenced by hw_channel_init().

#define hw_init (   type,
  metadata 
)
Value:
hw_driver_init(type, metadata); \
hw_channel_init(type, metadata)
void hw_driver_init(HW_TYPE, hw_metadata)
Definition: hardware.c:62
void hw_channel_init(HW_TYPE, hw_metadata)
Definition: hardware.c:94

Initialize hw driver and channel. Simply a convenience to reduce boilerplate.

Definition at line 143 of file hardware.h.

Referenced by adc_interrupt_init(), and main().

#define hw_init_and_subscribe (   type,
  metadata,
  pseudo_isr 
)
Value:
hw_init(type, metadata); \
hw_subscribe(type, metadata, pseudo_isr)
#define hw_subscribe(type, metadata, isr)
Definition: hardware.h:178
#define hw_init(type, metadata)
Definition: hardware.h:143

Initialize hw driver, channel and subscribe to notifications. Simply a convenience to reduce boilerplate.

Definition at line 149 of file hardware.h.

Referenced by main().

#define hw_subscribe (   type,
  metadata,
  isr 
)    _hw_subscribe(type, metadata, isr, false)

Subscribe to a hardware interrupt. This is also called connecting a signal (the isr to be notified) to a slot (the hw-triggered driver isr).

Parameters
Thehardware type in question
Metadataabout the device
Thepseudo-isr to be notified by the hardware driver

Definition at line 178 of file hardware.h.

Referenced by main(), and shell_spawn().

#define hw_subscribe_single_shot (   type,
  metadata,
  isr 
)    _hw_subscribe(type, metadata, isr, true)

Subscribe to a single-shot hardware interrupt. This is also called connecting a signal (the isr to be notified) to a slot (the hw-triggered driver isr). Note that a single-shot subscription differs from a normal subscription in that after the first notification, the subscription will unsubscribe itself.

Parameters
Thehardware type in question
Metadataabout the device
Thepseudo-isr to be notified by the hardware driver

Definition at line 190 of file hardware.h.

Referenced by button_debounce_start().

Typedef Documentation

Each peripheral channel needs to be able to notify subscribers about incoming hardware events

Definition at line 121 of file hardware.h.

typedef uint8_t hw_iterator

An iterator ensured to be of an optimized size according to the relevant #defines below it.

Definition at line 105 of file hardware.h.

Enumeration Type Documentation

enum HW_TYPE

Enum of possible hw types. This enum also serves as an offset into the uthash of the hw drivers' internal data structures.

Enumerator
HW_UART 
HW_TIMER 
HW_BUTTON 
HW_ADC 

Definition at line 46 of file hardware.h.

46  {
47  HW_UART,
48  HW_TIMER,
49  HW_BUTTON,
50  HW_ADC
51 } HW_TYPE;
HW_TYPE
Definition: hardware.h:46

Function Documentation

hw_channel* _hw_get_channel ( HW_TYPE  ,
hw_metadata   
)
inline

For internal use only. Take care of the conversion between a memory-mapped (raw) hw address and the index of said peripheral channel in the memory banks of libhw's device-specific data structures.

Parameters
hw_groupThe hardware group in question
raw_hw_channelThe specific channel of
Returns
Index of 'channel in 's data structures

Definition at line 203 of file hardware.c.

References hw_timer_metadata::base, hw_button_metadata::base, hw_metadata::button, hw_uart_metadata::channel, hw_driver::channels, GPIO_PORTE_BASE, HW_BUTTON, hw_driver_singleton(), HW_TIMER, HW_UART, postpone_death, hw_metadata::timer, TIMER0_BASE, hw_metadata::uart, and UART0_BASE.

Referenced by _hw_subscribe(), hw_channel_init(), hw_notify(), and hw_unsubscribe().

203  {
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 }
#define TIMER0_BASE
Definition: hw_memmap.h:81
#define GPIO_PORTE_BASE
Definition: hw_memmap.h:73
#define postpone_death()
Definition: nexus.h:40
hw_driver * hw_driver_singleton(HW_TYPE type)
Definition: hardware.c:220
#define UART0_BASE
Definition: hw_memmap.h:61
int32_t memory_address_t
Definition: nexus.h:48
hw_channel channels[8]
Definition: hardware.h:138

Here is the call graph for this function:

Here is the caller graph for this function:

void _hw_subscribe ( HW_TYPE  ,
hw_metadata  ,
void(*)(notification note)  isr,
bool   
)

Subscribe to a hardware interrupt. This is also called connecting a signal (the isr to be notified) to a slot (the hw-triggered driver isr).

Parameters
Thehardware type in question
Metadataabout the device
Thepseudo-isr to be notified by the hardware driver

Definition at line 121 of file hardware.c.

References _hw_get_channel(), CDL_DELETE, CDL_PREPEND, hw_channel::free_slots, hw_channel::full_slots, _isr_subscription::single_shot_subscription, and _isr_subscription::slot.

Referenced by schedule_aperiodic().

124  {
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 }
bool single_shot_subscription
Definition: hardware.h:123
uint8_t hw_iterator
Definition: hardware.h:105
void(* slot)(notification)
Definition: hardware.h:124
_isr_subscription * free_slots
Definition: hardware.h:132
#define CDL_DELETE(head, del)
Definition: utlist.h:705
_isr_subscription * full_slots
Definition: hardware.h:133
hw_channel * _hw_get_channel(HW_TYPE type, hw_metadata metadata)
Definition: hardware.c:203
#define CDL_PREPEND(head, add)
Definition: utlist.h:671

Here is the call graph for this function:

Here is the caller graph for this function:

uint32_t* get_adc_samples ( )
void hw_channel_init ( HW_TYPE  ,
hw_metadata   
)

This function is responsible for enabling a specific channel on the specified hardware device. Internal libhw datastructures will also be reset.

Parameters
hw_groupThe hardware group in question
raw_channelThe memory-mapped address of the device channel to initialize
metadataInformation about how to initialize the device

Definition at line 94 of file hardware.c.

References _hw_get_channel(), button_set_interrupt(), CDL_PREPEND, hw_channel::free_slots, hw_channel::full_slots, HW_BUTTON, HW_DRIVER_MAX_SUBSCRIPTIONS, HW_TIMER, HW_UART, hw_channel::isr_subscriptions, NULL, postpone_death, timer_add_interrupt(), and uart_init().

Referenced by adc_interrupt_init(), button_debounce_start(), and main().

94  {
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 }
uint8_t hw_iterator
Definition: hardware.h:105
_isr_subscription * free_slots
Definition: hardware.h:132
#define HW_DRIVER_MAX_SUBSCRIPTIONS
Definition: hardware.h:116
#define postpone_death()
Definition: nexus.h:40
void timer_add_interrupt(hw_metadata metadata)
Definition: timer.c:18
_isr_subscription * full_slots
Definition: hardware.h:133
void button_set_interrupt(hw_metadata metadata)
Definition: button.c:35
void uart_init(hw_metadata metadata)
Definition: uart.c:39
#define NULL
Definition: defines.h:32
hw_channel * _hw_get_channel(HW_TYPE type, hw_metadata metadata)
Definition: hardware.c:203
_isr_subscription isr_subscriptions[8]
Definition: hardware.h:131
#define CDL_PREPEND(head, add)
Definition: utlist.h:671

Here is the call graph for this function:

Here is the caller graph for this function:

void hw_daemon ( void  )

Definition at line 172 of file hardware.c.

References hw_notify_uart(), HW_SEM_UART0, INT_UART0, os_surrender_context, sem_guard, sem_take, UART0_BASE, UART_DEFAULT_BAUD_RATE, and uart_metadata_init.

Referenced by hw_init_daemon(), and main().

172  {
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 }
static volatile semaphore_t HW_SEM_UART0
Definition: hardware.h:11
void hw_notify_uart(hw_metadata uart_metadata)
Definition: hardware.c:189
#define UART_DEFAULT_BAUD_RATE
Definition: uart.h:14
#define sem_take(sem)
#define INT_UART0
Definition: hw_ints.h:451
#define uart_metadata_init(_baud_rate, _channel, _interrupt)
Definition: uart.h:29
#define sem_guard(sem)
#define os_surrender_context()
Definition: os.h:142
#define UART0_BASE
Definition: hw_memmap.h:61

Here is the call graph for this function:

Here is the caller graph for this function:

void hw_driver_init ( HW_TYPE  ,
hw_metadata   
)

This function is responsible for enabling the peripherals and internal data strutures used by the specified .

Parameters
hw_groupThe hardware group driver to initialize

Definition at line 62 of file hardware.c.

References hw_timer_metadata::base, button_init(), hw_uart_metadata::channel, HW_BUTTON, HW_TIMER, HW_UART, postpone_death, SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOF, SYSCTL_PERIPH_TIMER0, SYSCTL_PERIPH_UART0, SysCtlPeripheralEnable(), hw_metadata::timer, TIMER0_BASE, hw_metadata::uart, and UART0_BASE.

Referenced by main().

62  {
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 }
#define TIMER0_BASE
Definition: hw_memmap.h:81
#define SYSCTL_PERIPH_GPIOF
Definition: sysctl.h:76
#define SYSCTL_PERIPH_UART0
Definition: sysctl.h:122
#define SYSCTL_PERIPH_GPIOA
Definition: sysctl.h:71
#define postpone_death()
Definition: nexus.h:40
#define SYSCTL_PERIPH_TIMER0
Definition: sysctl.h:114
void SysCtlPeripheralEnable(uint32_t ui32Peripheral)
Definition: sysctl.c:841
#define UART0_BASE
Definition: hw_memmap.h:61
void button_init(hw_metadata metadata)
Definition: button.c:22

Here is the call graph for this function:

Here is the caller graph for this function:

hw_driver* hw_driver_singleton ( HW_TYPE  )
inline

Return the one hw_driver per hardware device group in use by the TM4C.

Parameters
Thehardware type to grab a pointer of
Returns
Pointer to the hw_driver data structure managing

Definition at line 220 of file hardware.c.

References HW_BUTTON, HW_BUTTON_DRIVER, HW_TIMER, HW_TIMER_DRIVER, HW_UART, HW_UART_DRIVER, NULL, and postpone_death.

Referenced by _hw_get_channel().

220  {
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 }
static hw_driver HW_TIMER_DRIVER
Definition: hardware.c:35
static hw_driver HW_UART_DRIVER
Definition: hardware.c:34
#define postpone_death()
Definition: nexus.h:40
static hw_driver HW_BUTTON_DRIVER
Definition: hardware.c:36
#define NULL
Definition: defines.h:32

Here is the caller graph for this function:

void hw_init_daemon ( )

Initialize libhw's internal data structures

Definition at line 54 of file hardware.c.

References hw_daemon(), and os_add_thread().

54  {
55 
57 }
tcb_t * os_add_thread(task_t task)
Definition: os.c:72
void hw_daemon(void)
Definition: hardware.c:172

Here is the call graph for this function:

void hw_notify ( HW_TYPE  ,
hw_metadata  ,
notification   
)

Notify threads subscribed to about an incoming hardware event.

Parameters
hw_groupThe hardwawre group that received the incoming hardware event
channelThe channel of that received the incoming hardware event
notificationsThe notification (prepared by NVIC-invoked ISR) containing information regarding the recently-occurring hardware interrupt event

Definition at line 149 of file hardware.c.

References _hw_get_channel(), CDL_DELETE, CDL_PREPEND, hw_channel::free_slots, hw_channel::full_slots, _isr_subscription::next, NULL, _isr_subscription::single_shot_subscription, and _isr_subscription::slot.

Referenced by GPIOPortF_Handler(), hw_notify_uart(), s_Handler(), sA_Handler(), TIMER0A_Handler(), TIMER1A_Handler(), and TIMER2A_Handler().

149  {
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 }
bool single_shot_subscription
Definition: hardware.h:123
uint8_t hw_iterator
Definition: hardware.h:105
void(* slot)(notification)
Definition: hardware.h:124
_isr_subscription * next
Definition: hardware.h:125
_isr_subscription * free_slots
Definition: hardware.h:132
#define CDL_DELETE(head, del)
Definition: utlist.h:705
_isr_subscription * full_slots
Definition: hardware.h:133
#define NULL
Definition: defines.h:32
hw_channel * _hw_get_channel(HW_TYPE type, hw_metadata metadata)
Definition: hardware.c:203
#define CDL_PREPEND(head, add)
Definition: utlist.h:671

Here is the call graph for this function:

Here is the caller graph for this function:

void hw_notify_uart ( hw_metadata  uart_metadata)

Iterate over all chars in the respective uart's RX_FIFO and notify all subscribed tasks.

Parameters
UARTmetadata

Definition at line 189 of file hardware.c.

References notification::_char, buffer_dec, buffer_empty, buffer_last, hw_notify(), HW_UART, and UART0_RX_BUFFER.

Referenced by hw_daemon().

189  {
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 }
void hw_notify(HW_TYPE type, hw_metadata metadata, notification note)
Definition: hardware.c:149
static uint8_t UART0_RX_BUFFER[BUFFER_MAX_LENGTH]
Definition: hardware.c:38
#define buffer_last(buf)
Definition: buffer.h:55
#define buffer_empty(buf)
Definition: buffer.h:63
#define buffer_dec(buf)
Definition: buffer.h:39
char _char
Definition: notify.h:25

Here is the call graph for this function:

Here is the caller graph for this function:

void hw_unsubscribe ( HW_TYPE  ,
hw_metadata  ,
void(*)(notification note)  isr 
)

Unsubscribe from a hardware interrupt. This is also called disconnecting a signal (the isr in question) from a slot (the hw-triggered driver isr).

Parameters
Thehardware type in question
Metadataabout the device
Thepseudo-isr to be notified by the hardware driver

Definition at line 137 of file hardware.c.

References _hw_get_channel(), CDL_DELETE, CDL_PREPEND, hw_channel::free_slots, and hw_channel::full_slots.

Referenced by shell_kill().

139  {
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 }
_isr_subscription * free_slots
Definition: hardware.h:132
#define CDL_DELETE(head, del)
Definition: utlist.h:705
_isr_subscription * full_slots
Definition: hardware.h:133
hw_channel * _hw_get_channel(HW_TYPE type, hw_metadata metadata)
Definition: hardware.c:203
#define CDL_PREPEND(head, add)
Definition: utlist.h:671

Here is the call graph for this function:

Here is the caller graph for this function:

Variable Documentation

volatile semaphore_t HW_SEM_UART0
static

Definition at line 11 of file hardware.h.

Referenced by hw_daemon(), and UART0_Handler().