main.c 6.3 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
#include "flc.h"
#include "icc.h"
11
#include "i2c.h"
schneider's avatar
schneider committed
12
#include "crc.h"
13
14
#include "board.h"
#include "led.h"
schneider's avatar
schneider committed
15
#include "ff.h"
16
#include "crc16-ccitt.h"
17
#include "pb.h"
18
19
20
#include "display.h"
#include "GUI_Paint.h"
#include "card10.h"
21

22
#include "pmic.h"
23

schneider's avatar
schneider committed
24
25
#define GPIO_PORT_IN                PORT_1
#define GPIO_PIN_IN                 PIN_6
26

schneider's avatar
schneider committed
27
#define PARTITION_START (0x10000000 + 64 * 1024)
28
#define PARTITION_END (0x10000000 + 1024 * 1024 - 1)
29

schneider's avatar
schneider committed
30
extern void run_usbmsc(void);
31
32

DIR dir;
schneider's avatar
schneider committed
33
FATFS FatFs;
34

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

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

schneider's avatar
schneider committed
50
51
    return true;
}
52

schneider's avatar
schneider committed
53
54
55
56
57
58
59
60
61
62
63
64
65
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;
    }
66

67
    uint16_t crcval = 0;
schneider's avatar
schneider committed
68
69
70
71
72
73
    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;
74
        }
75
        crcval = crc16_ccitt(crcval, data, readbytes);
schneider's avatar
schneider committed
76
    } while (readbytes == sizeof(data));
77

schneider's avatar
schneider committed
78
79
80
81
82
83
84
    f_close(&file);

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

schneider's avatar
schneider committed
88
bool is_update_needed(void)
89
{
schneider's avatar
schneider committed
90
91
92
93
94
95
96
97
98
99
    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;
100
101
    }

schneider's avatar
schneider committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    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));
116

schneider's avatar
schneider committed
117
    f_close(&file);
118

schneider's avatar
schneider committed
119
    return different;
120
121
}

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

schneider's avatar
schneider committed
131
void flash_partition(void)
132
{
schneider's avatar
schneider committed
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
    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);
164
165
}

schneider's avatar
schneider committed
166
167
168
169
static inline void boot(const void * vtable){
    SCB->VTOR = (uintptr_t) vtable;

	// Reset stack pointer & branch to the new reset vector.
170
171
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
schneider's avatar
schneider committed
172
173
174
175
176
177
178
	__asm(  "mov r0, %0\n"
			"ldr sp, [r0]\n"
			"ldr r0, [r0, #4]\n"
			"bx r0\n"
			:
			: "r"(vtable)
			: "%sp", "r0");
179
#pragma GCC diagnostic pop
schneider's avatar
schneider committed
180
181
};

182
183
184
static void pmic_button(bool falling)
{
	if (falling) {
Rahix's avatar
Rahix committed
185
186
187
188
189
190
191
192
		printf("Resetting ...\n");
		/*
		 * Give the UART fifo time to clear.
		 * TODO: Do this properly
		 */
		for (int i = 0; i < 0x1000000; i++) {
			__asm volatile("nop");
		}
193
194
195
		MXC_GCR->rstr0 = MXC_F_GCR_RSTR0_SYSTEM;
	}
}
196
197

/******************************************************************************/
schneider's avatar
schneider committed
198
int main(void)
199
{
200
201
    printf("\n\nBootloader\n");
    card10_init();
202
203

    pmic_set_button_callback(pmic_button);
schneider's avatar
schneider committed
204

205
206
207
208
209
    Paint_DrawString_EN(0, 16*0, "Bootloader", &Font16, 0x0000, 0xffff);
    Paint_DrawString_EN(0, 16*1, __DATE__, &Font16, 0x0000, 0xffff);

    LCD_Update();

schneider's avatar
schneider committed
210
    // If the button is pressed, we go into MSC mode.
211
    if (PB_Get(3)) {
212
213
        Paint_DrawString_EN(0, 16*2, "USB activated. Waiting.", &Font16, 0x0000, 0xffff);
        LCD_Update();
schneider's avatar
schneider committed
214
215
216
217
218
219
        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);
220
221
    }

schneider's avatar
schneider committed
222
223
    if(mount()) {
        if(check_integrity()) {
224
            printf("Found valid application image\n");
schneider's avatar
schneider committed
225
            if(is_update_needed()) {
226
                printf("Trying to update application from external flash\n");
227
228
                Paint_DrawString_EN(0, 16*4, "Updating...", &Font16, 0x0000, 0xffff);
                LCD_Update();
schneider's avatar
schneider committed
229
230
231
232
233
234
                erase_partition();
                flash_partition();
            } else {
                printf("No update needed\n");
            }
        } else {
235
236
            Paint_DrawString_EN(0, 16*2, "Integrity check failed", &Font16, 0x0000, 0xffff);
            LCD_Update();
schneider's avatar
schneider committed
237
238
            printf("Integrity check failed\n");
        }
239
    } else {
240
241
        Paint_DrawString_EN(0, 16*2, "Failed to mount file system", &Font16, 0x0000, 0xffff);
        LCD_Update();
242
        printf("Failed to mount the external flash\n");
schneider's avatar
schneider committed
243
244
245
246
    }


    printf("Trying to boot\n");
247
248
249
    Paint_DrawString_EN(0, 16*4, "Trying to boot", &Font16, 0x0000, 0xffff);
    LCD_Update();
    //while(1);
schneider's avatar
schneider committed
250
251
252
253
254
255
    // boot partition
    boot((uintptr_t *) PARTITION_START);

    while (1) {
        // Should never be reached.
    }
256
257
258
259
260
261
262
}

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