1 | #include "can_interface.h"
|
2 |
|
3 |
|
4 | enum Can_Bootloader_State can_bootloader_state = AWAITING_REQUEST;
|
5 |
|
6 | uint8_t active_data_buffer_offset = 0;
|
7 | uint8_t active_data_buffer = 0;
|
8 | char data_buffer[2][44];
|
9 | uint8_t data_buffer_length = 0;
|
10 |
|
11 | uint8_t active_page_buffer = 0;
|
12 | char page_buffer[2][SPM_PAGESIZE];
|
13 |
|
14 | uint32_t page_count = 1;
|
15 | uint8_t page_count_flag = 0;
|
16 |
|
17 | void switch_active_data_buffer(){
|
18 | if(active_data_buffer == 0){active_data_buffer=1;}else{active_data_buffer=0;}
|
19 | }
|
20 |
|
21 | void switch_active_page_buffer(){
|
22 | if(active_page_buffer == 0){active_page_buffer=1;}else{active_page_buffer=0;}
|
23 | }
|
24 |
|
25 | int8_t buffer_can_message_data(uint8_t length, char *data){
|
26 |
|
27 | uint8_t len = length;
|
28 | int8_t return_value = -1;
|
29 |
|
30 | for(uint8_t i=1;i<len;i++){
|
31 | char tmp = *(data+i);
|
32 | if((tmp == ':') && (active_data_buffer_offset!=0)){
|
33 | return_value = active_data_buffer;
|
34 | switch_active_data_buffer();
|
35 | data_buffer_length = active_data_buffer_offset;
|
36 | active_data_buffer_offset=0;
|
37 | }
|
38 | data_buffer[active_data_buffer][active_data_buffer_offset] = tmp;
|
39 | active_data_buffer_offset++;
|
40 |
|
41 | }
|
42 | return return_value;
|
43 | }
|
44 |
|
45 |
|
46 | int8_t buffer_page_data(uint8_t length, char *data){
|
47 | static uint8_t offset = 0;
|
48 | uint8_t len = length;
|
49 | int8_t return_value = -1;
|
50 | for(uint8_t i=1;i<len;i++){
|
51 | char tmp = *(data+i);
|
52 | if(offset == (SPM_PAGESIZE-1)){
|
53 | return_value = active_data_buffer;
|
54 | switch_active_page_buffer();
|
55 | offset=0;
|
56 | }
|
57 | data_buffer[active_page_buffer][offset] = tmp;
|
58 | offset++;
|
59 | }
|
60 | return return_value;
|
61 | }
|
62 |
|
63 | void write_bootloader_message_buffered_to_can(uint16_t length, char *input){
|
64 | static uint16_t offset = 0;
|
65 | uint8_t loops = (length / 7)+1;
|
66 |
|
67 | for(uint8_t i=0;i<loops;i++){
|
68 | uint8_t len = 7;
|
69 | if(i+1 == loops){
|
70 | len = length % 7;
|
71 | }
|
72 |
|
73 | char *data = malloc(sizeof(char)*(len+1));
|
74 | memcpy(data+1,input+offset, (size_t)len);
|
75 | data[0] = BOOTLOADER_MESSAGE;
|
76 | offset += len;
|
77 |
|
78 | write_message_to_can(DEVICE_ID,len+1,data);
|
79 | free(data);
|
80 |
|
81 | uint8_t escape_flag = 0;
|
82 | while(escape_flag == 0){
|
83 |
|
84 | if((PIND & (1<<PD7)) == 0){
|
85 | Message *message;
|
86 | handle_interrupt(message);
|
87 | //escape_flag = 1;
|
88 | if((message->id == 1) && (message->data[0] == BOOTLOADER_MESSAGE_CLEAR_TO_SEND)){
|
89 | escape_flag = 1;
|
90 | }
|
91 | }
|
92 | }
|
93 | }
|
94 | offset = 0;
|
95 | }
|
96 |
|
97 |
|
98 | static uint16_t hex2num (const uint8_t * ascii, uint8_t offset, uint8_t len)
|
99 | {
|
100 | uint8_t i;
|
101 | uint16_t val = 0;
|
102 |
|
103 | for (i=0; i<len; i++)
|
104 | {
|
105 | uint8_t c = *(ascii+offset+i);
|
106 |
|
107 | /* Hex-Ziffer auf ihren Wert abbilden */
|
108 | if (c >= '0' && c <= '9') c -= '0';
|
109 | else if (c >= 'A' && c <= 'F') c -= 'A' - 10;
|
110 | else if (c >= 'a' && c <= 'f') c -= 'a' - 10;
|
111 |
|
112 | val = 16 * val + c;
|
113 | }
|
114 |
|
115 | return val;
|
116 | }
|
117 |
|
118 |
|
119 | uint8_t handle_can_message(Message *message){
|
120 | if(message->id != 1){
|
121 | return -1;
|
122 | }
|
123 | /* switch(can_bootloader_state){
|
124 | case AWAITING_REQUEST:
|
125 | handle_can_request(message);
|
126 | break;
|
127 | case AWAITING_DATA:
|
128 | handle_can_data(message);
|
129 | break;
|
130 |
|
131 | }*/
|
132 |
|
133 | switch(message->data[0]){
|
134 | case FLASH_REQUEST:
|
135 | handle_can_request(message);
|
136 | break;
|
137 | case FLASH_DATA:
|
138 | handle_can_data(message);
|
139 | break;
|
140 | case FLASH_COMPLETE:
|
141 | handle_can_flash_complete(message);
|
142 | break;
|
143 | }
|
144 | return 0;
|
145 | }
|
146 |
|
147 | void handle_can_request(Message *message){
|
148 | if(message->data[1] == DEVICE_ID){
|
149 | char data[1] = {FLASH_REQUEST_CONFIRM};
|
150 | can_bootloader_state = WRITING_TO_CAN;
|
151 | write_message_to_can(DEVICE_ID,1,data);
|
152 | can_bootloader_state = AWAITING_DATA;
|
153 | }
|
154 |
|
155 | }
|
156 |
|
157 | void handle_can_data(Message *message){
|
158 | int8_t buffer = buffer_can_message_data(message->length,message->data);
|
159 | if(buffer != -1){
|
160 | /*switch(parse_hex_line(buffer)){
|
161 | case FLASH_COMPLETE:
|
162 | write_message_to_can(4,
|
163 | }*/
|
164 | write_bootloader_message_buffered_to_can(data_buffer_length,data_buffer[buffer]);
|
165 | }
|
166 | char tmp[1] = {FLASH_DATA_CLEAR_TO_SEND};
|
167 | write_message_to_can(DEVICE_ID,1,tmp);
|
168 | }
|
169 |
|
170 |
|
171 | void handle_can_flash_complete(Message *message){
|
172 | data_buffer[active_data_buffer][11] = '\n';
|
173 | write_bootloader_message_buffered_to_can(12,data_buffer[active_data_buffer]);
|
174 | char data[1] = {FLASH_COMPLETE_CONFIRM};
|
175 | write_message_to_can(DEVICE_ID, 1, data);
|
176 | }
|
177 |
|
178 | uint8_t parse_hex_line(uint8_t buffer){
|
179 | int hex_checksum = 0;
|
180 |
|
181 | uint8_t byte_count = (uint8_t)hex2num(data_buffer[buffer],1,2);
|
182 | uint16_t address = hex2num(data_buffer[buffer],3,4);
|
183 | uint8_t type = (uint8_t)hex2num(data_buffer[buffer],7,2);
|
184 |
|
185 | if(page_count_flag){
|
186 | page_count = address - (address % SPM_PAGESIZE);
|
187 | page_count_flag = 0;
|
188 | }
|
189 |
|
190 | if(type == 2){
|
191 | return FLASHED_LINE_SUCCESSFUL;
|
192 | }
|
193 |
|
194 | hex_checksum += byte_count;
|
195 | hex_checksum += type;
|
196 | hex_checksum += (uint8_t)address;
|
197 | hex_checksum += (uint8_t)(address >> 8);
|
198 |
|
199 | char *tmp_buffer = malloc(sizeof(char)*byte_count);
|
200 |
|
201 | for(uint8_t i=0;i<byte_count;i++){
|
202 | tmp_buffer[i] = (char)hex2num(data_buffer[buffer],9+(i*2),2);
|
203 | hex_checksum += tmp_buffer[i];
|
204 | }
|
205 |
|
206 | uint8_t hex_checksum_byte = hex2num(data_buffer[buffer],9+byte_count*2,2);
|
207 |
|
208 | hex_checksum += hex_checksum_byte;
|
209 | hex_checksum &= 0x00FF;
|
210 |
|
211 | if(hex_checksum != 0){
|
212 | return CHECKSUM_FAILURE;
|
213 | }
|
214 |
|
215 | int8_t status = buffer_page_data(byte_count,tmp_buffer);
|
216 |
|
217 | free(tmp_buffer);
|
218 |
|
219 | if(status != -1){
|
220 | //program_page((uint16_t)page_count,page_buffer[status]);
|
221 | memset(page_buffer[status], 0xFF, sizeof(page_buffer[status]));
|
222 | page_count_flag = 1;
|
223 | }
|
224 |
|
225 | if(type == 1){
|
226 | //program_page((uint16_t)page_count,page_buffer[active_data_buffer]);
|
227 | return FLASH_COMPLETE;
|
228 | }
|
229 |
|
230 | return 1;
|
231 |
|
232 |
|
233 | }
|