-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipc.c
189 lines (162 loc) · 4.16 KB
/
ipc.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include "ipc.h"
#include "uart.h"
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stddef.h>
#include "m128_hal.h"
#include <stdlib.h>
#include <spi.h>
#include "aaps_a.h"
#define IPC_DUMMY_BYTE 0xff
#define IPC_SYNC_BYTE 0xfc
#define IPC_FINALIZE_BYTE 0xc0
#define IPC_GET_BYTE 0x55
#define IPC_PUT_BYTE 0x66
#define WAIT_CNT 5000
#define PUT_WAIT_CNT 3000
struct spi_device_t gui =
{
//.opto_coupled = true,
//.hw_ch = system_channel[0],
.init = init_aaps_a,
};
struct spi_device_t analog =
{
//.opto_coupled = true,
//.hw_ch = system_channel[0],
.init = init_aaps_a,
};
volatile uint8_t send_semaphore = 0;
volatile uint8_t spi_data_buf = 0;
ipc_ret_t ipc_get_pkt(uint8_t slave, struct ipc_packet_t *pkt)
{
/* TODO: Handle return values */
volatile uint8_t data;
uint8_t buf = IPC_GET_BYTE;
uint16_t wait_cnt = WAIT_CNT;
struct hw_channel_t *hw_ch = channel_lookup(slave);
ipc_ret_t result = IPC_RET_OK;
enable(hw_ch);
do
{
data = spi_transfer(buf);
if (!wait_cnt--)
{
printk("Transfer failed! 0x%x\n", data);
result = IPC_RET_ERROR_GET_SYNC;
goto no_answer;
}
}while(data != IPC_SYNC_BYTE); /* Wait for ACK */
/* First byte is data length */
uint8_t rx_len = spi_transfer(buf);
pkt->len = rx_len;
/* Allocate enough bytes for data */
pkt->data = (uint8_t*)malloc(pkt->len - IPC_PKT_OVERHEAD);
if (pkt->data == NULL)
{
result = IPC_RET_ERROR_OUT_OF_MEMORY;
goto no_answer;
}
if (pkt->len == 0)
{
/* TODO: Add return value */
printk("Len is zero\n");
result = IPC_RET_ERROR_GENERIC;
goto no_answer;
}
/* TODO: Remove duplication of length variable
* on slave side.
*/
data = spi_transfer(buf);
rx_len--;
pkt->cmd = spi_transfer(buf);
rx_len--;
pkt->crc = spi_transfer(buf);
rx_len--;
while(rx_len--)
{
pkt->data[rx_len] = spi_transfer(buf);
/*
* This delay is dependant on system
* clocks on master and slave.
*/
_delay_us(8);
}
/* Synchronize end of transmission */
wait_cnt = WAIT_CNT;
do
{
data = spi_transfer(buf);
if (!wait_cnt--)
{
printk("Finalize failed! Received: 0x%x\n", data);
result = IPC_RET_ERROR_GET_FINALIZE;
goto no_answer;
}
}while(data != IPC_FINALIZE_BYTE); /* Wait for ACK */
no_answer:
irq_from_slave[slave]--;
if (irq_from_slave[slave] < 0)
return IPC_RET_ERROR_GENERIC;
disable(hw_ch);
return result;
}
struct hw_channel_t *channel_lookup(uint8_t ch)
{
return system_channel[ch];
}
ipc_ret_t ipc_put_pkt(uint8_t slave, struct ipc_packet_t *pkt)
{
uint8_t data;
ipc_ret_t result = IPC_RET_OK;
uint16_t wait_cnt = PUT_WAIT_CNT;
struct hw_channel_t *hw_ch = channel_lookup(slave);
if (pkt == NULL || hw_ch == NULL)
return IPC_RET_ERROR_BAD_PARAMS;
enable(hw_ch);
do
{
data = spi_transfer(IPC_PUT_BYTE);
if (!wait_cnt--)
{
result = IPC_RET_ERROR_PUT_SYNC;
goto no_answer;
}
}while(data != IPC_SYNC_BYTE); /* Wait for ACK */
/* Put packet overhead data */
spi_transfer(pkt->len);
spi_transfer(pkt->cmd);
spi_transfer(pkt->crc);
/* Put packet payload */
for (uint8_t i = 0; i < pkt->len - IPC_PKT_OVERHEAD; i++)
spi_transfer(pkt->data[i]);
wait_cnt = WAIT_CNT;
do
{
/* TODO: Fix this magic number */
data = spi_transfer(0x10);
if (!wait_cnt--)
{
result = IPC_RET_ERROR_PUT_FINALIZE;
goto no_answer;
}
}while(data != IPC_FINALIZE_BYTE); /* Wait for ACK */
no_answer:
disable(hw_ch);
return result;
}
int8_t ipc_which_irq(volatile int8_t irq_flags[])
{
/* TODO: Perhaps 'i' should be static so
* that IRQs in the end of the vector doesn't
* get starved.
*/
uint8_t i;
for (i = 0; i < HW_NBR_OF_CHANNELS; i++)
{
if (irq_flags[i])
return i;
}
return NO_IRQ;
}