Skip to content

Commit

Permalink
* initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Matej committed Feb 3, 2014
0 parents commit 80fd9df
Show file tree
Hide file tree
Showing 22 changed files with 1,876 additions and 0 deletions.
73 changes: 73 additions & 0 deletions circbuf8.c
@@ -0,0 +1,73 @@
// ------------------------------------------------------------------
// --- circbuf.c - circular buffer routines ---
// --- ---
// --- 7.nov.2010, Matej Kogovsek (matej@hamradio.si) ---
// ------------------------------------------------------------------

#include "stm32f10x.h"
#include "circbuf8.h"

// ------------------------------------------------------------------
// initializes (clears) circ buf

void cbuf8_clear(volatile struct cbuf8_t* cb, uint8_t* const p, const uint16_t s)
{
uint32_t g = __get_PRIMASK();
__disable_irq();

cb->buf = p;
cb->size = s;
cb->head = 0;
cb->tail = 0;
cb->len = 0;

__set_PRIMASK(g);
}

// ------------------------------------------------------------------
// inserts an element

uint8_t cbuf8_put(volatile struct cbuf8_t* cb, const uint8_t d)
{
uint32_t g = __get_PRIMASK();
__disable_irq();

if (cb->len == cb->size) {
__set_PRIMASK(g);
return 0;
}

cb->buf[cb->tail] = d;
cb->tail++;
if(cb->tail == cb->size) { cb->tail = 0; }
cb->len++;

__set_PRIMASK(g);
return 1;
}

// ------------------------------------------------------------------
// gets the next element

uint8_t cbuf8_get(volatile struct cbuf8_t* cb, uint8_t* const d)
{
uint32_t g = __get_PRIMASK();
__disable_irq();

if (cb->len == 0) {
__set_PRIMASK(g);
return 0;
}

if( d ) { // if d is null, cbuf_get can be used to check for data in buffer
*d = cb->buf[cb->head];
cb->head++;
if(cb->head == cb->size) { cb->head = 0; }
cb->len--;
}

__set_PRIMASK(g);
return 1;
}

// ------------------------------------------------------------------
25 changes: 25 additions & 0 deletions circbuf8.h
@@ -0,0 +1,25 @@
// ------------------------------------------------------------------
// --- circbuf.c - circular buffer routines ---
// --- ---
// --- 7.nov.2010, Matej Kogovsek (matej@hamradio.si) ---
// ------------------------------------------------------------------

#ifndef MAT_CIRCBUF8_H
#define MAT_CIRCBUF8_H

#include <inttypes.h>

struct cbuf8_t
{
uint8_t* buf;
uint16_t head;
uint16_t tail;
uint16_t len;
uint16_t size;
};

void cbuf8_clear(volatile struct cbuf8_t* cb, uint8_t* const p, const uint16_t s);
uint8_t cbuf8_put(volatile struct cbuf8_t* cb, const uint8_t d);
uint8_t cbuf8_get(volatile struct cbuf8_t* cb, uint8_t* const d);

#endif
121 changes: 121 additions & 0 deletions cmt.c
@@ -0,0 +1,121 @@
// ------------------------------------------------------------------
// --- cmt.c ---
// --- simple cooperative "on-delay" multitasking ---
// --- 15.dec.2013, Matej Kogovsek ---
// ------------------------------------------------------------------

#include "stm32f10x.h"

#include "cmt.h"

volatile uint8_t cmt_curtask = 0;
volatile struct cmt_task cmt_tasks[CMT_MAXTASKS];
volatile uint8_t cmt_numtasks = 1;

// ------------------------------------------------------------------
// task switching is done here
// this should not be called with interrupts disabled
void cmt_delay_ticks(uint32_t d)
{
asm("push {r4-r11}\n"); // push all registers not saved by the caller

__disable_irq();
cmt_tasks[cmt_curtask].sp = __get_MSP(); // remember current task's SP
cmt_tasks[cmt_curtask].d = d; // and how long it wishes to sleep
__enable_irq();

uint8_t i = cmt_curtask;
while( 1 ) {
//wdt_reset();
i = (i + 1) % cmt_numtasks;
if( 0 == cmt_tasks[i].d ) { break; } // found ready to run task
}

__disable_irq();
cmt_curtask = i;
__set_MSP(cmt_tasks[i].sp); // restore task's stack pointer
__enable_irq();

uint32_t tp = cmt_tasks[i].tp;
if( tp ) { // if this is the first time the task
cmt_tasks[i].tp = 0; // is run, jump to task proc directly
asm("bx %0\n"::"r" (tp):);
}

asm("pop {r4-r11}\n");
}

// ------------------------------------------------------------------
// setup task, call this to setup all tasks
uint8_t cmt_setup_task(void (*task_proc)(void), uint32_t task_sp)
{
cmt_tasks[0].minsp = -1; // should be in cmt_init, but can as well be here
cmt_tasks[0].tp = 0;

if( cmt_numtasks >= CMT_MAXTASKS ) return 0;

cmt_tasks[cmt_numtasks].sp = task_sp;
cmt_tasks[cmt_numtasks].tp = 1|(uint32_t)task_proc;
cmt_tasks[cmt_numtasks].d = 0; // ready to run
cmt_tasks[cmt_numtasks].minsp = -1;

return ++cmt_numtasks;
}

// ------------------------------------------------------------------
// should be called by a timer interrupt
void cmt_tick(void)
{
// keep track of current task's min SP
if( __get_MSP() < cmt_tasks[cmt_curtask].minsp ) {
cmt_tasks[cmt_curtask].minsp = __get_MSP();
}

// decrease all tasks' delay count
uint8_t i;
for( i = 0; i < cmt_numtasks; i++ ) {
if( cmt_tasks[i].d ) {
cmt_tasks[i].d--;
}
}
}

// ------------------------------------------------------------------
// returns the task's minimal detected stack pointer
uint32_t cmt_minsp(uint8_t task_num)
{
if( task_num < cmt_numtasks ) {
return cmt_tasks[task_num].minsp;
}
return 0;
}

// ------------------------------------------------------------------
// tries to acquire mutex
uint8_t cmt_try_acquire(struct cmt_mutex* m)
{
if( (m->ot == cmt_curtask) || (m->ac == 0) ) {
m->ot = cmt_curtask;
m->ac++;
return 1;
}
return 0;
}

// ------------------------------------------------------------------
// waits until mutex acquired
void cmt_acquire(struct cmt_mutex* m)
{
while( !cmt_try_acquire(m) ) {
cmt_delay_ticks(0);
}
}

// ------------------------------------------------------------------
// releases mutex
void cmt_release(struct cmt_mutex* m)
{
if( (m->ot == cmt_curtask) && (m->ac > 0) ) {
m->ac--;
}
}
36 changes: 36 additions & 0 deletions cmt.h
@@ -0,0 +1,36 @@
// ------------------------------------------------------------------
// --- cmt.c ---
// --- simple cooperative "on-sleep" multitasking ---
// --- 8.mar.2011, Matej Kogovsek ---
// ------------------------------------------------------------------

#ifndef MAT_CMT_H
#define MAT_CMT_H

#include <inttypes.h>

#define CMT_MAXTASKS 5

struct cmt_task
{
uint32_t sp; // stack pointer
uint32_t tp; // task proc
uint32_t d; // ticks left to sleep
uint32_t minsp; // min detected task's SP
};

struct cmt_mutex
{
uint8_t ot; // owning task
uint8_t ac; // acquire count
};

void cmt_delay_ticks(uint32_t d);
uint8_t cmt_setup_task(void (*task_proc)(void), uint32_t task_sp);
void cmt_tick(void);
uint32_t cmt_minsp(uint8_t task_num);

uint8_t cmt_try_acquire(struct cmt_mutex* m);
void cmt_acquire(struct cmt_mutex* m);
void cmt_release(struct cmt_mutex* m);
#endif
49 changes: 49 additions & 0 deletions hmc5883l.c
@@ -0,0 +1,49 @@

#include "stm32f10x.h"
#include "i2c.h"
#include "hmc5883l.h"
#include <math.h>

const uint8_t HMC_I2C_ADDR = 0x3c;

uint8_t hmc_init(uint8_t cra, uint8_t crb, uint8_t mode)
{
uint8_t b[4] = {0, cra, crb, mode};

return i2c_wr(I2C1, b, 4, HMC_I2C_ADDR);
}

uint8_t hmc_read(int16_t* x, int16_t* y, int16_t* z)
{
uint8_t b[6] = {3};

if( i2c_wr(I2C1, b, 1, HMC_I2C_ADDR) ) { return 1; }

if( i2c_rd(I2C1, b, 6, HMC_I2C_ADDR) ) { return 1; }

*x = (((int16_t)b[0]) << 8) | b[1];
*z = (((int16_t)b[2]) << 8) | b[3];
*y = (((int16_t)b[4]) << 8) | b[5];

return 0;
}

float hmc_heading(int16_t x, int16_t y)
{
float heading = atan2(y, x);

if( heading < 0 ) { heading += 2 * M_PI; }

return heading * 180 / M_PI;
}

bool hmc_present(void)
{
uint8_t b[3] = {10};

if( i2c_wr(I2C1, b, 1, HMC_I2C_ADDR) ) { return false; }

if( i2c_rd(I2C1, b, 3, HMC_I2C_ADDR) ) { return false; }

return (b[0] == 'H') && (b[1] == '4') && (b[2] == '3');
}
15 changes: 15 additions & 0 deletions hmc5883l.h
@@ -0,0 +1,15 @@

#ifndef HMC8883L_H
#define HMC8883L_H

#include <stdbool.h>

uint8_t hmc_init(uint8_t cra, uint8_t crb, uint8_t mode);

uint8_t hmc_read(int16_t* x, int16_t* y, int16_t* z);

float hmc_heading(int16_t x, int16_t y);

bool hmc_present(void);

#endif

0 comments on commit 80fd9df

Please sign in to comment.