main.c 5.23 KB
Newer Older
1
2
#include <stdio.h>
#include <stddef.h>
schneider's avatar
schneider committed
3
4
5
#include <stdbool.h>
#include <string.h>

6
7
8
#include "mxc_config.h"
#include "mxc_sys.h"
#include "mxc_delay.h"
schneider's avatar
schneider committed
9
10
11
#include "flc.h"
#include "icc.h"
#include "crc.h"
12
13
#include "board.h"
#include "led.h"
schneider's avatar
schneider committed
14
#include "ff.h"
15
16
#include "crc16-ccitt.h"

17

schneider's avatar
schneider committed
18
19
#define GPIO_PORT_IN                PORT_1
#define GPIO_PIN_IN                 PIN_6
20
21


schneider's avatar
schneider committed
22
23
24
#define PARTITION_START (0x10000000 + 64 * 1024)
#define PARTITION_END (0x10000000 + 512 * 1024 - 1) /* TODO: check if 1 MB also works. Might have to enable the second bank */
//#define PARTITION_END (0x10000000 + 1024 * 1024 - 1)
25

schneider's avatar
schneider committed
26
extern void run_usbmsc(void);
27
28

DIR dir;
schneider's avatar
schneider committed
29
FATFS FatFs;
30

schneider's avatar
schneider committed
31
bool mount(void)
32
{
schneider's avatar
schneider committed
33
34
35
36
37
    FRESULT res;
    res=f_mount(&FatFs,"/",0);
    if(res != FR_OK) {
        printf("f_mount error %d\n", res);
        return false;
38
39
    }

schneider's avatar
schneider committed
40
41
42
43
    res = f_opendir(&dir, "0:");
    if(res != FR_OK) {
        printf("f_opendir error %d\n", res);
        return false;
44
45
    }

schneider's avatar
schneider committed
46
47
    return true;
}
48

schneider's avatar
schneider committed
49
50
51
52
53
54
55
56
57
58
59
60
61
bool check_integrity(void)
{
    FIL file;
    UINT readbytes;
    char *filename = "card10.bin";
    uint8_t data[512];
    FRESULT res;

    res=f_open(&file, filename, FA_OPEN_EXISTING|FA_READ);
    if(res != FR_OK) {
        printf("f_open error %d\n", res);
        return false;
    }
62

63
    uint16_t crcval = 0;
schneider's avatar
schneider committed
64
65
66
67
68
69
    do {
        res = f_read(&file, data, sizeof(data), &readbytes);
        if(res != FR_OK) {
            printf("f_read error %d\n", res);
            crcval = 1; // Make sure to fail the test
            break;
70
        }
71
        crcval = crc16_ccitt(crcval, data, readbytes);
schneider's avatar
schneider committed
72
    } while (readbytes == sizeof(data));
73

schneider's avatar
schneider committed
74
75
76
77
78
79
80
    f_close(&file);

    if(crcval == 0) {
        return true;
    } else {
        printf("CRC check failed. Final CRC: %d\n", crcval);
        return false;
81
82
83
    }
}

schneider's avatar
schneider committed
84
bool is_update_needed(void)
85
{
schneider's avatar
schneider committed
86
87
88
89
90
91
92
93
94
95
    FIL file;
    UINT readbytes;
    char *filename = "card10.bin";
    uint8_t data[512];
    FRESULT res;

    res=f_open(&file, filename, FA_OPEN_EXISTING|FA_READ);
    if(res != FR_OK) {
        printf("f_open error %d\n", res);
        return false;
96
97
    }

schneider's avatar
schneider committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    uint8_t *partition = (uint8_t *)(intptr_t)PARTITION_START;
    bool different = false;
    do {
        res = f_read(&file, data, sizeof(data), &readbytes);
        if(res != FR_OK) {
            printf("f_read error %d\n", res);
            break; /* Going to return false, don't want to use this file */
        }
        if(memcmp(partition, data, readbytes)) {
            different = true;
            break;
        }
        partition += readbytes;
    } while (readbytes == sizeof(data));
112

schneider's avatar
schneider committed
113
    f_close(&file);
114

schneider's avatar
schneider committed
115
    return different;
116
117
}

schneider's avatar
schneider committed
118
void erase_partition(void)
119
{
schneider's avatar
schneider committed
120
121
122
123
    int ret = FLC_MultiPageErase(PARTITION_START, PARTITION_END);
    if(ret != E_NO_ERROR) {
        printf("FLC_MultiPageErase failed with %d\n", ret);
        while(1);
124
125
126
    }
}

schneider's avatar
schneider committed
127
void flash_partition(void)
128
{
schneider's avatar
schneider committed
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
    FIL file;
    UINT readbytes;
    char *filename = "card10.bin";
    uint8_t data[512];
    FRESULT res;

    res=f_open(&file, filename, FA_OPEN_EXISTING|FA_READ);
    if(res != FR_OK) {
        printf("f_open error %d\n", res);
        while(1);
    }

    uint32_t partition = PARTITION_START;

    ICC_Disable();
    do {
        res = f_read(&file, data, sizeof(data), &readbytes);
        if(res != FR_OK) {
            printf("f_read error %d\n", res);
            break; /* Going to return false, don't want to use this file */
        }
        int ret = FLC_Write(partition, readbytes, (uint32_t *)data); /* wild cast. not sure if this works */
        if(ret != E_NO_ERROR) {
            printf("FLC_Write failed with %d\n", ret);
            while(1);
        }
        partition += readbytes;
    } while (readbytes == sizeof(data));
    ICC_Enable();

    f_close(&file);
160
161
}

schneider's avatar
schneider committed
162
163
164
165
166
167
168
169
170
171
172
173
174
static inline void boot(const void * vtable){
    SCB->VTOR = (uintptr_t) vtable;

	// Reset stack pointer & branch to the new reset vector.
	__asm(  "mov r0, %0\n"
			"ldr sp, [r0]\n"
			"ldr r0, [r0, #4]\n"
			"bx r0\n"
			:
			: "r"(vtable)
			: "%sp", "r0");
};

175
176

/******************************************************************************/
schneider's avatar
schneider committed
177
int main(void)
178
{
schneider's avatar
schneider committed
179
180
181

    printf("\n\nBootloader\n");
    // If the button is pressed, we go into MSC mode.
182
183
    //if (!GPIO_InGet(&gpio_in)) {
    if (PB_Get(0)) {
schneider's avatar
schneider committed
184
185
186
187
188
189
        run_usbmsc();

        // If we return, don't try to boot. Maybe rather trigger a software reset.
        // Reason: Not sure in which state the USB peripheral is and what kind
        // of interrupts are active.
        while(1);
190
191
192
    }


schneider's avatar
schneider committed
193
194
    if(mount()) {
        if(check_integrity()) {
195
            printf("Found valid application image\n");
schneider's avatar
schneider committed
196
            if(is_update_needed()) {
197
                printf("Trying to update application from external flash\n");
schneider's avatar
schneider committed
198
199
200
201
202
203
204
205
206
                MXC_FLC0->clkdiv = 54;
                erase_partition();
                flash_partition();
            } else {
                printf("No update needed\n");
            }
        } else {
            printf("Integrity check failed\n");
        }
207
208
    } else {
        printf("Failed to mount the external flash\n");
schneider's avatar
schneider committed
209
210
211
212
213
214
215
216
217
218
    }


    printf("Trying to boot\n");
    // boot partition
    boot((uintptr_t *) PARTITION_START);

    while (1) {
        // Should never be reached.
    }
219
220
221
222
223
224
225
}

/******************************************************************************/
void SysTick_Handler(void)
{
    mxc_delay_handler();
}