initial commit
This commit is contained in:
280
source/firmware/kernel/ascii_font.h
Normal file
280
source/firmware/kernel/ascii_font.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* ascii_font.h
|
||||
*
|
||||
* Created on: Jan 15, 2016
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef ASCII_FONT_H_
|
||||
#define ASCII_FONT_H_
|
||||
|
||||
#include "font.h"
|
||||
|
||||
static const unsigned char ascii_font[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
|
||||
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
|
||||
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
|
||||
0x18, 0x3C, 0x7E, 0x3C, 0x18,
|
||||
0x1C, 0x57, 0x7D, 0x57, 0x1C,
|
||||
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
|
||||
0x00, 0x18, 0x3C, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
|
||||
0x00, 0x18, 0x24, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
|
||||
0x30, 0x48, 0x3A, 0x06, 0x0E,
|
||||
0x26, 0x29, 0x79, 0x29, 0x26,
|
||||
0x40, 0x7F, 0x05, 0x05, 0x07,
|
||||
0x40, 0x7F, 0x05, 0x25, 0x3F,
|
||||
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
|
||||
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
|
||||
0x14, 0x22, 0x7F, 0x22, 0x14,
|
||||
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
|
||||
0x06, 0x09, 0x7F, 0x01, 0x7F,
|
||||
0x00, 0x66, 0x89, 0x95, 0x6A,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60,
|
||||
0x94, 0xA2, 0xFF, 0xA2, 0x94,
|
||||
0x08, 0x04, 0x7E, 0x04, 0x08,
|
||||
0x10, 0x20, 0x7E, 0x20, 0x10,
|
||||
0x08, 0x08, 0x2A, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x2A, 0x08, 0x08,
|
||||
0x1E, 0x10, 0x10, 0x10, 0x10,
|
||||
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
|
||||
0x30, 0x38, 0x3E, 0x38, 0x30,
|
||||
0x06, 0x0E, 0x3E, 0x0E, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5F, 0x00, 0x00,
|
||||
0x00, 0x07, 0x00, 0x07, 0x00,
|
||||
0x14, 0x7F, 0x14, 0x7F, 0x14,
|
||||
0x24, 0x2A, 0x7F, 0x2A, 0x12,
|
||||
0x23, 0x13, 0x08, 0x64, 0x62,
|
||||
0x36, 0x49, 0x56, 0x20, 0x50,
|
||||
0x00, 0x08, 0x07, 0x03, 0x00,
|
||||
0x00, 0x1C, 0x22, 0x41, 0x00,
|
||||
0x00, 0x41, 0x22, 0x1C, 0x00,
|
||||
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
|
||||
0x08, 0x08, 0x3E, 0x08, 0x08,
|
||||
0x00, 0x80, 0x70, 0x30, 0x00,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x60, 0x60, 0x00,
|
||||
0x20, 0x10, 0x08, 0x04, 0x02,
|
||||
0x3E, 0x51, 0x49, 0x45, 0x3E,
|
||||
0x00, 0x42, 0x7F, 0x40, 0x00,
|
||||
0x72, 0x49, 0x49, 0x49, 0x46,
|
||||
0x21, 0x41, 0x49, 0x4D, 0x33,
|
||||
0x18, 0x14, 0x12, 0x7F, 0x10,
|
||||
0x27, 0x45, 0x45, 0x45, 0x39,
|
||||
0x3C, 0x4A, 0x49, 0x49, 0x31,
|
||||
0x41, 0x21, 0x11, 0x09, 0x07,
|
||||
0x36, 0x49, 0x49, 0x49, 0x36,
|
||||
0x46, 0x49, 0x49, 0x29, 0x1E,
|
||||
0x00, 0x00, 0x14, 0x00, 0x00,
|
||||
0x00, 0x40, 0x34, 0x00, 0x00,
|
||||
0x00, 0x08, 0x14, 0x22, 0x41,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x00, 0x41, 0x22, 0x14, 0x08,
|
||||
0x02, 0x01, 0x59, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x5D, 0x59, 0x4E,
|
||||
0x7C, 0x12, 0x11, 0x12, 0x7C,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x36,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x22,
|
||||
0x7F, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x41,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x01,
|
||||
0x3E, 0x41, 0x41, 0x51, 0x73,
|
||||
0x7F, 0x08, 0x08, 0x08, 0x7F,
|
||||
0x00, 0x41, 0x7F, 0x41, 0x00,
|
||||
0x20, 0x40, 0x41, 0x3F, 0x01,
|
||||
0x7F, 0x08, 0x14, 0x22, 0x41,
|
||||
0x7F, 0x40, 0x40, 0x40, 0x40,
|
||||
0x7F, 0x02, 0x1C, 0x02, 0x7F,
|
||||
0x7F, 0x04, 0x08, 0x10, 0x7F,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x51, 0x21, 0x5E,
|
||||
0x7F, 0x09, 0x19, 0x29, 0x46,
|
||||
0x26, 0x49, 0x49, 0x49, 0x32,
|
||||
0x03, 0x01, 0x7F, 0x01, 0x03,
|
||||
0x3F, 0x40, 0x40, 0x40, 0x3F,
|
||||
0x1F, 0x20, 0x40, 0x20, 0x1F,
|
||||
0x3F, 0x40, 0x38, 0x40, 0x3F,
|
||||
0x63, 0x14, 0x08, 0x14, 0x63,
|
||||
0x03, 0x04, 0x78, 0x04, 0x03,
|
||||
0x61, 0x59, 0x49, 0x4D, 0x43,
|
||||
0x00, 0x7F, 0x41, 0x41, 0x41,
|
||||
0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x00, 0x41, 0x41, 0x41, 0x7F,
|
||||
0x04, 0x02, 0x01, 0x02, 0x04,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40,
|
||||
0x00, 0x03, 0x07, 0x08, 0x00,
|
||||
0x20, 0x54, 0x54, 0x78, 0x40,
|
||||
0x7F, 0x28, 0x44, 0x44, 0x38,
|
||||
0x38, 0x44, 0x44, 0x44, 0x28,
|
||||
0x38, 0x44, 0x44, 0x28, 0x7F,
|
||||
0x38, 0x54, 0x54, 0x54, 0x18,
|
||||
0x00, 0x08, 0x7E, 0x09, 0x02,
|
||||
0x18, 0xA4, 0xA4, 0x9C, 0x78,
|
||||
0x7F, 0x08, 0x04, 0x04, 0x78,
|
||||
0x00, 0x44, 0x7D, 0x40, 0x00,
|
||||
0x20, 0x40, 0x40, 0x3D, 0x00,
|
||||
0x7F, 0x10, 0x28, 0x44, 0x00,
|
||||
0x00, 0x41, 0x7F, 0x40, 0x00,
|
||||
0x7C, 0x04, 0x78, 0x04, 0x78,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x78,
|
||||
0x38, 0x44, 0x44, 0x44, 0x38,
|
||||
0xFC, 0x18, 0x24, 0x24, 0x18,
|
||||
0x18, 0x24, 0x24, 0x18, 0xFC,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x08,
|
||||
0x48, 0x54, 0x54, 0x54, 0x24,
|
||||
0x04, 0x04, 0x3F, 0x44, 0x24,
|
||||
0x3C, 0x40, 0x40, 0x20, 0x7C,
|
||||
0x1C, 0x20, 0x40, 0x20, 0x1C,
|
||||
0x3C, 0x40, 0x30, 0x40, 0x3C,
|
||||
0x44, 0x28, 0x10, 0x28, 0x44,
|
||||
0x4C, 0x90, 0x90, 0x90, 0x7C,
|
||||
0x44, 0x64, 0x54, 0x4C, 0x44,
|
||||
0x00, 0x08, 0x36, 0x41, 0x00,
|
||||
0x00, 0x00, 0x77, 0x00, 0x00,
|
||||
0x00, 0x41, 0x36, 0x08, 0x00,
|
||||
0x02, 0x01, 0x02, 0x04, 0x02,
|
||||
0x3C, 0x26, 0x23, 0x26, 0x3C,
|
||||
0x1E, 0xA1, 0xA1, 0x61, 0x12,
|
||||
0x3A, 0x40, 0x40, 0x20, 0x7A,
|
||||
0x38, 0x54, 0x54, 0x55, 0x59,
|
||||
0x21, 0x55, 0x55, 0x79, 0x41,
|
||||
0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
|
||||
0x21, 0x55, 0x54, 0x78, 0x40,
|
||||
0x20, 0x54, 0x55, 0x79, 0x40,
|
||||
0x0C, 0x1E, 0x52, 0x72, 0x12,
|
||||
0x39, 0x55, 0x55, 0x55, 0x59,
|
||||
0x39, 0x54, 0x54, 0x54, 0x59,
|
||||
0x39, 0x55, 0x54, 0x54, 0x58,
|
||||
0x00, 0x00, 0x45, 0x7C, 0x41,
|
||||
0x00, 0x02, 0x45, 0x7D, 0x42,
|
||||
0x00, 0x01, 0x45, 0x7C, 0x40,
|
||||
0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
|
||||
0xF0, 0x28, 0x25, 0x28, 0xF0,
|
||||
0x7C, 0x54, 0x55, 0x45, 0x00,
|
||||
0x20, 0x54, 0x54, 0x7C, 0x54,
|
||||
0x7C, 0x0A, 0x09, 0x7F, 0x49,
|
||||
0x32, 0x49, 0x49, 0x49, 0x32,
|
||||
0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
|
||||
0x32, 0x4A, 0x48, 0x48, 0x30,
|
||||
0x3A, 0x41, 0x41, 0x21, 0x7A,
|
||||
0x3A, 0x42, 0x40, 0x20, 0x78,
|
||||
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
|
||||
0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
|
||||
0x3D, 0x40, 0x40, 0x40, 0x3D,
|
||||
0x3C, 0x24, 0xFF, 0x24, 0x24,
|
||||
0x48, 0x7E, 0x49, 0x43, 0x66,
|
||||
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
|
||||
0xFF, 0x09, 0x29, 0xF6, 0x20,
|
||||
0xC0, 0x88, 0x7E, 0x09, 0x03,
|
||||
0x20, 0x54, 0x54, 0x79, 0x41,
|
||||
0x00, 0x00, 0x44, 0x7D, 0x41,
|
||||
0x30, 0x48, 0x48, 0x4A, 0x32,
|
||||
0x38, 0x40, 0x40, 0x22, 0x7A,
|
||||
0x00, 0x7A, 0x0A, 0x0A, 0x72,
|
||||
0x7D, 0x0D, 0x19, 0x31, 0x7D,
|
||||
0x26, 0x29, 0x29, 0x2F, 0x28,
|
||||
0x26, 0x29, 0x29, 0x29, 0x26,
|
||||
0x30, 0x48, 0x4D, 0x40, 0x20,
|
||||
0x38, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x38,
|
||||
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
|
||||
0x2F, 0x10, 0x28, 0x34, 0xFA,
|
||||
0x00, 0x00, 0x7B, 0x00, 0x00,
|
||||
0x08, 0x14, 0x2A, 0x14, 0x22,
|
||||
0x22, 0x14, 0x2A, 0x14, 0x08,
|
||||
0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
|
||||
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
|
||||
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
|
||||
0x00, 0x00, 0x00, 0xFF, 0x00,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x00,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x00,
|
||||
0x10, 0x10, 0xFF, 0x00, 0xFF,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x14, 0x14, 0x14, 0xFC, 0x00,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xFF,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xFC,
|
||||
0x14, 0x14, 0x17, 0x10, 0x1F,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0x1F, 0x00,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x14,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x17,
|
||||
0x00, 0x00, 0xFC, 0x04, 0xF4,
|
||||
0x14, 0x14, 0x17, 0x10, 0x17,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xF4,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x17, 0x14,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0xF4, 0x14,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x14,
|
||||
0x00, 0x00, 0x00, 0xFC, 0x14,
|
||||
0x00, 0x00, 0xF0, 0x10, 0xF0,
|
||||
0x10, 0x10, 0xFF, 0x10, 0xFF,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x14,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x10,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x38, 0x44, 0x44, 0x38, 0x44,
|
||||
0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
|
||||
0x7E, 0x02, 0x02, 0x06, 0x06,
|
||||
0x02, 0x7E, 0x02, 0x7E, 0x02,
|
||||
0x63, 0x55, 0x49, 0x41, 0x63,
|
||||
0x38, 0x44, 0x44, 0x3C, 0x04,
|
||||
0x40, 0x7E, 0x20, 0x1E, 0x20,
|
||||
0x06, 0x02, 0x7E, 0x02, 0x02,
|
||||
0x99, 0xA5, 0xE7, 0xA5, 0x99,
|
||||
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
|
||||
0x4C, 0x72, 0x01, 0x72, 0x4C,
|
||||
0x30, 0x4A, 0x4D, 0x4D, 0x30,
|
||||
0x30, 0x48, 0x78, 0x48, 0x30,
|
||||
0xBC, 0x62, 0x5A, 0x46, 0x3D,
|
||||
0x3E, 0x49, 0x49, 0x49, 0x00,
|
||||
0x7E, 0x01, 0x01, 0x01, 0x7E,
|
||||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
|
||||
0x44, 0x44, 0x5F, 0x44, 0x44,
|
||||
0x40, 0x51, 0x4A, 0x44, 0x40,
|
||||
0x40, 0x44, 0x4A, 0x51, 0x40,
|
||||
0x00, 0x00, 0xFF, 0x01, 0x03,
|
||||
0xE0, 0x80, 0xFF, 0x00, 0x00,
|
||||
0x08, 0x08, 0x6B, 0x6B, 0x08,
|
||||
0x36, 0x12, 0x36, 0x24, 0x36,
|
||||
0x06, 0x0F, 0x09, 0x0F, 0x06,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00,
|
||||
0x00, 0x00, 0x10, 0x10, 0x00,
|
||||
0x30, 0x40, 0xFF, 0x01, 0x01,
|
||||
0x00, 0x1F, 0x01, 0x01, 0x1E,
|
||||
0x00, 0x19, 0x1D, 0x17, 0x12,
|
||||
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
|
||||
};
|
||||
|
||||
const struct font font_ascii_7x5 = {
|
||||
5,
|
||||
7,
|
||||
1,
|
||||
256,
|
||||
(unsigned char *)ascii_font
|
||||
};
|
||||
|
||||
#endif /* ASCII_FONT_H_ */
|
35
source/firmware/kernel/bitmap.c
Normal file
35
source/firmware/kernel/bitmap.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* canvas.c
|
||||
*
|
||||
* Created on: Jan 15, 2016
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "font.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
int bitmap_print_text(const struct font *font, struct bitmap *bitmap, int x_pos,
|
||||
int y_pos, char *text)
|
||||
{
|
||||
int i = 0, pos = 0;
|
||||
/* align to page */
|
||||
if(y_pos % 8 != 0)
|
||||
y_pos -= y_pos % 8;
|
||||
|
||||
pos = y_pos / 8 * bitmap->x_size + x_pos;
|
||||
while(text[i] != 0) {
|
||||
while(((pos + font->char_size_x) % bitmap->x_size) < font->char_size_x)
|
||||
pos++;
|
||||
memcpy(&bitmap->buffer[pos], &font->font[text[i] * font->char_size_x],
|
||||
font->char_size_x);
|
||||
memset(&bitmap->buffer[pos + font->char_size_x], 0x00,
|
||||
font->char_between);
|
||||
i++;
|
||||
pos += font->char_size_x + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
20
source/firmware/kernel/bitmap.h
Normal file
20
source/firmware/kernel/bitmap.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* bitmap.h
|
||||
*
|
||||
* Created on: Jan 15, 2016
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef BITMAP_H_
|
||||
#define BITMAP_H_
|
||||
|
||||
struct bitmap {
|
||||
int x_size;
|
||||
int y_size;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
int bitmap_print_text(const struct font *font, struct bitmap *bitmap, int x_pos,
|
||||
int y_pos, char *text);
|
||||
|
||||
#endif /* BITMAP_H_ */
|
18
source/firmware/kernel/ctx.h
Executable file
18
source/firmware/kernel/ctx.h
Executable 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_ */
|
36
source/firmware/kernel/driver/adc.c
Executable file
36
source/firmware/kernel/driver/adc.c
Executable 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);
|
||||
}
|
38
source/firmware/kernel/driver/adc.h
Executable file
38
source/firmware/kernel/driver/adc.h
Executable 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_ */
|
25
source/firmware/kernel/driver/battery_monitor.c
Executable file
25
source/firmware/kernel/driver/battery_monitor.c
Executable file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* battery_monitor.c
|
||||
*
|
||||
* Created on: Dec 23, 2012
|
||||
* Author: tkl
|
||||
*/
|
||||
#include "stddef.h"
|
||||
#include "adc.h"
|
||||
#include "battery_monitor.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct battery_monitor_voltage get_voltage(const struct battery_monitor *device)
|
||||
{
|
||||
struct battery_monitor_voltage ret;
|
||||
ret.valid = false;
|
||||
if(NULL == device) {
|
||||
return ret;
|
||||
}
|
||||
adc_open(device->adc);
|
||||
ret.raw = adc_read(device->adc, device->timeout);
|
||||
adc_close(device->adc);
|
||||
ret.voltage = ret.raw * device->factor / device->divider + device->offset;
|
||||
ret.valid = true;
|
||||
return ret;
|
||||
}
|
34
source/firmware/kernel/driver/battery_monitor.h
Executable file
34
source/firmware/kernel/driver/battery_monitor.h
Executable file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* battery_monitor.h
|
||||
*
|
||||
* Created on: Dec 23, 2012
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef BATTERY_MONITOR_H_
|
||||
#define BATTERY_MONITOR_H_
|
||||
|
||||
#include "stdbool.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief battery monitor device.
|
||||
struct battery_monitor {
|
||||
const struct adc *adc; //!< Adc device for the battery monitor.
|
||||
const unsigned short timeout; //!< Adc measurement timeout.
|
||||
const int factor; //!< Factor to calculate voltage from adc result.
|
||||
const int divider; //!< Divider to calculate voltage from adc result.
|
||||
const int offset; //!< Offset to calculate voltage from adc result.
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//! \brief Value container for the battery monitor.
|
||||
struct battery_monitor_voltage {
|
||||
unsigned short voltage; //!< Calculated voltage.
|
||||
unsigned short raw; //!< Raw value of the adc.
|
||||
bool valid; //!< Indicates if result is valid.
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct battery_monitor_voltage get_voltage(const struct battery_monitor * device);
|
||||
|
||||
#endif /* BATTERY_MONITOR_H_ */
|
147
source/firmware/kernel/driver/cc110x.c
Executable file
147
source/firmware/kernel/driver/cc110x.c
Executable file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* cc110x.c
|
||||
*
|
||||
* Created on: Jul 20, 2012
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "board.h"
|
||||
#include "stack.h"
|
||||
#include "queue.h"
|
||||
#include "thread.h"
|
||||
#include "schedule.h"
|
||||
#include "irq.h"
|
||||
#include "sys_tick.h"
|
||||
#include "cc110x.h"
|
||||
|
||||
static volatile bool tx_condition;
|
||||
extern volatile struct thread_context *current_thread;
|
||||
|
||||
static void it_cb(const struct cc110x *cc110x, enum cc110x_it_type it_type);
|
||||
|
||||
int cc110x_open(const struct cc110x *cc110x)
|
||||
{
|
||||
if(NULL == cc110x)
|
||||
return (-1);
|
||||
|
||||
tx_condition = false;
|
||||
cc110x->fp->init(cc110x);
|
||||
cc110x->fp->set_it_callback(cc110x->arch_dep_device, it_cb, cc110x);
|
||||
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_PWD);
|
||||
cc110x_write_pa_table(cc110x);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int cc110x_close(const struct cc110x *cc110x)
|
||||
{
|
||||
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_PWD);
|
||||
blocking_read_wakeup(cc110x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cc110x_set_radio_mode(const struct cc110x *cc110x,
|
||||
enum cc110x_radio_mode mode)
|
||||
{
|
||||
if(NULL == cc110x) {
|
||||
return;
|
||||
}
|
||||
*(cc110x->radio_mode) = mode;
|
||||
enum cc110x_strobe_cmd cmd = STROBE_SIDLE;
|
||||
switch(mode) {
|
||||
case CC110X_RADIO_MODE_NONE: return;
|
||||
case CC110X_RADIO_MODE_IDLE: cmd = STROBE_SIDLE; break;
|
||||
case CC110X_RADIO_MODE_RX: cmd = STROBE_SRX; break;
|
||||
case CC110X_RADIO_MODE_TX: cmd = STROBE_STX; break;
|
||||
case CC110X_RADIO_MODE_PWD: cmd = STROBE_SPWD; break;
|
||||
}
|
||||
cc110x->fp->strobe(cc110x->arch_dep_device, cmd);
|
||||
}
|
||||
|
||||
enum cc110x_radio_mode cc110x_get_radio_mode(const struct cc110x *cc110x)
|
||||
{
|
||||
if(NULL == cc110x)
|
||||
return (CC110X_RADIO_MODE_NONE);
|
||||
return (*(cc110x->radio_mode));
|
||||
}
|
||||
|
||||
void cc110x_write_pa_table(const struct cc110x *cc110x)
|
||||
{
|
||||
if(NULL == cc110x)
|
||||
return;
|
||||
cc110x->fp->write_pa_table(cc110x->arch_dep_device);
|
||||
}
|
||||
|
||||
void cc110x_strobe(const struct cc110x *cc110x, enum cc110x_strobe_cmd cmd)
|
||||
{
|
||||
if(NULL == cc110x)
|
||||
return;
|
||||
cc110x->fp->strobe(cc110x->arch_dep_device, cmd);
|
||||
}
|
||||
|
||||
int cc110x_write(const struct cc110x *cc110x, const char *buffer,
|
||||
int size)
|
||||
{
|
||||
enum cc110x_radio_mode mode;
|
||||
int ret;
|
||||
if((NULL == cc110x) || (NULL == buffer))
|
||||
return (-1);
|
||||
mode = cc110x_get_radio_mode(cc110x);
|
||||
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE);
|
||||
cc110x_strobe(cc110x, STROBE_SFTX);
|
||||
ret = cc110x->fp->write(cc110x->arch_dep_device, buffer, size);
|
||||
tx_condition = true;
|
||||
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_TX);
|
||||
while(tx_condition);
|
||||
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE);
|
||||
cc110x_strobe(cc110x, STROBE_SFTX);
|
||||
cc110x_set_radio_mode(cc110x, mode);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int cc110x_read(const struct cc110x *cc110x, char *buffer, int size)
|
||||
{
|
||||
int ret;
|
||||
unsigned int irq;
|
||||
if((NULL == cc110x) || (NULL == buffer))
|
||||
return (-1);
|
||||
if(0 == cc110x_get_rx_count(cc110x)) {
|
||||
irq = disable_irq();
|
||||
current_thread->status = THREAD_STATUS_BLOCKING;
|
||||
current_thread->wakeup_blocking_source = (void*) cc110x;
|
||||
restore_irq(irq);
|
||||
schedule();
|
||||
}
|
||||
enum cc110x_radio_mode mode = cc110x_get_radio_mode(cc110x);
|
||||
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE);
|
||||
ret = cc110x_get_rx_count(cc110x);
|
||||
ret = cc110x->fp->read(cc110x->arch_dep_device, buffer, ret);
|
||||
cc110x_strobe(cc110x, STROBE_SFRX);
|
||||
cc110x_set_radio_mode(cc110x, mode);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int cc110x_get_rx_count(const struct cc110x *cc110x)
|
||||
{
|
||||
if(NULL == cc110x)
|
||||
return (-1);
|
||||
return (cc110x->fp->get_rx_count(cc110x->arch_dep_device));
|
||||
}
|
||||
|
||||
static void it_cb(const struct cc110x *cc110x,
|
||||
enum cc110x_it_type it_type)
|
||||
{
|
||||
if(NULL == cc110x)
|
||||
return;
|
||||
switch(it_type) {
|
||||
case IT_TYPE_NONE:
|
||||
break;
|
||||
case IT_TYPE_RX_COMPLETE:
|
||||
blocking_read_wakeup(cc110x);
|
||||
break;
|
||||
case IT_TYPE_TX_COMPLETE:
|
||||
tx_condition = false;
|
||||
break;
|
||||
}
|
||||
}
|
88
source/firmware/kernel/driver/cc110x.h
Executable file
88
source/firmware/kernel/driver/cc110x.h
Executable file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* cc110x.h
|
||||
*
|
||||
* Created on: Jul 20, 2012
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef CC110X_H_
|
||||
#define CC110X_H_
|
||||
|
||||
enum cc110x_radio_mode {
|
||||
CC110X_RADIO_MODE_NONE = 0,
|
||||
CC110X_RADIO_MODE_IDLE,
|
||||
CC110X_RADIO_MODE_RX,
|
||||
CC110X_RADIO_MODE_TX,
|
||||
CC110X_RADIO_MODE_PWD
|
||||
};
|
||||
|
||||
enum cc110x_strobe_cmd {
|
||||
STROBE_SRES = 0,
|
||||
STROBE_SFSTXON,
|
||||
STROBE_SXOFF,
|
||||
STROBE_SCAL,
|
||||
STROBE_SRX,
|
||||
STROBE_STX,
|
||||
STROBE_SIDLE,
|
||||
STROBE_SWOR,
|
||||
STROBE_SPWD,
|
||||
STROBE_SFRX,
|
||||
STROBE_SFTX,
|
||||
STROBE_SWORRST,
|
||||
STROBE_SNOP
|
||||
};
|
||||
|
||||
enum cc110x_it_type {
|
||||
IT_TYPE_NONE = 0,
|
||||
IT_TYPE_RX_COMPLETE,
|
||||
IT_TYPE_TX_COMPLETE
|
||||
};
|
||||
|
||||
typedef void (*cc110x_fp_init)(const void *);
|
||||
typedef void (*cc110x_fp_write_pa_table)(const void *);
|
||||
typedef void (*cc110x_fp_set_radio_mode)(const void *, enum cc110x_radio_mode);
|
||||
typedef char (*cc110x_fp_strobe)(const void *, enum cc110x_strobe_cmd);
|
||||
typedef int (*cc110x_fp_write)(const void *, const char *, int);
|
||||
typedef int (*cc110x_fp_read)(const void *, char *, int);
|
||||
typedef int (*cc110x_fp_set_it_cb)(const void *, const void *, const void *);
|
||||
typedef int (*cc110x_fp_get_rx_count)(const void *);
|
||||
|
||||
//! \brief Contains the function pointer to access the cc110x driver.
|
||||
struct cc110x_fp {
|
||||
/*! Function pointer to the init function. */
|
||||
const cc110x_fp_init init;
|
||||
/*! Function pointer to the strobe function. */
|
||||
const cc110x_fp_strobe strobe;
|
||||
/*! Function pointer to the write function. */
|
||||
const cc110x_fp_write write;
|
||||
/*! Function pointer to the read function. */
|
||||
const cc110x_fp_read read;
|
||||
/*! Function pointer to the write_pa_table function. */
|
||||
const cc110x_fp_write_pa_table write_pa_table;
|
||||
/*! Function pointer to the set_it_callback function. */
|
||||
const cc110x_fp_set_it_cb set_it_callback;
|
||||
/*! Function pointer to the get_rx_count function. */
|
||||
const cc110x_fp_get_rx_count get_rx_count;
|
||||
};
|
||||
|
||||
//! \brief The cc110x driver object.
|
||||
struct cc110x {
|
||||
/*! Radio mode. */
|
||||
enum cc110x_radio_mode *radio_mode;
|
||||
/*! Architecture depended underlaying device (i.e. spi_t or NULL). */
|
||||
const void *arch_dep_device;
|
||||
/*! Function pointer for the cc110x driver access. */
|
||||
const struct cc110x_fp *fp;
|
||||
};
|
||||
|
||||
int cc110x_open(const struct cc110x *cc110x);
|
||||
int cc110x_close(const struct cc110x *cc110x);
|
||||
int cc110x_write(const struct cc110x *cc110x, const char *buffer, int size);
|
||||
int cc110x_read(const struct cc110x *cc110x, char *buffer, int size);
|
||||
int cc110x_get_rx_count(const struct cc110x *cc110x);
|
||||
void cc110x_set_radio_mode(const struct cc110x *cc110x, enum cc110x_radio_mode mode);
|
||||
enum cc110x_radio_mode cc110x_get_radio_mode(const struct cc110x *cc110x);
|
||||
void cc110x_write_pa_table(const struct cc110x *cc110x);
|
||||
void cc110x_strobe(const struct cc110x *cc110x, enum cc110x_strobe_cmd cmd);
|
||||
|
||||
#endif /* CC110X_H_ */
|
3
source/firmware/kernel/driver/driver.mk
Executable file
3
source/firmware/kernel/driver/driver.mk
Executable file
@@ -0,0 +1,3 @@
|
||||
SUB_FOLDER += firmware/kernel/driver
|
||||
INCLUDES += firmware/kernel/driver
|
||||
DOC_SRC += firmware/kernel/driver
|
126
source/firmware/kernel/driver/ds75.c
Executable file
126
source/firmware/kernel/driver/ds75.c
Executable file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* ds75.c
|
||||
*
|
||||
* Created on: Aug 1, 2012
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "ds75.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#define TEMPERATURE_REGISTER_ADDR 0x00
|
||||
#define CONFIGURATION_REGISTER_ADDR 0x01
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int ds75_open(const struct ds75 *device) {
|
||||
if(NULL == device) {
|
||||
return -1;
|
||||
}
|
||||
*device->config_value = 0x00;
|
||||
return device->i2c->fp->open(device->i2c->arch_dep_device);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int ds75_close(const struct ds75 *device) {
|
||||
if(NULL == device) {
|
||||
return -1;
|
||||
}
|
||||
return device->i2c->fp->close(device->i2c->arch_dep_device);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int ds75_set_precision(const struct ds75 *device, enum ds75_precision precision)
|
||||
{
|
||||
if(NULL == device) {
|
||||
return -1;
|
||||
}
|
||||
char cfg = *device->config_value | (precision << 5);
|
||||
char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
|
||||
int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
|
||||
device->i2c_slave_addr, buffer, sizeof(buffer));
|
||||
if (ret >= 0) {
|
||||
*device->config_value = cfg;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
enum ds75_precision ds_75_get_precision(const struct ds75 *device) {
|
||||
if(NULL == device) {
|
||||
return DS_75_PRECISION_INVALID;
|
||||
}
|
||||
|
||||
char cfg = *device->config_value;
|
||||
cfg >>= 5;
|
||||
cfg &= 3;
|
||||
return (enum ds75_precision) cfg;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int ds_75_shut_down(const struct ds75 *device) {
|
||||
if(NULL == device) {
|
||||
return -1;
|
||||
}
|
||||
char cfg = *device->config_value | (1 << 0);
|
||||
char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
|
||||
int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
|
||||
device->i2c_slave_addr, buffer, sizeof(buffer));
|
||||
if (ret >= 0) {
|
||||
*device->config_value = cfg;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int ds_75_wakeup(const struct ds75 *device) {
|
||||
if(NULL == device) {
|
||||
return -1;
|
||||
}
|
||||
char cfg = *device->config_value & ~(1 << 0);
|
||||
char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
|
||||
int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
|
||||
device->i2c_slave_addr, buffer, sizeof(buffer));
|
||||
if (ret >= 0) {
|
||||
*device->config_value = cfg;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct ds75_temperature ds_75_get_temperature(const struct ds75 *device) {
|
||||
struct ds75_temperature ret;
|
||||
ret.temperature = 0xFFFF;
|
||||
ret.raw[0] = 0xFF;
|
||||
ret.raw[1] = 0xFF;
|
||||
ret.valid = false;
|
||||
if(NULL == device) {
|
||||
return ret;
|
||||
}
|
||||
// set temperature register
|
||||
char addr = TEMPERATURE_REGISTER_ADDR;
|
||||
int res = device->i2c->fp->write(device->i2c->arch_dep_device, device->i2c_slave_addr, &addr, 1);
|
||||
if(res < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// read temperature register
|
||||
res = device->i2c->fp->read(device->i2c->arch_dep_device, device->i2c_slave_addr, ret.raw, 2);
|
||||
if(res < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret.valid = true;
|
||||
|
||||
ret.temperature = ret.raw[0];
|
||||
if(ret.temperature & 0x0080) {
|
||||
ret.temperature |= 0xFF00;
|
||||
}
|
||||
ret.temperature *= 10;
|
||||
unsigned short s_low = (unsigned char)ret.raw[1];
|
||||
s_low >>= 4;
|
||||
s_low *= 625;
|
||||
s_low += 500;
|
||||
s_low /= 1000;
|
||||
ret.temperature += s_low;
|
||||
return ret;
|
||||
}
|
49
source/firmware/kernel/driver/ds75.h
Executable file
49
source/firmware/kernel/driver/ds75.h
Executable file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* ds75.h
|
||||
*
|
||||
* Created on: Aug 1, 2012
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef DS75_H_
|
||||
#define DS75_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "i2c.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
enum ds75_precision {
|
||||
DS_75_PRECISION_9_BIT = 0,
|
||||
DS_75_PRECISION_10_BIT,
|
||||
DS_75_PRECISION_11_BIT,
|
||||
DS_75_PRECISION_12_BIT,
|
||||
|
||||
DS_75_PRECISION_INVALID
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//! \brief The ds75 driver object.
|
||||
struct ds75 {
|
||||
const struct i2c * i2c; //!< The i2c device the ds75 is connected to.
|
||||
const char i2c_slave_addr; //!< The i2c slave address of the ds 75.
|
||||
char *const config_value; //!< Config value.
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//! \brief Data container for the ds 75 measurement result.
|
||||
struct ds75_temperature {
|
||||
short temperature; //!< Calculated temperature.
|
||||
char raw[2]; //!< Raw i2c result.
|
||||
bool valid; //!< Validity indicator.
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int ds75_open(const struct ds75 *device);
|
||||
int ds75_close(const struct ds75 *device);
|
||||
int ds75_set_precision(const struct ds75 *device, enum ds75_precision precision);
|
||||
enum ds75_precision ds_75_get_precision(const struct ds75 *device);
|
||||
int ds_75_shut_down(const struct ds75 *device);
|
||||
int ds_75_wakeup(const struct ds75 *device);
|
||||
struct ds75_temperature ds_75_get_temperature(const struct ds75 *device);
|
||||
|
||||
#endif /* DS75_H_ */
|
61
source/firmware/kernel/driver/gpio.c
Executable file
61
source/firmware/kernel/driver/gpio.c
Executable 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);
|
||||
}
|
78
source/firmware/kernel/driver/gpio.h
Executable file
78
source/firmware/kernel/driver/gpio.h
Executable 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_ */
|
53
source/firmware/kernel/driver/i2c.c
Executable file
53
source/firmware/kernel/driver/i2c.c
Executable 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);
|
||||
}
|
75
source/firmware/kernel/driver/i2c.h
Executable file
75
source/firmware/kernel/driver/i2c.h
Executable 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_ */
|
218
source/firmware/kernel/driver/rtc.c
Executable file
218
source/firmware/kernel/driver/rtc.c
Executable 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));
|
||||
}
|
161
source/firmware/kernel/driver/rtc.h
Executable file
161
source/firmware/kernel/driver/rtc.h
Executable 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_ */
|
51
source/firmware/kernel/driver/spi.c
Executable file
51
source/firmware/kernel/driver/spi.c
Executable 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);
|
||||
}
|
75
source/firmware/kernel/driver/spi.h
Executable file
75
source/firmware/kernel/driver/spi.h
Executable 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_ */
|
139
source/firmware/kernel/driver/ssd1306.c
Normal file
139
source/firmware/kernel/driver/ssd1306.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* ssd1306.c
|
||||
*
|
||||
* Created on: Jan 13, 2016
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "i2c.h"
|
||||
#include "font.h"
|
||||
#include "bitmap.h"
|
||||
#include "ssd1306.h"
|
||||
|
||||
#define MAX_COLUMN 128
|
||||
#define MAX_ROW 64
|
||||
#define PAGE_COUNT 8
|
||||
#define HEAD_PAGE_COUNT 2
|
||||
#define BODY_PAGE_COUNT PAGE_COUNT - HEAD_PAGE_COUNT
|
||||
|
||||
#define CMD_MODE 0x80
|
||||
#define DATA_MODE 0x40
|
||||
|
||||
#define COLUMN_ADDR 0x21
|
||||
#define PAGE_ADDR 0x22
|
||||
#define DISPLAY_OFF 0xAE
|
||||
|
||||
static const char init_sequence[] = {
|
||||
0x80, 0xAE, 0x80, 0x20, 0x80, 0x10, 0x80, 0xb0, 0x80, 0xc8, 0x80, 0x00,
|
||||
0x80, 0x10, 0x80, 0x40, 0x80, 0x81, 0x80, 0x7f, 0x80, 0xa1, 0x80, 0xa6,
|
||||
0x80, 0xa8, 0x80, 0x3f, 0x80, 0xa4, 0x80, 0xd3, 0x80, 0x00, 0x80, 0xd5,
|
||||
0x80, 0xf0, 0x80, 0xd9, 0x80, 0x22, 0x80, 0xda, 0x80, 0x12, 0x80, 0xdb,
|
||||
0x80, 0x20, 0x80, 0x8d, 0x80, 0x14, 0x80, 0xaf
|
||||
};
|
||||
|
||||
static int set_column(const struct ssd1306 *dev, char column)
|
||||
{
|
||||
char buf[6];
|
||||
buf[0] = CMD_MODE;
|
||||
buf[1] = COLUMN_ADDR;
|
||||
buf[2] = CMD_MODE;
|
||||
buf[3] = column;
|
||||
buf[4] = CMD_MODE;
|
||||
buf[5] = MAX_COLUMN - 1;
|
||||
return i2c_write(dev->dev, dev->i2c_addr, buf, 6);
|
||||
}
|
||||
|
||||
static int set_page(const struct ssd1306 *dev, char page)
|
||||
{
|
||||
char buf[6];
|
||||
buf[0] = CMD_MODE;
|
||||
buf[1] = PAGE_ADDR;
|
||||
buf[2] = CMD_MODE;
|
||||
buf[3] = page;
|
||||
buf[4] = CMD_MODE;
|
||||
buf[5] = MAX_ROW / PAGE_COUNT - 1;
|
||||
return i2c_write(dev->dev, dev->i2c_addr, buf, 6);
|
||||
}
|
||||
|
||||
static int clear_head(const struct ssd1306 *dev)
|
||||
{
|
||||
int ret, i, j;
|
||||
char buf[2];
|
||||
|
||||
ret = set_column(dev, 0);
|
||||
ret |= set_page(dev, 0);
|
||||
|
||||
buf[0] = DATA_MODE;
|
||||
buf[1] = 0x00;
|
||||
for(i = 0; i < HEAD_PAGE_COUNT; i++)
|
||||
for(j = 0; j < MAX_COLUMN; j++)
|
||||
ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clear_body(const struct ssd1306 *dev)
|
||||
{
|
||||
int ret, i, j;
|
||||
char buf[2];
|
||||
|
||||
ret = set_column(dev, 0);
|
||||
ret |= set_page(dev, 2);
|
||||
|
||||
buf[0] = DATA_MODE;
|
||||
buf[1] = 0x00;
|
||||
for(i = 0; i < BODY_PAGE_COUNT; i++)
|
||||
for(j = 0; j < MAX_COLUMN; j++)
|
||||
ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clear(const struct ssd1306 *dev)
|
||||
{
|
||||
int ret;
|
||||
ret = clear_head(dev);
|
||||
ret |= clear_body(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssd1306_open(const struct ssd1306 *dev)
|
||||
{
|
||||
int ret;
|
||||
ret = i2c_open((struct i2c *)dev->dev);
|
||||
ret = i2c_write(dev->dev, dev->i2c_addr, init_sequence,
|
||||
sizeof(init_sequence) / sizeof(init_sequence[0]));
|
||||
ret |= clear(dev);
|
||||
ret |= set_column(dev, 0);
|
||||
ret |= set_page(dev, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssd1306_close(const struct ssd1306 *dev)
|
||||
{
|
||||
int ret;
|
||||
char buf[2];
|
||||
buf[0] = CMD_MODE;
|
||||
buf[1] = DISPLAY_OFF;
|
||||
ret = i2c_write(dev->dev, dev->i2c_addr, buf, 2);
|
||||
ret |= i2c_close((struct i2c *)dev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssd1306_write(const struct ssd1306 *dev, const struct bitmap *bitmap)
|
||||
{
|
||||
int ret, i, len = bitmap->x_size * bitmap->y_size / 8;
|
||||
char buf[2] = {DATA_MODE, 0x00};
|
||||
|
||||
if(len != MAX_COLUMN * PAGE_COUNT)
|
||||
return -1;
|
||||
ret = set_column(dev, 0);
|
||||
ret |= set_page(dev, 0);
|
||||
for(i = 0; i < len; i++) {
|
||||
buf[1] = bitmap->buffer[i];
|
||||
ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
22
source/firmware/kernel/driver/ssd1306.h
Normal file
22
source/firmware/kernel/driver/ssd1306.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* ssd1306.h
|
||||
*
|
||||
* Created on: Jan 13, 2016
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef SSD1306_H_
|
||||
#define SSD1306_H_
|
||||
|
||||
struct ssd1306 {
|
||||
const struct i2c *dev;
|
||||
const char i2c_addr;
|
||||
};
|
||||
|
||||
struct bitmap;
|
||||
|
||||
int ssd1306_open(const struct ssd1306 *dev);
|
||||
int ssd1306_close(const struct ssd1306 *dev);
|
||||
int ssd1306_write(const struct ssd1306 *dev, const struct bitmap *bitmap);
|
||||
|
||||
#endif /* SSD1306_H_ */
|
35
source/firmware/kernel/driver/timer.c
Executable file
35
source/firmware/kernel/driver/timer.c
Executable 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);
|
||||
}
|
43
source/firmware/kernel/driver/timer.h
Executable file
43
source/firmware/kernel/driver/timer.h
Executable 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_ */
|
78
source/firmware/kernel/driver/uart.c
Executable file
78
source/firmware/kernel/driver/uart.c
Executable file
@@ -0,0 +1,78 @@
|
||||
//! \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 "ringbuffer.h"
|
||||
#include "irq.h"
|
||||
#include "stack.h"
|
||||
#include "queue.h"
|
||||
#include "thread.h"
|
||||
#include "schedule.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, 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);
|
||||
}
|
63
source/firmware/kernel/driver/uart.h
Executable file
63
source/firmware/kernel/driver/uart.h
Executable 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_ */
|
19
source/firmware/kernel/font.h
Normal file
19
source/firmware/kernel/font.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* font.h
|
||||
*
|
||||
* Created on: Jan 15, 2016
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef FONT_H_
|
||||
#define FONT_H_
|
||||
|
||||
struct font {
|
||||
int char_size_x;
|
||||
int char_size_y;
|
||||
int char_between;
|
||||
int char_count;
|
||||
unsigned char *font;
|
||||
};
|
||||
|
||||
#endif /* FONT_H_ */
|
17
source/firmware/kernel/irq.h
Normal file
17
source/firmware/kernel/irq.h
Normal 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_ */
|
15
source/firmware/kernel/isr.h
Normal file
15
source/firmware/kernel/isr.h
Normal 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_ */
|
5
source/firmware/kernel/kernel.mk
Executable file
5
source/firmware/kernel/kernel.mk
Executable file
@@ -0,0 +1,5 @@
|
||||
SUB_FOLDER += firmware/kernel
|
||||
INCLUDES += firmware/kernel
|
||||
DOC_SRC += firmware/kernel
|
||||
|
||||
include firmware/kernel/driver/driver.mk
|
18
source/firmware/kernel/low_power.h
Executable file
18
source/firmware/kernel/low_power.h
Executable 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_ */
|
64
source/firmware/kernel/queue.c
Normal file
64
source/firmware/kernel/queue.c
Normal 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;
|
||||
}
|
26
source/firmware/kernel/queue.h
Normal file
26
source/firmware/kernel/queue.h
Normal 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_ */
|
64
source/firmware/kernel/ringbuffer.c
Executable file
64
source/firmware/kernel/ringbuffer.c
Executable 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;
|
||||
}
|
49
source/firmware/kernel/ringbuffer.h
Executable file
49
source/firmware/kernel/ringbuffer.h
Executable 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_ */
|
37
source/firmware/kernel/schedule.c
Executable file
37
source/firmware/kernel/schedule.c
Executable file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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();
|
||||
}
|
21
source/firmware/kernel/schedule.h
Executable file
21
source/firmware/kernel/schedule.h
Executable file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
void schedule_start(void);
|
||||
#define schedule() arch_schedule()
|
||||
|
||||
#endif /* SCHEDULE_H_ */
|
69
source/firmware/kernel/semaphore.c
Normal file
69
source/firmware/kernel/semaphore.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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 *)¤t_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;
|
||||
}
|
||||
|
20
source/firmware/kernel/semaphore.h
Normal file
20
source/firmware/kernel/semaphore.h
Normal 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_ */
|
18
source/firmware/kernel/stack.h
Normal file
18
source/firmware/kernel/stack.h
Normal 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_ */
|
70
source/firmware/kernel/sys_tick.c
Normal file
70
source/firmware/kernel/sys_tick.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 "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();
|
||||
}
|
||||
|
15
source/firmware/kernel/sys_tick.h
Normal file
15
source/firmware/kernel/sys_tick.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
void sleep_ms(unsigned int ms);
|
||||
|
||||
#endif /* SYS_TICK_H_ */
|
149
source/firmware/kernel/thread.c
Normal file
149
source/firmware/kernel/thread.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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 "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;
|
||||
if(thread->pid < 0)
|
||||
return NULL;
|
||||
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;
|
||||
}
|
||||
}
|
61
source/firmware/kernel/thread.h
Normal file
61
source/firmware/kernel/thread.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* thread.h
|
||||
*
|
||||
* Created on: Apr 13, 2015
|
||||
* Author: tkl
|
||||
*/
|
||||
|
||||
#ifndef THREAD_H_
|
||||
#define THREAD_H_
|
||||
|
||||
#define MAX_THREAD_COUNT 32
|
||||
|
||||
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_list {
|
||||
unsigned int count; //<! Number of elements in list
|
||||
struct thread_context *list[MAX_THREAD_COUNT];
|
||||
};
|
||||
|
||||
void thread_init(void);
|
||||
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_switch_context(void);
|
||||
|
||||
void thread_exit(void);
|
||||
|
||||
void blocking_read_wakeup(const void *src);
|
||||
|
||||
|
||||
#endif /* THREAD_H_ */
|
Reference in New Issue
Block a user