-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathspi.c
executable file
·116 lines (108 loc) · 2.54 KB
/
spi.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "stm8s.h"
#include "ltkrn.h"
#include "spi.h"
#define SPI_DR SPI->DR
volatile char *spi_tx_bfr;
volatile char *spi_rx_bfr;
volatile int spi_tx_len;
volatile int spi_rx_len;
volatile int spi_tx_cnt;
volatile int spi_rx_cnt;
volatile int spi_flag;
volatile int spi_stat;
krn_thread *spi_master_sleep_thread;
static krn_mutex spi_master_mutex;
void spi_master_init(char prescaler)
{
krn_mutex_init(&spi_master_mutex);
SPI->CR1 = SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_MSTR | SPI_BAUDRATEPRESCALER_16;
SPI->CR2 = SPI_CR2_SSI | SPI_CR2_SSM;
SPI->ICR = SPI_ICR_TXEI;
}
void spi_master_start()
{
CRITICAL_STORE;
CRITICAL_START();
spi_flag = 0;
spi_tx_cnt = 0;
spi_rx_cnt = 0;
if(spi_tx_len != 0) spi_flag |= SPI_TX_PEND;
if(spi_rx_len != 0) spi_flag |= SPI_RX_PEND;
if( (spi_flag & (SPI_RX_PEND | SPI_TX_PEND)) == 0 ) {
CRITICAL_END();
return;
}
SPI->CR1 |= SPI_CR1_SPE;
if(spi_flag & SPI_TX_PEND) SPI_DR = *(spi_tx_bfr++);
else SPI_DR = 0xff;
CRITICAL_END();
}
void spi_master_wait()
{
CRITICAL_STORE;
CRITICAL_START();
if(spi_flag & (SPI_RX_PEND | SPI_TX_PEND) )
{
spi_master_sleep_thread = krn_thread_current;
krn_thread_lock(spi_master_sleep_thread);
krn_dispatch();
}
CRITICAL_END();
}
#if defined(__IAR_SYSTEMS_ICC__)
#pragma vector = 12
#endif
INTERRUPT void spi_isr (void)
#if defined(__RCSTM8__)
interrupt 10
#endif
{
if(spi_flag & SPI_TX_PEND)
{
spi_tx_len--;
spi_tx_cnt++;
if( spi_tx_len == 0 )
{
spi_flag &= ~SPI_TX_PEND;
if(spi_flag & SPI_RX_PEND) SPI_DR = 0xff;
else {
SPI->CR1 &= ~SPI_CR1_SPE;
if(spi_master_sleep_thread) {
krn_thread_unlock(spi_master_sleep_thread);
krn_thread_move(spi_master_sleep_thread, krn_thread_current);
spi_master_sleep_thread = 0;
krn_dispatch(); //uncomment for extra hardness
}
spi_flag |= SPI_IDLE;
}
}
else
{
SPI_DR = *(spi_tx_bfr++);
spi_flag |= SPI_TX_EV;;
}
}
else
{
*(spi_rx_bfr++) = SPI_DR;
spi_flag |= SPI_RX_EV;
spi_rx_len--;
spi_rx_cnt++;
if( spi_rx_len == 0 )
{
spi_flag &= ~SPI_RX_PEND;
spi_flag |= SPI_IDLE;
SPI->CR1 &= ~SPI_CR1_SPE;
if(spi_master_sleep_thread) {
krn_thread_unlock(spi_master_sleep_thread);
krn_thread_move(spi_master_sleep_thread, krn_thread_current);
spi_master_sleep_thread = 0;
krn_dispatch(); //uncomment for extra hardness
}
}
else SPI_DR = 0xff;
}
}