initial commit

This commit is contained in:
tkl
2016-07-28 21:02:54 +02:00
commit 8b47a2b3e6
424 changed files with 175707 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
/*
* adc.c
*
* Created on: Dec 23, 2012
* Author: tkl
*/
#include <stddef.h>
#include "adc.h"
//------------------------------------------------------------------------------
int adc_open(const struct adc *device) {
if(NULL == device) {
return -1;
}
adc_fp_open open = device->fp->open;
return open(device->arch_dep_device);
}
//------------------------------------------------------------------------------
int adc_close(const struct adc *device) {
if(NULL == device) {
return -1;
}
adc_fp_close close = device->fp->close;
return close(device->arch_dep_device);
}
//------------------------------------------------------------------------------
uint16_t adc_read(const struct adc *device, int timeout) {
if(NULL == device) {
return -1;
}
adc_fp_read read = device->fp->read;
return read(device->arch_dep_device, timeout);
}

View File

@@ -0,0 +1,130 @@
/*
* driver.c
*
* Created on: Jul 27, 2016
* Author: tkl
*/
#include <stddef.h>
#include "driver.h"
#include "adc.h"
#include "gpio.h"
#include "i2c.h"
#include "rtc.h"
#include "spi.h"
#include "uart.h"
int open(const struct driver *driver)
{
int ret = -1;
if(NULL == driver)
return ret;
switch(driver->driver_type) {
case DRIVER_TYPE_ADC:
ret = adc_open((const struct adc *)(driver->device_driver));
break;
case DRIVER_TYPE_GPIO:
ret = gpio_open((const struct gpio *)(driver->device_driver));
break;
case DRIVER_TYPE_I2C:
ret = i2c_open((struct i2c *)(driver->device_driver));
break;
case DRIVER_TYPE_RTC:
ret = rtc_open((const struct rtc *)(driver->device_driver));
break;
case DRIVER_TYPE_SPI:
ret = spi_open((const struct spi *)(driver->device_driver));
break;
case DRIVER_TYPE_UART:
ret = uart_open((const struct uart *)(driver->device_driver));
break;
}
return ret;
}
int close(const struct driver *driver)
{
int ret = -1;
if(NULL == driver)
return ret;
switch(driver->driver_type) {
case DRIVER_TYPE_ADC:
ret = adc_close((const struct adc *)(driver->device_driver));
break;
case DRIVER_TYPE_GPIO:
ret = gpio_close((const struct gpio *)(driver->device_driver));
break;
case DRIVER_TYPE_I2C:
ret = i2c_close((struct i2c *)(driver->device_driver));
break;
case DRIVER_TYPE_RTC:
ret = rtc_close((const struct rtc *)(driver->device_driver));
break;
case DRIVER_TYPE_SPI:
ret = spi_close((const struct spi *)(driver->device_driver));
break;
case DRIVER_TYPE_UART:
ret = uart_close((const struct uart *)(driver->device_driver));
break;
}
return ret;
}
int read(const struct driver *driver, char *buffer, int len)
{
int ret = -1;
if(NULL == driver)
return ret;
switch(driver->driver_type) {
case DRIVER_TYPE_ADC:
break;
case DRIVER_TYPE_GPIO:
ret = gpio_read((const struct gpio *)(driver->device_driver));
if(len > 0) {
buffer[0] = ret + 0x30;
ret = 1;
}
break;
case DRIVER_TYPE_I2C:
break;
case DRIVER_TYPE_RTC:
break;
case DRIVER_TYPE_SPI:
break;
case DRIVER_TYPE_UART:
ret = uart_read((const struct uart *)(driver->device_driver), buffer, len);
break;
}
return ret;
}
int write(const struct driver *driver, const char *buffer, int len)
{
int ret = -1;
if(NULL == driver)
return ret;
switch(driver->driver_type) {
case DRIVER_TYPE_ADC:
break;
case DRIVER_TYPE_GPIO:
if(len > 0) {
char send = 0;
if((buffer[0] - 0x30) > 0)
send = 1;
gpio_write((const struct gpio *)(driver->device_driver), send);
ret = 1;
}
break;
case DRIVER_TYPE_I2C:
break;
case DRIVER_TYPE_RTC:
break;
case DRIVER_TYPE_SPI:
break;
case DRIVER_TYPE_UART:
ret = uart_write((const struct uart *)(driver->device_driver), buffer, len);
break;
}
return ret;
}

View File

@@ -0,0 +1,4 @@
CHECK_FOLDER += firmware/kernel/driver
SUB_FOLDER += firmware/kernel/driver
INCLUDES += firmware/kernel/driver/include
DOC_SRC += firmware/kernel/driver

View File

@@ -0,0 +1,61 @@
/*! \file gpio.c
* \author tkl
* \date Feb 13, 2012
* \brief Source file of the architecture independent gpio driver.
*/
#include <stddef.h>
#include "gpio.h"
int gpio_open(const struct gpio *device)
{
if(device == NULL)
return -1;
gpio_fp_open_t open = device->fp->open;
return open(device->arch_dep_device);
}
int gpio_close(const struct gpio *device)
{
if(device == NULL)
return -1;
gpio_fp_close_t close = device->fp->close;
return close(device->arch_dep_device);
}
char gpio_read(const struct gpio *device)
{
if(device == NULL)
return 0;
gpio_fp_read_t read = device->fp->read;
return read(device->arch_dep_device);
}
void gpio_write(const struct gpio *device, char byte)
{
if(device == NULL)
return;
gpio_fp_write_t write = device->fp->write;
write(device->arch_dep_device, byte);
}
void gpio_toggle(const struct gpio *device) {
if(device == NULL)
return;
gpio_fp_toggle_t toggle = device->fp->toggle;
toggle(device->arch_dep_device);
}
int gpio_set_exti_callback(const struct gpio *device, const void *callback,
const void *param)
{
if((device == NULL) || (callback == NULL))
return -1;
gpio_fp_set_cb_t set_cb = device->fp->set_cb;
return set_cb(device->arch_dep_device, callback, param);
}

View File

@@ -0,0 +1,53 @@
//! \file i2c.c
//! \author tkl
//! \date Apr 26, 2012
//! \brief Source file of the architecture independent i2c driver.
#include <stddef.h>
#include "i2c.h"
int i2c_open(struct i2c *device)
{
if(device == NULL) {
return -1;
}
i2c_fp_open_t open = device->fp->open;
device->cnt_subscriber++;
return open(device->arch_dep_device);
}
int i2c_close(struct i2c *device)
{
int ret = -1;
if(device == NULL) {
return -1;
}
i2c_fp_close_t close = device->fp->close;
device->cnt_subscriber--;
if(device->cnt_subscriber == 0)
ret = close(device->arch_dep_device);
else
ret = 0; /* close only if all subscribers are gone. */
return ret;
}
//-----------------------------------------------------------------------------
int i2c_write(const struct i2c *device, char addr, const char *buffer,
unsigned int len)
{
if(device == NULL) {
return -1;
}
i2c_fp_write_t write = device->fp->write;
return write(device->arch_dep_device, addr, buffer, len);
}
//-----------------------------------------------------------------------------
int i2c_read(const struct i2c *device, char addr, char *buffer,
unsigned int len)
{
if(device == NULL) {
return -1;
}
i2c_fp_read_t read = device->fp->read;
return read(device->arch_dep_device, addr, buffer, len);
}

View File

@@ -0,0 +1,38 @@
/*
* adc.h
*
* Created on: Dec 23, 2012
* Author: tkl
*/
#ifndef ADC_H_
#define ADC_H_
#include <stdint.h>
//------------------------------------------------------------------------------
typedef int (*adc_fp_open)(const void *);
typedef int (*adc_fp_close)(const void *);
typedef uint16_t (*adc_fp_read)(const void *, int);
//------------------------------------------------------------------------------
//! \brief Contains the function pointer to access the adc driver.
struct adc_fp {
const adc_fp_open open; //!< Function pointer to the open function.
const adc_fp_close close; //!< Function pointer to the close function.
const adc_fp_read read; //!< Function pointer to the read function.
};
//------------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the adc driver.
struct adc {
const void *arch_dep_device; //!< Architecture depended adc device (i.e. msp430_adc_t).
const struct adc_fp *fp; //!< Function pointer for the adc driver access.
};
//------------------------------------------------------------------------------
int adc_open(const struct adc *device);
int adc_close(const struct adc *device);
uint16_t adc_read(const struct adc *device, int timeout);
#endif /* ADC_H_ */

View File

@@ -0,0 +1,78 @@
/*! \file gpio.h
* \author tkl
* \date Feb 13, 2012
* \brief Header file of the architecture independent gpio driver.
*/
#ifndef GPIO_H_
#define GPIO_H_
//! \brief Function pointer to the open function.
typedef int (*gpio_fp_open_t)(const void*);
//! \brief Function pointer to the close function.
typedef int (*gpio_fp_close_t)(const void*);
//! \brief Function pointer to the read function.
typedef char (*gpio_fp_read_t)(const void*);
//! \brief Function pointer to the write function.
typedef void (*gpio_fp_write_t)(const void*, char);
//! \brief Function pointer to the toggle function.
typedef void (*gpio_fp_toggle_t)(const void*);
//! \brief Function pointer to the set_callback function.
typedef int (*gpio_fp_set_cb_t)(const void*, const void*, const void*);
//! \brief Contains the function pointer to access the gpio driver.
struct gpio_fp {
const gpio_fp_open_t open; //!< Function pointer to the open function.
const gpio_fp_close_t close; //!< Function pointer to the close function.
const gpio_fp_read_t read; //!< Function pointer to the read function.
const gpio_fp_write_t write; //!< Function pointer to the write function.
const gpio_fp_toggle_t toggle; //!< Function pointer to the toggle function.
const gpio_fp_set_cb_t set_cb; //!< Function pointer to the set_callback function.
};
//! \brief Contains the architecture depended device and the access functions to the gpio driver.
struct gpio {
const void *arch_dep_device; //!< Architecture depended gpio device (i.e. stm32f10x_gpio_t).
const struct gpio_fp *fp; //!< Function pointer for the gpio driver access.
};
/*! \brief Open a gpio pin.
* \param device The gpio to open.
* \retval -1 in error case.
*/
int gpio_open(const struct gpio *device);
/*! \brief Close a gpio pin
* \param device The gpio to close.
* \retval -1 in error case.
*/
int gpio_close(const struct gpio *device);
/*! \brief read from a gpio pin
* \param device The gpio to read from
* \return Read out value.
*/
char gpio_read(const struct gpio *device);
/*! \brief write to a gpio pin
* \param device The gpio to write to.
* \param byte The value to write.
*/
void gpio_write(const struct gpio *device, char byte);
//! \brief toggle a gpio pin
//! \param device the gpio to toggle.
void gpio_toggle(const struct gpio *device);
//! \brief set the callback for a gpio pin external interrupt
//! \param device The gpio to set a callback for.
//! \param callback The function pointer to be called back.
//! \param param The parameter for the call back.
int gpio_set_exti_callback(const struct gpio *device, const void *callback,
const void *param);
#endif /* GPIO_H_ */

View File

@@ -0,0 +1,75 @@
//! \file spi.h
//! \author tkl
//! \date Apr 26, 2012
//! \brief Header file of the architecture independent i2c driver.
#ifndef I2C_H_
#define I2C_H_
//-----------------------------------------------------------------------------
//! \brief Function pointer to the open function.
typedef int (*i2c_fp_open_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the close function.
typedef int (*i2c_fp_close_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the write function.
typedef int (*i2c_fp_write_t)(const void *, char addr, const char *buffer,
unsigned int len);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the read function.
typedef int (*i2c_fp_read_t)(const void *, char addr, char *buffer,
unsigned int len);
//-----------------------------------------------------------------------------
//! \brief Contains the function pointer to access the i2c driver.
struct i2c_fp {
const i2c_fp_open_t open; //!< Function pointer to the open function.
const i2c_fp_close_t close; //!< Function pointer to the close function.
const i2c_fp_write_t write; //!< Function pointer to the write function.
const i2c_fp_read_t read; //!< Function pointer to the read function.
};
//-----------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the i2c driver.
struct i2c {
const void *arch_dep_device; //!< Architecture depended i2c device (i.e. stm32f10x_i2c_t).
const struct i2c_fp *fp; //!< Function pointer for the i2c driver access.
int cnt_subscriber; //!< Number of opened slaves
};
//-----------------------------------------------------------------------------
//! \brief Open i2c device.
//! \param device The device to open.
//! \retval -1 in error case.
int i2c_open(struct i2c *device);
//-----------------------------------------------------------------------------
//! \brief Close i2c device.
//! \param device The device to close.
//! \retval -1 in error case.
int i2c_close(struct i2c *device);
//-----------------------------------------------------------------------------
//! \brief Write to an i2c device.
//! \param device The device to write to.
//! \param addr The i2c address of the i2c sink.
//! \param buffer The buffer to write.
//! \param len The length of the buffer.
//! \retval -1 in error case, otherwise the number of written bytes.
int i2c_write(const struct i2c *device, char addr, const char *buffer,
unsigned int len);
//-----------------------------------------------------------------------------
//! \brief Read from an i2c device.
//! \param device The device to read from.
//! \param addr The i2c address of the i2c source
//! \param buffer The buffer to read to.
//! \param len The maximum length of the buffer.
//! \retval -1 in error case, otherwise the number of read bytes.
int i2c_read(const struct i2c *device, char addr, char *buffer,
unsigned int len);
#endif /* I2C_H_ */

View File

@@ -0,0 +1,161 @@
//! \file rtc.h
//! \author tkl
//! \date Jul 8, 2012
//! \brief Header file of the architecture independent rtc implementation.
#ifndef RTC_H_
#define RTC_H_
#include <stdint.h>
//-----------------------------------------------------------------------------
//! \brief Loki time container.
struct loki_time {
uint32_t sec; //!< Seconds. [0-60]
uint32_t min; //!< Minutes. [0-59]
uint32_t hour; //!< Hours. [0-23]
uint32_t day; //!< Day. [1-31]
uint32_t mon; //!< Month. [0-11]
uint32_t year; //!< Year.
};
//-----------------------------------------------------------------------------
//! \brief Rtc interrupt interval.
enum rtc_interval {
RTC_INTERVAL_MINUTE = 0, //!< rtc interrupt every minute.
RTC_INTERVAL_HOUR, //!< rtc interrupt every hour.
RTC_INTERVAL_MIDNIGHT, //!< rtc interrupt every day at 00:00.
RTC_INTERVAL_NOON //!< rtc interrupt every day at 12:00.
};
//-----------------------------------------------------------------------------
//! \brief Rtc alarm mask.
enum rtc_alarm_mask {
RTC_ALARM_DISABLED = 0x00, //!< Alarm mask disabled.
RTC_ALARM_MINUTE = 0x01, //!< Alarm mask minute.
RTC_ALARM_HOUR = 0x02, //!< Alarm mask hour.
RTC_ALARM_DAY_OF_WEEK = 0x04, //!< Alarm mask day of week.
RTC_ALARM_DAY_OF_MONTH = 0x08 //!< Alarm mask day of month.
};
//-----------------------------------------------------------------------------
//! Callback for the open function of the arch depended rtc driver.
typedef int (*rtc_fp_open_t)(const void*);
//! Callback for the close function of the arch depended rtc driver.
typedef int (*rtc_fp_close_t)(const void*);
//! Callback for the time set function of the arch depended rtc driver.
typedef void (*rtc_fp_set_time_t)(const void*, const struct loki_time*);
//! Callback for the time get function of the arch depended rtc driver.
typedef struct loki_time *(*rtc_fp_get_time_t)(const void*, struct loki_time*);
//! Callback for the start interval event function.
typedef int (*rtc_fp_start_interval_event)
(const void *, enum rtc_interval, const void *, const void *);
//! Callback for the stop interval event.
typedef int (*rtc_fp_stop_interval_event)(const void *);
//! Callback for the start alarm event.
typedef int (*rtc_fp_start_alarm_event)
(const void *, const struct loki_time*, enum rtc_alarm_mask, const void *, const void *);
//! Callback for the stop alarm event.
typedef int (*rtc_fp_stop_alarm_event)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to access the rct driver.
struct rtc_fp {
const rtc_fp_open_t open; //!< Function pointer to the open function.
const rtc_fp_close_t close; //!< Function pointer to the close function.
const rtc_fp_set_time_t set_time; //!< Function pointer to the set_time function.
const rtc_fp_get_time_t get_time; //!< Function pointer to the get_time function.
const rtc_fp_start_interval_event start_interval; //!< Function pointer to the start_interval function.
const rtc_fp_stop_interval_event stop_interval; //!< Function pointer to the stop_interval function.
const rtc_fp_start_alarm_event start_alarm; //!< Function pointer to the start_alarm function.
const rtc_fp_stop_alarm_event stop_alarm; //!< Function pointer to the stop_alarm function.
};
//-----------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the rtc driver.
struct rtc {
const void *arch_dep_device; //!< Architecture depended rtc device (i.e. msp430_rtc_t).
const struct rtc_fp *fp; //!< Function pointer for the rtc driver access.
};
//-----------------------------------------------------------------------------
//! \brief Open a rtc device.
//! \param device The rtc device to open.
//! \retval -1 in error case.
int rtc_open(const struct rtc *device);
//-----------------------------------------------------------------------------
//! \brief Close a rtc device.
//! \param device The rtc device to close.
//! \retval -1 in error case.
int rtc_close(const struct rtc *device);
//-----------------------------------------------------------------------------
//! \brief Set rtc time.
//! \param device The rtc device.
//! \param time The time to set.
void rtc_set_time(const struct rtc *device, const struct loki_time *time);
//-----------------------------------------------------------------------------
//! \brief Get rtc time.
//! \param device The rtc device.
//! \param time The time to get.
//! \retval NULL in error case, otherwise points to time.
struct loki_time *rtc_get_time(const struct rtc *device,
struct loki_time *time);
//-----------------------------------------------------------------------------
//! \brief Converts a Unix timestamp to a loki_time.
//! \param tick The Unix timestamp.
//! \return the converted time.
struct loki_time tick_to_time(uint32_t tick);
//-----------------------------------------------------------------------------
//! \brief Converts a loki_time to aunix timestamp.
//! \param time The time to convert.
//! \return The converted unix timestamp.
uint32_t time_to_tick(const struct loki_time *time);
//-----------------------------------------------------------------------------
//! \brief Starts a rtc interval event.
//! On every occurance of interval the rtc event gets fired.
//! \param device The rtc device.
//! \param interval The interval of rtc event occurance.
//! \param callback The callback is executed in case of interval event.
//! \param argument The argument for the callback.
//! \retval -1 in error case.
int rtc_start_interval_event(const struct rtc *device, enum rtc_interval interval,
const void * callback, const void *argument);
//-----------------------------------------------------------------------------
//! \brief Stops a rtc interval event.
//! \param device The rtc device.
//! \retval -1 in error case.
int rtc_stop_interval_event(const struct rtc *device);
//-----------------------------------------------------------------------------
//! \brief Starts a rtc alarm event.
//! \param device The rtc device.
//! \param alarm_time The time to fire the alarm.
//! \param alarm_mask The mask to filter the alarm time.
//! \param callback The callback is executed in case of alarm.
//! \param argument The argument for the callback.
//! \retval -1 in error case.
int rtc_start_alarm_event(const struct rtc *device,
const struct loki_time *alarm_time, enum rtc_alarm_mask alarm_mask,
const void * callback, const void *argument);
//-----------------------------------------------------------------------------
//! \brief Stops a rtc alarm.
//! \param device The rtc device.
//! \retval -1 in error case.
int rtc_stop_alarm_event(const struct rtc *device);
#endif /* RTC_H_ */

View File

@@ -0,0 +1,75 @@
//! \file spi.h
//! \author tkl
//! \date Feb 11, 2012
//! \brief Header file of the architecture independent spi driver.
#ifndef SPI_H_
#define SPI_H_
//-----------------------------------------------------------------------------
//! \brief Function pointer to the open function.
typedef int (*spi_fp_open_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the close function.
typedef int (*spi_fp_close_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the assert chip select function.
typedef void (*spi_fp_assert_cs_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the deassert chip select function.
typedef void (*spi_fp_deassert_cs_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the receive / transmit function.
typedef char (*spi_fp_rxtx_byte_t)(const void *, char);
//-----------------------------------------------------------------------------
//! \brief Contains the function pointer to access the spi driver.
struct spi_fp {
const spi_fp_open_t open; //!< Function pointer to the open function.
const spi_fp_close_t close; //!< Function pointer to the close function.
const spi_fp_assert_cs_t assert_cs; //!< Function pointer to the assert chip select function.
const spi_fp_deassert_cs_t deassert_cs; //!< Function pointer to the deassert chip select function.
const spi_fp_rxtx_byte_t rxtx_byte; //!< Function pointer to the receive / transmit function.
};
//-----------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the spi driver.
struct spi {
const void *arch_dep_device; //!< Architecture depended spi device (i.e. stm32f10x_spi_t).
const struct spi_fp *fp; //!< Function pointer for the spi driver access.
};
//-----------------------------------------------------------------------------
//! \brief Open spi device.
//! \param device The spi to open.
int spi_open(const struct spi *device);
//-----------------------------------------------------------------------------
//! \brief Close spi device.
//! \param device The spi to close.
//! \retval -1 in error case.
int spi_close(const struct spi *device);
//-----------------------------------------------------------------------------
//! \brief Assert the spi's chip select.
//! \param device The spi to assert.
//! \retval -1 in error case.
void spi_assert_cs(const struct spi * device);
//-----------------------------------------------------------------------------
//! \brief Deassert the spi'schip select.
//! \param device The spi to deassert.
//! \retval -1 in error case.
void spi_deassert_cs(const struct spi * device);
//-----------------------------------------------------------------------------
//! \brief rx/tx byte over spi.
//! \param device The spi to act on.
//! \param byte The data to transmit.
//! \return The received data
char spi_rxtx_byte(const struct spi * device, char byte);
#endif /* SPI_H_ */

View File

@@ -0,0 +1,43 @@
//! \file timer.h
//! \author tkl
//! \date Jul 4, 2012
//! \brief Header file of the architecture independent timer implementation.
#ifndef TIMER_H_
#define TIMER_H_
typedef int (*timer_fp_open_t)(const void*); //!< callback for the open function of the arch depended timer driver.
typedef int (*timer_fp_close_t)(const void*); //!< callback for the close function of the arch depended timer driver.
typedef int (*timer_fp_set_cb_t)(const void*, const void *, const void *); //!< callback for set_callback function of the arch depended timer driver.
//! \brief The access function pointer for the timer.
struct timer_fp {
const timer_fp_open_t open; //!< Function pointer to the open function.
const timer_fp_close_t close; //!< Function pointer to the close function.
const timer_fp_set_cb_t set_cb; //!< Function pointer to the set_callback function.
};
//! \brief Contains the architecture depended device informations.
struct loki_timer {
const void *arch_dep_device; //!< Architecture depended timer device (i.e. msp430_timer).
const struct timer_fp *fp; //!< Function pointer to the architectur depended timer driver access.
};
//! \brief Open a timer timer
//! \param device The timer device to open.
//! \retval -1 in error case.
int timer_open(const struct loki_timer *device);
//! \brief Close a timer timer
//! \param device The timer device to close.
//! \retval -1 in error case.
int timer_close(const struct loki_timer *device);
//! \brief Set the callback for a sys tick timer
//! \param device The timer device to set the callback for.
//! \param callback The function pointer to call back.
//! \param param The parameter for the call back.
//! \retval -1 in error case.
int timer_set_it_callback(const struct loki_timer *device, const void *callback,
const void *param);
#endif /* TIMER_H_ */

View File

@@ -0,0 +1,63 @@
//! \file uart.h
//! \author tkl
//! \date Jul 15, 2012
//! \brief Header file of the architecture independent uart implementation.
#ifndef UART_H_
#define UART_H_
//! Function pointer for the uart open function.
typedef int (*uart_fp_open_t)(const void*);
//! Function pointer for the uart close function.
typedef int (*uart_fp_close_t)(const void*);
//! Function pointer for the uart read function.
typedef int (*uart_fp_read_t)(const void*, char*, int);
//! Function pointer for the uart write function.
typedef int (*uart_fp_write_t)(const void*, const char*, int);
//! Function pointer for the uart set callback function.
typedef int (*uart_fp_set_cb_t)(const void*, const void *, const void*);
//! \brief Uart access.
struct uart_fp {
const uart_fp_open_t open; //!< Open.
const uart_fp_close_t close; //!< Close.
const uart_fp_read_t read; //!< Read.
const uart_fp_write_t write; //!< Write.
const uart_fp_set_cb_t set_cb; //!< Set callback.
};
//! \brief Uart driver object.
struct uart {
const void *arch_dep_device; //!< Architecture depended uart device.
const struct uart_fp *fp; //!< Uart access.
struct ringbuffer *buffer; //!< Intermediate buffer.
};
//! \brief Open an uart device.
//! \param this The uart device to open.
//! \retval -1 in error case.
int uart_open(const struct uart *this);
//! \brief Close an uart device.
//! \param this The uart device to close.
//! \retval -1 in error case.
int uart_close(const struct uart *this);
//! \brief Read from an uart device.
//! \param this The uart device to read from.
//! \param buffer The buffer to read to.
//! \param len The size of the buffer.
//! \retval -1 in error case, otherwise the number of read characters.
int uart_read(const struct uart *this, char *buffer, int len);
//! \brief Write to an uart device.
//! \param this The uart device to write to.
//! \param buffer The buffer to write.
//! \param len The number of characters to write.
//! \retval -1 in error case, otherwise the number of written characters.
int uart_write(const struct uart *this, const char *buffer, int len);
#endif /* UART_H_ */

View File

@@ -0,0 +1,218 @@
//! \file rtc.c
//! \author tkl
//! \date Jul 8, 2012
//! \brief Source file of the architecture independent rtc implementation.
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "rtc.h"
//-----------------------------------------------------------------------------
int rtc_open(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_open_t open = device->fp->open;
return (open(device->arch_dep_device));
}
//-----------------------------------------------------------------------------
int rtc_close(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_close_t close = device->fp->close;
return (close(device->arch_dep_device));
}
//-----------------------------------------------------------------------------
void rtc_set_time(const struct rtc *device, const struct loki_time *time) {
if(NULL == device) {
return;
}
rtc_fp_set_time_t set_time = device->fp->set_time;
set_time(device->arch_dep_device, time);
}
//-----------------------------------------------------------------------------
struct loki_time *rtc_get_time(const struct rtc *device, struct loki_time *time) {
if(NULL == device) {
return (NULL);
}
rtc_fp_get_time_t get_time = device->fp->get_time;
return (get_time(device->arch_dep_device, time));
}
#ifndef __isleap
//! Nonzero if YEAR is a leap year (every 4 years, except every 100th isn't, and every 400th is).
#define __isleap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
#endif
//! Seconds per hour.
#define SECS_PER_HOUR (long)(60 * 60)
//! Seconds per day.
#define SECS_PER_DAY (long)(SECS_PER_HOUR * 24)
//! Clocks per sec.
#define CLOCKS_PER_SEC 1000
static const uint8_t __mon_lengths[2][12] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, /* Normal years. */
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } /* Leap years. */
};
//-----------------------------------------------------------------------------
uint32_t time_to_tick(const struct loki_time *time) {
if(NULL == time) {
return (0);
}
uint32_t ret = 0;
uint32_t year = time->year - 1970;
ret = time->sec + time->min * 60 + time->hour * 3600;
uint32_t days_in_year = 0;
switch(time->mon) {
case 1:
days_in_year = time->day;
break;
case 2:
days_in_year = time->day + 31;
break;
case 3:
days_in_year = time->day + 31 + 28;
break;
case 4:
days_in_year = time->day + 31 + 28 + 31;
break;
case 5:
days_in_year = time->day + 31 + 28 + 31 + 30;
break;
case 6:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31;
break;
case 7:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30;
break;
case 8:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31;
break;
case 9:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31;
break;
case 10:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30;
break;
case 11:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31;
break;
case 12:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30;
break;
}
if(days_in_year > 0) {
days_in_year--;
}
uint32_t leap_days = 0;
uint32_t y = time->year;
while(y >= 1970) {
leap_days += __isleap(y) ? 1 : 0;
y--;
}
if(__isleap(time->year)) {
if(days_in_year < 59) {
if(leap_days > 0) {
leap_days--;
}
}
}
ret += (days_in_year + leap_days) * 60 * 60 * 24;
ret += (year * 60 * 60 * 24 * 365);
return (ret);
}
//-----------------------------------------------------------------------------
struct loki_time tick_to_time(uint32_t tick) {
struct loki_time ret;
uint32_t days, rem;
uint32_t y;
char *ip;
days = tick / SECS_PER_DAY;
rem = tick % SECS_PER_DAY;
while (rem < 0) {
rem += SECS_PER_DAY;
--days;
}
while (rem >= SECS_PER_DAY) {
rem -= SECS_PER_DAY;
++days;
}
ret.hour = rem / SECS_PER_HOUR;
rem %= SECS_PER_HOUR;
ret.min = rem / 60;
ret.sec = rem % 60;
y = 1970;
while (days >= (rem = __isleap(y) ? 366 : 365)) {
++y;
days -= rem;
}
while (days < 0) {
--y;
days += __isleap(y) ? 366 : 365;
}
ret.year = y;
ip = (char *)__mon_lengths[__isleap(y)];
for (y = 0; days >= ip[y]; ++y)
days -= ip[y];
ret.mon = y + 1;
ret.day = days + 1;
return (ret);
}
//-----------------------------------------------------------------------------
int rtc_start_interval_event(const struct rtc *device, enum rtc_interval interval,
const void *callback, const void *argument) {
if(NULL == device) {
return (-1);
}
rtc_fp_start_interval_event start_interval = device->fp->start_interval;
return (start_interval(device->arch_dep_device, interval, callback, argument));
}
//-----------------------------------------------------------------------------
int rtc_stop_interval_event(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_stop_interval_event stop_interval = device->fp->stop_interval;
return (stop_interval(device->arch_dep_device));
}
//-----------------------------------------------------------------------------
int rtc_start_alarm_event(const struct rtc *device,
const struct loki_time *alarm_time, enum rtc_alarm_mask alarm_mask,
const void *callback, const void *argument)
{
if(NULL == device) {
return (-1);
}
rtc_fp_start_alarm_event start_alarm = device->fp->start_alarm;
return (start_alarm(device->arch_dep_device, alarm_time, alarm_mask,
callback, argument));
}
//-----------------------------------------------------------------------------
int rtc_stop_alarm_event(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_stop_alarm_event stop_alarm = device->fp->stop_alarm;
return (stop_alarm(device->arch_dep_device));
}

View File

@@ -0,0 +1,51 @@
//! \file spi.c
//! \author tkl
//! \date Feb 11, 2012
//! \brief Source file of the architecture independent spi driver.
#include <stddef.h>
#include "spi.h"
//-----------------------------------------------------------------------------
int spi_open(const struct spi *device) {
if(device == NULL) {
return -1;
}
spi_fp_open_t open = device->fp->open;
return open(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
int spi_close(const struct spi *device) {
if(device == NULL) {
return -1;
}
spi_fp_close_t close = device->fp->close;
return close(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
void spi_assert_cs(const struct spi * device) {
if(device == NULL) {
return;
}
spi_fp_assert_cs_t assert_cs = device->fp->assert_cs;
assert_cs(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
void spi_deassert_cs(const struct spi * device) {
if(device == NULL) {
return;
}
spi_fp_deassert_cs_t deassert_cs = device->fp->deassert_cs;
deassert_cs(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
char spi_rxtx_byte(const struct spi * device, char byte) {
if(device == NULL) {
return 0;
}
spi_fp_rxtx_byte_t rxtx_byte = device->fp->rxtx_byte;
return rxtx_byte(device->arch_dep_device, byte);
}

View File

@@ -0,0 +1,35 @@
//! \file timer.c
//! \author tkl
//! \date Jul 5, 2012
//! \brief Source file of the architecture independent timer implementation.
#include <stddef.h>
#include "timer.h"
int timer_open(const struct loki_timer *device)
{
if(device == NULL)
return -1;
timer_fp_open_t open = device->fp->open;
return open(device->arch_dep_device);
}
int timer_close(const struct loki_timer *device)
{
if(device == NULL)
return -1;
timer_fp_close_t close = device->fp->close;
return close(device->arch_dep_device);
}
int timer_set_it_callback(const struct loki_timer *device, const void *callback,
const void *param)
{
if((device == NULL) || (callback == NULL))
return -1;
timer_fp_set_cb_t set_cb = device->fp->set_cb;
return set_cb(device->arch_dep_device, callback, param);
}

View File

@@ -0,0 +1,80 @@
//! \file uart.c
//! \author tkl
//! \date Jul 15, 2012
//! \brief Source file of the architecture independent uart implementation.
#include <stddef.h>
#include <stdbool.h>
#include "driver.h"
#include "ringbuffer.h"
#include "irq.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "schedule.h"
#include "kernel.h"
#include "uart.h"
extern volatile struct thread_context *current_thread;
static const void *uart_it_callback(const void *param);
int uart_open(const struct uart *this)
{
if(NULL == this)
return (-1);
int ret = this->fp->set_cb(this->arch_dep_device, uart_it_callback, this);
ret |= this->fp->open(this->arch_dep_device);
return (ret);
}
int uart_close(const struct uart *this)
{
if(NULL == this)
return (-1);
blocking_read_wakeup((const void *)this);
return (this->fp->close(this->arch_dep_device));
}
int uart_read(const struct uart *this, char *buffer, int len)
{
int ret = -1;
unsigned int irq;
if(NULL == this)
return (-1);
irq = disable_irq();
if(ringbuffer_is_empty(this->buffer)) {
current_thread->status = THREAD_STATUS_BLOCKING;
current_thread->wakeup_blocking_source = (void*) this;
restore_irq(irq);
schedule();
}
ret = ringbuffer_read(this->buffer, buffer, len);
restore_irq(irq);
return ret;
}
int uart_write(const struct uart *this, const char *buffer, int len)
{
if(NULL == this)
return (-1);
return (this->fp->write(this->arch_dep_device, buffer, len));
}
static const void *uart_it_callback(const void *param)
{
if(NULL == param)
return (NULL);
char c = 0;
struct uart *uart = (struct uart *)param;
uart->fp->read((const void *)uart->arch_dep_device, &c, 1);
if(!ringbuffer_is_full(uart->buffer))
ringbuffer_write(uart->buffer, &c, 1);
blocking_read_wakeup(param);
return (param);
}

View File

@@ -0,0 +1,18 @@
/*
* ctx.h
*
* Created on: Feb 20, 2015
* Author: tkl
*/
#ifndef CTX_H_
#define CTX_H_
#ifdef ARCH_MSP430
#include "msp430_ctx.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_ctx.h"
#endif
#endif /* CTX_H_ */

View File

@@ -0,0 +1,17 @@
/*
* irq.h
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#ifndef IRQ_H_
#define IRQ_H_
#ifdef ARCH_MSP430
#include "msp430_irq.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_irq.h"
#endif
#endif /* IRQ_H_ */

View File

@@ -0,0 +1,15 @@
/*
* isr.h
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#ifndef ISR_H_
#define ISR_H_
#ifdef ARCH_MSP430
#include "msp430_isr.h"
#endif
#endif /* ISR_H_ */

View File

@@ -0,0 +1,24 @@
/*
* list.h
*
* Created on: Jul 27, 2016
* Author: tkl
*/
#ifndef SOURCE_FIRMWARE_KERNEL_LIST_H_
#define SOURCE_FIRMWARE_KERNEL_LIST_H_
struct list_node {
struct list_node *next;
unsigned int data;
};
struct list {
struct list_node *front;
struct list_node *rear;
};
int list_init(struct list *head);
int list_add(struct list *head, struct list_node *node);
#endif /* SOURCE_FIRMWARE_KERNEL_LIST_H_ */

View File

@@ -0,0 +1,18 @@
/*
* low_power.h
*
* Created on: Feb 17, 2015
* Author: tkl
*/
#ifndef LOW_POWER_H_
#define LOW_POWER_H_
#ifdef ARCH_MSP430
#include "msp430_low_power.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_low_power.h"
#endif
#endif /* LOW_POWER_H_ */

View File

@@ -0,0 +1,49 @@
/*
* ringbuffer.h
*
* Created on: Jul 24, 2012
* Author: tkl
*/
#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_
//-----------------------------------------------------------------------------
//! \brief A ring buffer object.
struct ringbuffer {
char *buffer; //!< The buffer.
char *read; //!< Read access.
char *write; //!< Write access.
int size; //!< Buffer size.
int used; //!< Buffer in use.
};
//-----------------------------------------------------------------------------
//! \brief Read out n characters from ring buffer.
//! \param this The ring buffer to read from.
//! \param buffer to read to.
//! \param size The maximum number of characters to read.
//! \retval -1 in error case, otherwise the number of read characters.
int ringbuffer_read(struct ringbuffer *this, char *buffer, int size);
//-----------------------------------------------------------------------------
//! \brief Write n characters to ring buffer.
//! \param this The ring buffer to write to.
//! \param buffer to write.
//! \param size The number of characters to write.
//! \retval -1 in error case, otherwise the number of written characters.
int ringbuffer_write(struct ringbuffer *this, const char *buffer, int size);
//-----------------------------------------------------------------------------
//! \brief Check if ring buffer is full.
//! \param this The ring buffer to check.
//! \retval -1 in error case, otherwise 1 (true) / 0 (false).
int ringbuffer_is_full(const struct ringbuffer *this);
//-----------------------------------------------------------------------------
//! \brief Check if ring buffer is empty.
//! \param this The ring buffer to check.
//! \retval -1 in error case, otherwise 1 (true) / 0 (false).
int ringbuffer_is_empty(const struct ringbuffer *this);
#endif /* RINGBUFFER_H_ */

View File

@@ -0,0 +1,20 @@
/*
* schedule.h
*
* Created on: Feb 20, 2015
* Author: tkl
*/
#ifndef SCHEDULE_H_
#define SCHEDULE_H_
#ifdef ARCH_MSP430
#include "msp430_schedule.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_ctx.h"
#endif
#define schedule() arch_schedule()
#endif /* SCHEDULE_H_ */

View File

@@ -0,0 +1,20 @@
/*
* semaphore.h
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#ifndef SEMAPHORE_H_
#define SEMAPHORE_H_
struct semaphore {
int cnt;
struct queue queue;
};
int semaphore_init(struct semaphore *sem, int value);
int semaphore_wait(struct semaphore *sem);
int semaphore_post(struct semaphore *sem);
#endif /* SEMAPHORE_H_ */

View File

@@ -0,0 +1,18 @@
/*
* stack.h
*
* Created on: Sep 27, 2015
* Author: tkl
*/
#ifndef STACK_H_
#define STACK_H_
#ifdef ARCH_MSP430
#include "msp430_stack.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_stack.h"
#endif
#endif /* STACK_H_ */

View File

@@ -0,0 +1,13 @@
/*
* sys_tick.h
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#ifndef SYS_TICK_H_
#define SYS_TICK_H_
void sys_tick_init(const struct loki_timer *hw_timer);
#endif /* SYS_TICK_H_ */

View File

@@ -0,0 +1,22 @@
/*
* thread.h
*
* Created on: Apr 13, 2015
* Author: tkl
*/
#ifndef THREAD_H_
#define THREAD_H_
#define MAX_THREAD_COUNT 32
struct thread_list {
unsigned int count; //<! Number of elements in list
struct thread_context *list[MAX_THREAD_COUNT];
};
void thread_init(void);
void thread_switch_context(void);
void blocking_read_wakeup(const void *src);
#endif /* THREAD_H_ */

View File

@@ -0,0 +1,30 @@
/*
* driver.h
*
* Created on: Jul 27, 2016
* Author: tkl
*/
#ifndef SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_
#define SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_
enum driver_type {
DRIVER_TYPE_ADC,
DRIVER_TYPE_GPIO,
DRIVER_TYPE_I2C,
DRIVER_TYPE_RTC,
DRIVER_TYPE_SPI,
DRIVER_TYPE_UART
};
struct driver {
enum driver_type driver_type;
const void *device_driver;
};
int open(const struct driver *driver);
int close(const struct driver *driver);
int read(const struct driver *driver, char *buffer, int len);
int write(const struct driver *driver, const char *buffer, int len);
#endif /* SOURCE_FIRMWARE_KERNEL_DRIVER_INCLUDE_DRIVER_H_ */

View File

@@ -0,0 +1,51 @@
/*
* kernel.h
*
* Created on: Jul 28, 2016
* Author: tkl
*/
#ifndef SOURCE_FIRMWARE_KERNEL_INTERFACE_KERNEL_H_
#define SOURCE_FIRMWARE_KERNEL_INTERFACE_KERNEL_H_
void schedule_start(void);
enum thread_priority {
THREAD_PRIO_IDLE = 0,
THREAD_PRIO_LOW,
THREAD_PRIO_MEDIUM,
THREAD_PRIO_HIGH
};
enum thread_status {
THREAD_STATUS_INIT = 0,
THREAD_STATUS_EXECUTING,
THREAD_STATUS_WAITING,
THREAD_STATUS_SLEEPING,
THREAD_STATUS_BLOCKING
};
struct thread_context {
stack_t *sp; /**< thread's stack pointer */
stack_t *stack; /**< thread's stack start address */
unsigned int stack_size; /**< thread's stack size */
unsigned int pid; /**< thread's process id */
enum thread_priority priority; /**< thread's priority */
enum thread_status status; /**< thread's status */
unsigned long next_executing_time;
void *wakeup_blocking_source;
struct queue_node sem_queue_node;
};
struct thread_context *thread_create(
struct thread_context *thread,
stack_t *stack,
unsigned int stack_size,
void (*thread_func)(void *),
void *arg,
enum thread_priority priority);
void thread_exit(void);
void sleep_ms(unsigned int ms);
#endif /* SOURCE_FIRMWARE_KERNEL_INTERFACE_KERNEL_H_ */

View File

@@ -0,0 +1,26 @@
/*
* queue.h
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#ifndef QUEUE_H_
#define QUEUE_H_
struct queue_node {
struct queue_node *next;
unsigned int data;
};
struct queue {
struct queue_node *front;
struct queue_node *rear;
};
int queue_init(struct queue *head);
int queue_push(struct queue *head, struct queue_node *node);
int queue_pop(struct queue *head, struct queue_node *node);
bool queue_is_empty(struct queue *head);
#endif /* QUEUE_H_ */

View File

@@ -0,0 +1,7 @@
CHECK_FOLDER += firmware/kernel
SUB_FOLDER += firmware/kernel
INCLUDES += firmware/kernel/include
INCLUDES += firmware/kernel/interface
DOC_SRC += firmware/kernel
include firmware/kernel/driver/driver.mk

View File

@@ -0,0 +1,36 @@
/*
* list.c
*
* Created on: Jul 27, 2016
* Author: tkl
*/
#include "stddef.h"
#include "list.h"
int list_init(struct list *head)
{
if(NULL == head)
return -1;
head->front = NULL;
head->rear = NULL;
return 0;
}
int list_add(struct list *head, struct list_node *node)
{
if((NULL == head) || (NULL == node))
return -1;
if(head->front == NULL) {
head->front = node;
head->rear = node;
}
else {
head->rear->next = node;
head->rear = node;
}
return 1;
}

View File

@@ -0,0 +1,64 @@
/*
* queue.c
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "queue.h"
int queue_init(struct queue *head)
{
if(NULL == head)
return -1;
head->front = NULL;
head->rear = NULL;
return 0;
}
int queue_push(struct queue *head, struct queue_node *node)
{
if((NULL == head) || (NULL == node))
return -1;
if(head->front == NULL) {
head->front = node;
head->rear = node;
}
else {
head->rear->next = node;
head->rear = node;
}
return 1;
}
int queue_pop(struct queue *head, struct queue_node *node)
{
if(NULL == head)
return -1;
if(head->front == NULL)
return 0;
else {
memcpy(node, head->front, sizeof(struct queue_node));
head->front = node->next;
return 1;
}
return 0;
}
bool queue_is_empty(struct queue *head)
{
if(NULL == head)
return false;
if(head->front == NULL)
return true;
return false;
}

View File

@@ -0,0 +1,64 @@
/*
* ringbuffer.c
*
* Created on: Jul 24, 2012
* Author: tkl
*/
#include "irq.h"
#include "ringbuffer.h"
//-----------------------------------------------------------------------------
int ringbuffer_read(struct ringbuffer *this, char *buffer, int size) {
int i;
unsigned int irq;
for(i = 0; i < size; i++) {
if(this->used > 0) {
irq = disable_irq();
buffer[i] = *this->read;
this->read++;
this->used--;
if(this->read >= (this->buffer + this->size)) {
this->read = this->buffer;
}
restore_irq(irq);
}
else {
return i;
}
}
return 0;
}
//-----------------------------------------------------------------------------
int ringbuffer_write(struct ringbuffer *this, const char *buffer,
int size)
{
int i = 0;
unsigned int irq;
for(i = 0; i < size; i++) {
if(this->used < this->size) {
irq = disable_irq();
*this->write = buffer[i];
this->write++;
this->used++;
if(this->write >= (this->buffer + this->size)) {
this->write = this->buffer;
}
restore_irq(irq);
}
else {
return i;
}
}
return i;
}
//-----------------------------------------------------------------------------
int ringbuffer_is_full(const struct ringbuffer *this) {
return (this->used == this->size) ? 1 : 0;
}
//-----------------------------------------------------------------------------
int ringbuffer_is_empty(const struct ringbuffer *this) {
return (this->used == 0) ? 1 : 0;
}

View File

@@ -0,0 +1,38 @@
/*
* schedule.c
*
* Created on: Feb 20, 2015
* Author: tkl
*/
#include <stdbool.h>
#include "board.h"
#include "ctx.h"
#include "cpu.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "irq.h"
#include "schedule.h"
#include "low_power.h"
#include "kernel.h"
extern volatile struct thread_list threads;
volatile struct thread_context *current_thread;
static struct thread_context idle_task;
static stack_t idle_stack[22]; /* 30 didn't work with tx test app. why? */
void idle_func(void *arg)
{
while(1) {
enter_low_power();
}
}
void schedule_start(void)
{
thread_create(&idle_task, idle_stack, sizeof(idle_stack), idle_func, NULL, THREAD_PRIO_IDLE);
current_thread = threads.list[0];
enable_irq();
start_first_task();
}

View File

@@ -0,0 +1,70 @@
/*
* semaphore.c
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#include <stdbool.h>
#include <stddef.h>
#include "irq.h"
#include "queue.h"
#include "semaphore.h"
#include "stack.h"
#include "thread.h"
#include "schedule.h"
#include "kernel.h"
extern volatile struct thread_context *current_thread;
int semaphore_init(struct semaphore *sem, int value)
{
if(NULL == sem)
return -1;
sem->cnt = value;
queue_init(&sem->queue);
return 0;
}
int semaphore_wait(struct semaphore *sem)
{
unsigned int irq_state;
if(NULL == sem)
return -1;
irq_state = disable_irq();
if(sem->cnt > 0) {
sem->cnt--;
restore_irq(irq_state);
}
else {
current_thread->sem_queue_node.data = (unsigned int) current_thread;
queue_push(&sem->queue, (struct queue_node *)&current_thread->sem_queue_node);
current_thread->status = THREAD_STATUS_WAITING;
restore_irq(irq_state);
schedule();
}
return 0;
}
int semaphore_post(struct semaphore *sem)
{
unsigned int irq_state;
if(NULL == sem)
return -1;
irq_state = disable_irq();
if(queue_is_empty(&sem->queue))
sem->cnt++;
else {
struct queue_node next;
queue_pop(&sem->queue, &next);
struct thread_context *ctx = (struct thread_context *) next.data;
ctx->status = THREAD_STATUS_EXECUTING;
restore_irq(irq_state);
schedule();
}
restore_irq(irq_state);
return 0;
}

View File

@@ -0,0 +1,71 @@
/*
* sys_tick.c
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#include "irq.h"
#include "timer.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "schedule.h"
#include "kernel.h"
#include "sys_tick.h"
struct sys_tick_obj
{
struct loki_timer *hw_timer;
unsigned long tick;
unsigned int used;
};
extern volatile struct thread_context *current_thread;
extern volatile struct thread_list threads;
static struct sys_tick_obj sys_tick_obj;
void *timer_cb(void *arg)
{
int i;
sys_tick_obj.tick++;
for(i = 0; i < threads.count; i++) {
if(threads.list[i]->status == THREAD_STATUS_SLEEPING) {
if(threads.list[i]->next_executing_time <= sys_tick_obj.tick) {
threads.list[i]->status = THREAD_STATUS_EXECUTING;
sys_tick_obj.used--;
if(sys_tick_obj.used == 0)
timer_close(sys_tick_obj.hw_timer);
}
}
}
return arg;
}
void sys_tick_init(const struct loki_timer *hw_timer)
{
if(NULL == hw_timer)
return;
sys_tick_obj.tick = 0;
sys_tick_obj.used = 0;
sys_tick_obj.hw_timer = (struct loki_timer *)hw_timer;
timer_set_it_callback(hw_timer, timer_cb, NULL);
}
void sleep_ms(unsigned int ms)
{
int irq;
irq = disable_irq();
current_thread->next_executing_time = sys_tick_obj.tick + ms;
current_thread->status = THREAD_STATUS_SLEEPING;
sys_tick_obj.used++;
if(sys_tick_obj.used == 1)
timer_open(sys_tick_obj.hw_timer);
restore_irq(irq);
schedule();
}

View File

@@ -0,0 +1,148 @@
/*
* thread.c
*
* Created on: Mar 16, 2015
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#include "irq.h"
#include "stack.h"
#include "ctx.h"
#include "queue.h"
#include "kernel.h"
#include "thread.h"
extern volatile struct thread_context *current_thread;
volatile struct thread_list threads;
void thread_init(void)
{
int i;
for(i = 0; i < MAX_THREAD_COUNT; i++)
threads.list[i] = NULL;
threads.count = 0;
}
static void sort_thread_list_by_priority(void)
{
unsigned int irq, in, out;
struct thread_context *tmp;
irq = disable_irq();
for(out = 0; out < threads.count; out++) {
for(in = 0; in < threads.count - out - 1; in++) {
if(threads.list[in]->priority < threads.list[in + 1]->priority) {
tmp = threads.list[in];
threads.list[in] = threads.list[in + 1];
threads.list[in + 1] = tmp;
}
}
}
restore_irq(irq);
}
static int thread_list_add_node(struct thread_context *node)
{
unsigned int irq;
int i = -1;
if((NULL == node) || (threads.count >= MAX_THREAD_COUNT))
return i;
irq = disable_irq();
for(i = 0; i < MAX_THREAD_COUNT; i++) {
if(threads.list[i] == NULL) {
threads.list[i] = node;
threads.count++;
sort_thread_list_by_priority();
break;
}
}
restore_irq(irq);
return i;
}
static void thread_list_defragment(void)
{
int i;
unsigned int irq_state = disable_irq();
for(i = 0; i < (MAX_THREAD_COUNT - 1); i++) {
if((threads.list[i] == NULL) && (threads.list[i + 1] != NULL)) {
threads.list[i] = threads.list[i + 1];
threads.list[i + 1] = NULL;
}
}
restore_irq(irq_state);
}
static int thread_list_remove_node(struct thread_context *node)
{
int i = -1;
unsigned int irq_state;
if(NULL == node)
return i;
irq_state = disable_irq();
for(i = 0; i < MAX_THREAD_COUNT; i++) {
if(threads.list[i] == node) {
threads.list[i] = NULL;
threads.count--;
thread_list_defragment();
break;
}
}
restore_irq(irq_state);
return i;
}
struct thread_context *thread_create(
struct thread_context *thread,
stack_t *stack,
unsigned int stack_size,
void (*thread_func)(void *),
void *arg,
enum thread_priority priority)
{
if((thread == NULL) || (stack == NULL) || (thread_func == NULL) ||
(stack_size == 0))
return NULL;
thread->pid = threads.count;
thread->stack = stack;
thread->stack_size = stack_size;
thread->sp = stack_init(thread_func, arg, stack, stack_size);
thread->status = THREAD_STATUS_EXECUTING;
thread->priority = priority;
thread_list_add_node(thread);
return thread;
}
void thread_switch_context(void) {
int i;
for(i = 0; i < threads.count; i++) {
if(threads.list[i]->status == THREAD_STATUS_EXECUTING) {
current_thread = threads.list[i];
return;
}
}
}
void thread_exit(void)
{
disable_irq();
thread_list_remove_node((struct thread_context *)current_thread);
thread_switch_context();
restore_context();
}
void blocking_read_wakeup(const void *src)
{
int i;
for(i = 0; i < threads.count; i++) {
if( (threads.list[i]->status == THREAD_STATUS_BLOCKING) &&
(threads.list[i]->wakeup_blocking_source == src))
threads.list[i]->status = THREAD_STATUS_EXECUTING;
}
}