Project

General

Profile

Download (12.2 KB) Statistics
| Branch: | Tag: | Revision:
1 d33031df Harald Welte
/* ----------------------------------------------------------------------------
2
 *         ATMEL Microcontroller Software Support
3
 * ----------------------------------------------------------------------------
4
 * Copyright (c) 2009, Atmel Corporation
5
 *
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * - Redistributions of source code must retain the above copyright notice,
12
 * this list of conditions and the disclaimer below.
13
 *
14
 * Atmel's name may not be used to endorse or promote products derived from
15
 * this software without specific prior written permission.
16
 *
17
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 * ----------------------------------------------------------------------------
28
 */
29
/**
30
 *  \file
31
 *
32
 *  This file contains all the specific code for the
33
 *  usb_fast_source example.
34
 */
35
36
/*----------------------------------------------------------------------------
37
 *         Headers
38
 *----------------------------------------------------------------------------*/
39
40
#include <board.h>
41
42
#include <stdio.h>
43
#include <string.h>
44
#include <errno.h>
45
#include <stdint.h>
46
#include <stdbool.h>
47
#include <stdbool.h>
48
49
#include <irq/irq.h>
50
#include <pio/pio.h>
51
#include <pio/pio_it.h>
52
#include <utility/trace.h>
53
#include <utility/led.h>
54
55
#include <memories/flash/flashd.h>
56
57
#include <peripherals/rstc/rstc.h>
58
59
#include <usb/device/core/USBD.h>
60
#include <usb/device/core/USBDDriver.h>
61
#include <usb/device/dfu/dfu.h>
62
63
#include "dfu_desc.h"
64
65 5dcfd6a1 Christian Daniel
#include "opcode.h"
66
67 d33031df Harald Welte
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
68
69
/*----------------------------------------------------------------------------
70
 *         Definitions
71
 *----------------------------------------------------------------------------*/
72
73
/// Use for power management
74
#define STATE_IDLE    0
75
/// The USB device is in suspend state
76
#define STATE_SUSPEND 4
77
/// The USB device is in resume state
78
#define STATE_RESUME  5
79
80
//------------------------------------------------------------------------------
81
//         Internal variables
82
//------------------------------------------------------------------------------
83
/// State of USB, for suspend and resume
84
unsigned char USBState = STATE_IDLE;
85
86
/*----------------------------------------------------------------------------
87
 *         VBus monitoring (optional)
88
 *----------------------------------------------------------------------------*/
89
90
/**  VBus pin instance. */
91
static const Pin pinVbus = PIN_USB_VBUS;
92
93
/* this needs to be in sync with usb-strings.txt !! */
94
enum dfu_altif {
95
	ALTIF_APP,
96
	ALTIF_BOOT,
97
	ALTIF_RAM,
98
	ALTIF_FPGA
99
};
100
101
/**
102
 *  Handles interrupts coming from PIO controllers.
103
 */
104
static void ISR_Vbus(const Pin *pPin)
105
{
106
    /* Check current level on VBus */
107
    if (PIO_Get(&pinVbus))
108
    {
109 5dcfd6a1 Christian Daniel
        //TRACE_INFO("VBUS conn\n\r");
110 d33031df Harald Welte
        USBD_Connect();
111
    }
112
    else
113
    {
114 5dcfd6a1 Christian Daniel
        //TRACE_INFO("VBUS discon\n\r");
115 d33031df Harald Welte
        USBD_Disconnect();
116
    }
117
}
118
119
/**
120
 *  Configures the VBus pin to trigger an interrupt when the level on that pin
121
 *  changes.
122
 */
123
static void VBus_Configure( void )
124
{
125
    /* Configure PIO */
126
    PIO_Configure(&pinVbus, 1);
127
    PIO_ConfigureIt(&pinVbus, ISR_Vbus);
128
    PIO_EnableIt(&pinVbus);
129
130
    /* Check current level on VBus */
131
    if (PIO_Get(&pinVbus))
132
    {
133
        /* if VBUS present, force the connect */
134
        USBD_Connect();
135
    }
136
    else
137
    {
138 5dcfd6a1 Christian Daniel
        //TRACE_INFO("discon\n\r");
139 d33031df Harald Welte
        USBD_Disconnect();
140
    }
141
}
142
143
/*----------------------------------------------------------------------------
144
 *         USB Power Control
145
 *----------------------------------------------------------------------------*/
146
147
#ifdef PIN_USB_POWER_ENA
148
/** Power Enable A (MicroAB Socket) pin instance. */
149
static const Pin pinPOnA = PIN_USB_POWER_ENA;
150
#endif
151
#ifdef PIN_USB_POWER_ENB
152
/** Power Enable B (A Socket) pin instance. */
153
static const Pin pinPOnB = PIN_USB_POWER_ENB;
154
#endif
155
#ifdef PIN_USB_POWER_ENC
156
/** Power Enable C (A Socket) pin instance. */
157
static const Pin pinPOnC = PIN_USB_POWER_ENC;
158
#endif
159
/**
160
 * Configures the Power Enable pin to disable self power.
161
 */
162
static void USBPower_Configure( void )
163
{
164
  #ifdef PIN_USB_POWER_ENA
165
    PIO_Configure(&pinPOnA, 1);
166
  #endif
167
  #ifdef PIN_USB_POWER_ENB
168
    PIO_Configure(&pinPOnB, 1);
169
  #endif
170
  #ifdef PIN_USB_POWER_ENC
171
    PIO_Configure(&pinPOnC, 1);
172
  #endif
173
}
174
175
/*----------------------------------------------------------------------------
176
 *         Callbacks re-implementation
177
 *----------------------------------------------------------------------------*/
178
179
//------------------------------------------------------------------------------
180
/// Invoked when the USB device leaves the Suspended state. By default,
181
/// configures the LEDs.
182
//------------------------------------------------------------------------------
183
void USBDCallbacks_Resumed(void)
184
{
185
    // Initialize LEDs
186
    LED_Configure(USBD_LEDPOWER);
187
    LED_Set(USBD_LEDPOWER);
188
    LED_Configure(USBD_LEDUSB);
189
    LED_Clear(USBD_LEDUSB);
190
    USBState = STATE_RESUME;
191
}
192
193
//------------------------------------------------------------------------------
194
/// Invoked when the USB device gets suspended. By default, turns off all LEDs.
195
//------------------------------------------------------------------------------
196
void USBDCallbacks_Suspended(void)
197
{
198
    // Turn off LEDs
199
    LED_Clear(USBD_LEDPOWER);
200
    LED_Clear(USBD_LEDUSB);
201
    USBState = STATE_SUSPEND;
202
}
203
204
/* USBD callback */
205
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
206
{
207
	USBDFU_DFU_RequestHandler(request);
208
}
209
210
/* USBD callback */
211
void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
212
						 unsigned char setting)
213
{
214 5dcfd6a1 Christian Daniel
	//TRACE_INFO("DFU: IfSettingChgd(if=%u, alt=%u)\n\r", interface, setting);
215 d33031df Harald Welte
}
216
217
#define BOOT_FLASH_SIZE		(16 * 1024)
218
219
struct flash_part {
220
	void *base_addr;
221
	uint32_t size;
222
};
223
224
static const struct flash_part flash_parts[] = {
225
	[ALTIF_BOOT] = {
226
		.base_addr =	AT91C_IFLASH0,
227
		.size =		BOOT_FLASH_SIZE,
228
	},
229
	[ALTIF_APP] = {
230
		.base_addr =	(AT91C_IFLASH + BOOT_FLASH_SIZE),
231
		.size =		(AT91C_IFLASH0_SIZE - BOOT_FLASH_SIZE),
232
	},
233
	[ALTIF_RAM] = {
234
		.base_addr =	AT91C_IRAM,
235
		.size =		AT91C_IRAM_SIZE,
236
	},
237
	[ALTIF_FPGA] = {
238 5dcfd6a1 Christian Daniel
		.base_addr =	0,
239
		.size =		16*1024*1024, // really no limit
240 d33031df Harald Welte
	},
241
};
242
243
/* DFU callback */
244
int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
245
			 uint8_t *buf, unsigned int req_len)
246
{
247 5dcfd6a1 Christian Daniel
	return -EINVAL;
248
#if 0
249 d33031df Harald Welte
	struct flash_part *part;
250
	void *end, *addr;
251
	uint32_t real_len;
252
253 5dcfd6a1 Christian Daniel
	//TRACE_INFO("DFU: handle_upload(%u, %u, %u)\n\r", altif, offset, req_len);
254 d33031df Harald Welte
255
	if (altif > ARRAY_SIZE(flash_parts))
256
		return -EINVAL;
257
258
	part = &flash_parts[altif];
259
260
	addr = part->base_addr + offset;
261
	end = part->base_addr + part->size;
262
263
	real_len = end - addr;
264
	if (req_len < real_len)
265
		real_len = req_len;
266
267
	LED_Set(USBD_LEDOTHER);
268
	memcpy(buf, addr, real_len);
269
	LED_Clear(USBD_LEDOTHER);
270
271
	return real_len;
272 5dcfd6a1 Christian Daniel
#endif
273
}
274
275
extern unsigned short g_usDataType;
276
277
static uint8_t fpgaBuf[1024];
278
static uint fpgaBufStart; // file offset of first byte in buffer
279
static uint fpgaBufEnd;
280
static uint fpgaBufFill;
281
static uint fpgaBufRPtr;
282
static uint fpgaPushedAddr;
283
284
short int ispProcessVME();
285
void EnableHardware();
286
287
void fpgaPushAddr()
288
{
289
	fpgaPushedAddr = fpgaBufRPtr;
290
}
291
292
void fpgaPopAddr()
293
{
294
	printf("*");
295
	fpgaBufRPtr = fpgaPushedAddr;
296
}
297
298
uint8_t fpgaGetByte()
299
{
300
	uint8_t res = fpgaBuf[fpgaBufRPtr - fpgaBufStart];
301
	fpgaBufRPtr++;
302
303
	return res;
304
}
305
306
static int fpgaFlash(unsigned int offset, const uint8_t* buf, unsigned int len)
307
{
308
	int i;
309
310
	if(offset == 0) {
311
		for(i = 0; i < len; i++)
312
			fpgaBuf[i] = buf[i];
313
		fpgaBufStart = 0;
314
		fpgaBufEnd = len;
315
		fpgaBufFill = len;
316
		fpgaBufRPtr = 0;
317
318
		*((uint32_t*)(0x400e0410)) = (1 << 11);
319
		*((uint32_t*)(0x400e0e00 + 0x44)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
320
		*((uint32_t*)(0x400e0e00 + 0x60)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
321
		*((uint32_t*)(0x400e0e00 + 0x54)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
322
		*((uint32_t*)(0x400e0e00 + 0x10)) = (1 << 5) | (1 << 7) | (1 << 8);
323
		*((uint32_t*)(0x400e0e00 + 0x00)) = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
324
325
		if(fpgaGetByte())
326
			g_usDataType = COMPRESS;
327
		else g_usDataType = 0;
328
329
	    EnableHardware();
330
	} else {
331
		for(i = 0; i < len; i++)
332
			fpgaBuf[fpgaBufFill + i] = buf[i];
333
		fpgaBufEnd += len;
334
		fpgaBufFill += len;
335
	}
336
/*
337
	printf("\n\rs:%d,e:%d,f:%d,r:%d,p:%d\n",
338
		fpgaBufStart, fpgaBufEnd, fpgaBufFill, fpgaBufRPtr, fpgaPushedAddr);
339
*/
340
	while(fpgaBufEnd - fpgaBufRPtr > 192) {
341
		if((i = ispProcessVME()) < 0)
342
			return -1;
343
	}
344
345
	if(fpgaBufFill > 384) {
346
		uint moveby = fpgaBufFill - 384;
347
		uint movelen = fpgaBufFill - movelen;
348
349
		for(i = 0; i < movelen; i++)
350
			fpgaBuf[i] = fpgaBuf[i + moveby];
351
		fpgaBufStart += moveby;
352
		fpgaBufFill -= moveby;
353
/*
354
		printf("\n\rs:%d,e:%d,f:%d,r:%d,p:%d\n",
355
			fpgaBufStart, fpgaBufEnd, fpgaBufFill, fpgaBufRPtr, fpgaPushedAddr);
356
*/
357
	}
358
359
	return 0;
360 d33031df Harald Welte
}
361
362
/* DFU callback */
363
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
364
			 uint8_t *buf, unsigned int len)
365
{
366
	struct flash_part *part;
367
	void *end, *addr;
368
	int rc;
369
370
	TRACE_INFO("DFU: handle_dnload(%u, %u, %u)\n\r", altif, offset, len);
371
372
	if (altif > ARRAY_SIZE(flash_parts))
373
		return -EINVAL;
374
375
	part = &flash_parts[altif];
376
377
	addr = part->base_addr + offset;
378
	end = part->base_addr + part->size;
379
380
	if (addr + len > end) {
381 5dcfd6a1 Christian Daniel
		TRACE_ERROR("Write beyond end (%u)\n\r", altif);
382 d33031df Harald Welte
		g_dfu.status = DFU_STATUS_errADDRESS;
383
		return DFU_RET_STALL;
384
	}
385
386
	switch (altif) {
387
	case ALTIF_APP:
388
		/* SAM3U Errata 46.2.1.3 */
389
		SetFlashWaitState(6);
390
		LED_Set(USBD_LEDOTHER);
391
		rc = FLASHD_Write(addr, buf, len);
392
		LED_Clear(USBD_LEDOTHER);
393
		/* SAM3U Errata 46.2.1.3 */
394
		SetFlashWaitState(2);
395
		if (rc != 0) {
396 5dcfd6a1 Christian Daniel
			TRACE_ERROR("Write error (%u)\n\r", altif);
397
			g_dfu.status = DFU_STATUS_errPROG;
398
			return DFU_RET_STALL;
399
		}
400
		break;
401
402
	case ALTIF_FPGA:
403
		LED_Set(USBD_LEDOTHER);
404
		rc = fpgaFlash(offset, buf, len);
405
		LED_Clear(USBD_LEDOTHER);
406
		/* SAM3U Errata 46.2.1.3 */
407
		if (rc != 0) {
408
			TRACE_ERROR("FPGA error (ofs %d)\n\r", fpgaBufRPtr);
409 d33031df Harald Welte
			g_dfu.status = DFU_STATUS_errPROG;
410
			return DFU_RET_STALL;
411
		}
412
		break;
413 5dcfd6a1 Christian Daniel
414 d33031df Harald Welte
	default:
415 5dcfd6a1 Christian Daniel
		TRACE_WARNING("Not implemented (%u)\n\r", altif);
416 d33031df Harald Welte
		g_dfu.status = DFU_STATUS_errTARGET;
417
		break;
418
	}
419
420
	return DFU_RET_ZLP;
421
}
422
423
/* DFU callback */
424
void dfu_drv_updstatus(void)
425
{
426
	TRACE_INFO("DFU: updstatus()\n\r");
427
428
	if (g_dfu.state == DFU_STATE_dfuMANIFEST_SYNC)
429
		g_dfu.state = DFU_STATE_dfuMANIFEST;
430
}
431
432
/*----------------------------------------------------------------------------
433
 *         Exported functions
434
 *----------------------------------------------------------------------------*/
435
436
extern void USBD_IrqHandler(void);
437 5dcfd6a1 Christian Daniel
/*
438 d33031df Harald Welte
static const char *rst_type_strs[8] = {
439
	"General", "Backup", "Watchdog", "Softare", "User", "5", "6", "7"
440
};
441 5dcfd6a1 Christian Daniel
*/
442 d33031df Harald Welte
int main(void)
443
{
444
    volatile uint8_t usbConn = 0;
445
    unsigned long rst_type;
446
447
    TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
448
449 dc23dc5a Harald Welte
    printf("-- Osmocom USB DFU (" BOARD_NAME ") " GIT_REVISION " --\n\r");
450
    printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
451 d33031df Harald Welte
452
    rst_type = (RSTC_GetStatus() >> 8) & 0x7;
453 5dcfd6a1 Christian Daniel
    //printf("-- Reset type: %s --\n\r", rst_type_strs[rst_type]);
454 d33031df Harald Welte
455
    chipid_to_usbserial();
456
457
    /* If they are present, configure Vbus & Wake-up pins */
458
    PIO_InitializeInterrupts(0);
459
460
    /* Initialize all USB power (off) */
461
    USBPower_Configure();
462
463
    /* Audio STREAM LED */
464
    LED_Configure(USBD_LEDOTHER);
465
466
    USBDFU_Initialize(&dfu_descriptors);
467
468
    /* connect if needed */
469
    VBus_Configure();
470
471
    static int state = 0;
472
473
    /* Infinite loop */
474
    while (1)
475
    {
476
        if (USBD_GetState() < USBD_STATE_CONFIGURED)
477
        {
478
            usbConn = 0;
479
            continue;
480
        } else
481
		usbConn = 1;
482
	/* This works, but breaks JTAG debugging */
483
	//__WFE();
484
    }
485
}
486
/** \endcond */
Add picture from clipboard (Maximum size: 48.8 MB)