-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.c
More file actions
295 lines (266 loc) · 10 KB
/
Copy pathmain.c
File metadata and controls
295 lines (266 loc) · 10 KB
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/uart.h"
#include "driverlib/sysctl.h"
#include "utils/uartstdio.h"
#include "driverlib/crc.h"
#include "driverlib/udma.h"
#include "inc/hw_uart.h"
#include "inc/hw_types.h"
#include "inc/hw_udma.h"
#include "inc/hw_uart.h"
#include "inc/hw_ints.h"
#include "driverlib/interrupt.h"
#include <string.h>
#include <math.h>
/**
* main.c
*/
#define TXSIZE 1024
#if TXSIZE > 1024
#undef TXSIZE
#define TXSIZE 1024
#endif
uint32_t g_ui32SysClock;
uint8_t count;
#define DATA_ALIGN(var, align) __attribute__((aligned(align))) var
#pragma DATA_ALIGN(ControlTable, 1024)
uint8_t ControlTable[1024];
uint8_t bufferA[TXSIZE] = {0};
uint8_t bufferB[TXSIZE] = {0};
unsigned int rxbuffB;
unsigned int rxbuffA;
uint32_t received_size = 0;
uint32_t file_size = 0;
char file[1024]; // max 1mb for 2 firmwares
tDMAControlTable* ct;
int bytes_left = 0;
typedef enum uart_states{
IDLE,
INIT,
RECEIVING,
RECV_COMPLETE,
} state;
state dma_state = IDLE;
void sysClock(void){
g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320), 20000000);
}
void configureUART0(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC); //16 Mhz
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0|GPIO_PIN_1);
// assert dma request when buffer is half fill ie, 16/2 ->8 bytes
UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8); // used by udma for burst request
UARTStdioConfig(0, 115200, 16000000);
}
// buttons PJ0 and PJ1 is configured
void configureGPIOINPUT(void){
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);//enable port j
while(! SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOJ));//check clock enable
GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);// config port j bit 0 to input
GPIODirModeSet(GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_DIR_MODE_IN);
GPIOPadConfigSet(GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD_WPU);
}
void CRC_init(){
SysCtlPeripheralEnable(SYSCTL_PERIPH_CCM0);
CRCConfigSet(CCM0_BASE, CRC_CFG_INIT_0 | CRC_CFG_SIZE_32BIT | CRC_CFG_TYPE_P4C11DB7);
}
void
UARTReceive(uint8_t *data, uint32_t size)
{
// loop until RX FIFO is empty
while (!(HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE))
{
(void)HWREG(UART0_BASE + UART_O_DR); // Read and discard
}
while(size--)
{
while((HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE));
*data++ = HWREG(UART0_BASE + UART_O_DR);
}
}
void dma_init(){
//channel 8 for UART0 RX
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
//DMA Init
// HWREG(SYSCTL_RCGCBASE + 0x0000060C) = 0x00000001; // enable dma module clock - takes 5 clock cyles
HWREG(UDMA_CFG) = 0x00000001; // enable dma controller, set masteren bit
HWREG(UDMA_CTLBASE) = (uint32_t)&ControlTable;
HWREG(UART0_BASE + UART_O_DMACTL) = 0x00000007; // rxFIFO dma enabled, recv req disbale if recv error
//channel assign
HWREG(UDMA_CHMAP1) = 0; //uart0 rx channel 8[3:0], encoding 0 to select UART-0
// configure channel attributes
//channel prio set - high - 1 channel 8
HWREG(UDMA_PRIOSET) = (1<<8);
//use primary control structure , channel 8
HWREG(UDMA_ALTCLR) = (1<<8);
// use burst or single transfer
HWREG(UDMA_USEBURSTCLR) = (1<<8);
// request dma transfer by peripheral
HWREG(UDMA_REQMASKCLR) = (1<<8);
/*
Control Structure Offset Formula Example for Channel 8
Primary Base + (Channel * 16) Base + (8 * 16) = Base + 0x080
Alternate Base + 0x200 + (Channel * 16) Base + 0x200 + (8 * 16) = Base + 0x280
*/
ct = (tDMAControlTable*)HWREG(UDMA_CTLBASE);
// configure control structures
ct[0 + 8].ui32Control =
(3 << 26) | // SRCINC: No Increment (UART)
(0 << 24) | // SRCSIZE: 8-bit
(0 << 30) | // DSTINC: 8-bit Increment
(0 << 28) | // DSTSIZE: 8-bit
(3 << 14) | // ARBSIZE: 8 Transfers
(TXSIZE-1 << 4) | // XFERSIZE: TXSIZE-1 Transfers
(3 << 0); // XFERMODE: Ping-Pong;//primary Control mode
ct[0 + 8].pvSrcEndAddr = (void*)(UART0_BASE + UART_O_DR);//primary source pointer
ct[0 + 8].pvDstEndAddr = (void*)(bufferA + TXSIZE-1);//primary dest pointer
ct[32 + 8].ui32Control =
(0 << 30) | // destination address increment
(0 << 28) | // Destination data size: 8-bit
(3 << 26) | // SRCINC: No Increment (UART)
(0 << 24) | // SRCSIZE: 8-bit
(3 << 14) | // ARBSIZE: 8 Transfers
(TXSIZE-1 << 4) | // XFERSIZE: Transfers
(3 << 0); // XFERMODE: Ping-Pong;//alt control mode
ct[32 + 8].pvSrcEndAddr = (void*)(UART0_BASE + UART_O_DR);//alt source pointer
ct[32 + 8].pvDstEndAddr = (void*)(bufferB + TXSIZE-1);//alt dest pointer
IntMasterEnable();
UARTIntEnable(UART0_BASE, UART_INT_DMARX); //interruot when dma transfer until transfer size is completed
IntEnable(INT_UART0);
//enable channel, bit[n] - channel n
HWREG(UDMA_ENASET) = (1<<8);
while(!(HWREG(UDMA_ENASET) & (1 << 8)));
}
void inline recv_file(char* buff, size_t s) {
memcpy(file + received_size, buff, s);
}
void UART0_IntHandler(void){
uint32_t status = UARTIntStatus(UART0_BASE, true); // get interrupts status
UARTIntClear(UART0_BASE, status); // clear those interrupts
if (bytes_left == 0) {
dma_state = RECV_COMPLETE;
HWREG(UDMA_ENACLR) = (1 << 8); // Disable DMA
return; // Exit handler instead of break, since it's top-level
}
//check the mode of primary
ct = (tDMAControlTable*)HWREG(UDMA_CTLBASE);
uint8_t mode = ct[8].ui32Control & 0x00000007; //extarct first three bits - mode
dma_state = RECEIVING;
if(mode == UDMA_MODE_STOP){
rxbuffA++;
if(dma_state == RECEIVING){
uint32_t bytes_copy = (bytes_left < TXSIZE)? bytes_left : TXSIZE;
recv_file(bufferA, bytes_copy);
received_data += bytes_copy;
if(bytes_left < TXSIZE){
bytes_left = 0;
} else {
bytes_left -= TXSIZE;
}
}
//resrt transfer
ct[0 + 8].pvSrcEndAddr = (void*)(UART0_BASE + UART_O_DR);//primary source pointer
ct[0 + 8].pvDstEndAddr = (void*)(bufferA + TXSIZE-1);//primary dest pointer
ct[0 + 8].ui32Control =
(3 << 26) | // SRCINC: No Increment (UART)
(3 << 14) | // ARBSIZE: 8 Transfers
((TXSIZE-1) << 4) | // XFERSIZE: Transfers size
(3 << 0); // XFERMODE: Ping-Pong;//primary Control mode
}
mode = ct[32 + 8].ui32Control & 0x00000007; //extarct first three bits - mode
dma_state = RECEIVING;
if(mode == UDMA_MODE_STOP){
rxbuffB++;
if(dma_state == RECEIVING){
uint32_t bytes_copy = (bytes_left < TXSIZE)? bytes_left : TXSIZE;
recv_file(bufferB, bytes_copy);
received_data += bytes_copy;
if(bytes_left < TXSIZE){
bytes_left = 0;
} else {
bytes_left -= TXSIZE;
}
}
//resrt transfer
ct[32 + 8].pvSrcEndAddr = (void*)(UART0_BASE + UART_O_DR);//primary source pointer
ct[32 + 8].pvDstEndAddr = (void*)(bufferB + TXSIZE-1);//primary dest pointer
ct[32 + 8].ui32Control =
(3 << 26) | // SRCINC: No Increment (UART)
(3 << 14) | // ARBSIZE: 8 Transfers
((TXSIZE-1) << 4) | // XFERSIZE: Transfers szie
(3 << 0); // XFERMODE: Ping-Pong;//primary Control mode
}
if(received_size >= file_size){
dma_state = RECV_COMPLETE;
HWREG(UDMA_ENACLR) = (1 << 8); // Disable DMA
}
}
void buttons(){
uint32_t BUTTON_PRESS_0 = GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_0);
uint32_t BUTTON_PRESS_1 = GPIOPinRead(GPIO_PORTJ_BASE, GPIO_PIN_1);
if(!(BUTTON_PRESS_0 & GPIO_PIN_0)){
UARTprintf("count = %d\r\n", count++);
SysCtlDelay(g_ui32SysClock/12); // 250 ms
}
else if(!(BUTTON_PRESS_1 & GPIO_PIN_1)){
UARTprintf("count = %d\r\n", count--);
SysCtlDelay(g_ui32SysClock/12);
}
}
//
uint32_t convert(char* src){
int i = 0;
uint32_t dest = 0;
while(src[i] != 's'){
(dest) *= 10;
(dest) += src[i++] - '0';
}
return dest;
}
int main(void)
{
sysClock();
configureUART0();
configureGPIOINPUT();
CRC_init();
dma_init();
char command[20];
unsigned int crc = 0;
UARTprintf("\nuart start \r\n");
dma_state = INIT;
strncpy(command, "FILE_INFO",10);
UARTwrite(command, sizeof(command));
while(bufferA[0] == 0); // wait until data is recv
file_size = convert(bufferA);
bytes_left = file_size;
//RECV the file size and store in file_size variable
// how dta is recv, FILESIZEsCRCs , s is my dleimter here
crc = convert(bufferA + (uint32_t)(log10(file_size) + 2)); //log10 + 1 - no of bytes, skip s- plus one
strncpy(command, "SEND_FILE", 10);
UARTwrite(command, sizeof(command));
memset(bufferA, 0 ,sizeof(bufferA)); // clear the file size and crc before receiving the file
dma_state = RECEIVING;
//receive the crc and store in crc variable
while(1){
// //clear dma buffer before recv file
// memset(bufferA, 0, sizeof(bufferA));
// memset(bufferB, 0, sizeof(bufferB));
// dma_state = RECEIVING;
if(dma_state == RECV_COMPLETE) {
UARTprintf("\nFile received: %s\n", file);
crc = CRCDataProcess(CCM0_BASE, file, received_size, false);
UARTprintf("CRC: %u\n", crc);
while(1); // Or reset for next file
}
// SysCtlDelay(g_ui32SysClock/200);
}
// return 0;
}