can_interface.c


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
}