Commit 63a72567 authored by schneider's avatar schneider
Browse files

add initial bootloader. untested.

parent a76d8ebb
......@@ -67,6 +67,7 @@ CMSIS_ROOT=$(LIBS_DIR)/CMSIS
# Source files for this test (add path to VPATH below)
SRCS = main.c
SRCS += mscmem.c
SRCS += bootloader-usb.c
SRCS += ../lib/card10/mx25lba.c
# Where to find source files for this test
......
/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*
* $Id: main.c 31505 2017-10-20 21:16:29Z zach.metzinger $
*
*******************************************************************************
*/
/**
* @file main.c
* @brief USB Mass Storage Class example
* @details This project creates a mass storage device using either on-board RAM or
* external SPI flash memory. Load the project, connect a cable from the PC
* to the USB connector. A new external drive should appear than can be read
* and written.
*/
#include <stdio.h>
#include <stddef.h>
#include "mxc_config.h"
#include "mxc_sys.h"
#include "mxc_delay.h"
#include "board.h"
#include "led.h"
#include "usb.h"
#include "usb_event.h"
#include "enumerate.h"
#include "msc.h"
#include "descriptors.h"
#include "mscmem.h"
/***** Definitions *****/
#define EVENT_ENUM_COMP MAXUSB_NUM_EVENTS
#define EVENT_REMOTE_WAKE (EVENT_ENUM_COMP + 1)
/***** Global Data *****/
volatile int configured;
volatile int suspended;
volatile unsigned int event_flags;
int remote_wake_en;
/***** Function Prototypes *****/
static int setconfig_callback(usb_setup_pkt *sud, void *cbdata);
static int setfeature_callback(usb_setup_pkt *sud, void *cbdata);
static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata);
static int event_callback(maxusb_event_t evt, void *data);
static void usb_app_sleep(void);
static void usb_app_wakeup(void);
/***** File Scope Variables *****/
/* This EP assignment must match the Configuration Descriptor */
static const msc_cfg_t msc_cfg = {
1, /* EP OUT */
MXC_USBHS_MAX_PACKET, /* OUT max packet size */
2, /* EP IN */
MXC_USBHS_MAX_PACKET, /* IN max packet size */
};
static const msc_idstrings_t ids = {
"MAXIM", /* Vendor string. Maximum of 8 bytes */
"MSC Example", /* Product string. Maximum of 16 bytes */
"1.0" /* Version string. Maximum of 4 bytes */
};
/* Functions to control "disk" memory. See msc.h for definitions. */
static const msc_mem_t mem = {
mscmem_init,
mscmem_start,
mscmem_stop,
mscmem_ready,
mscmem_size,
mscmem_read,
mscmem_write,
};
/* This callback is used to allow the driver to call part specific initialization functions. */
int usb_startup_cb()
{
const sys_cfg_usbhs_t sys_usbhs_cfg = NULL;
return SYS_USBHS_Init(&sys_usbhs_cfg);
}
int usb_shutdown_cb()
{
return SYS_USBHS_Shutdown();
}
/* User-supplied function to delay usec micro-seconds */
void delay_us(unsigned int usec)
{
/* mxc_delay() takes unsigned long, so can't use it directly */
mxc_delay(usec);
}
/******************************************************************************/
void run_usbmsc(void)
{
maxusb_cfg_options_t usb_opts;
printf("Waiting for VBUS...\n");
/* Initialize state */
configured = 0;
suspended = 0;
event_flags = 0;
remote_wake_en = 0;
/* Start out in full speed */
usb_opts.enable_hs = 0;
usb_opts.delay_us = delay_us; /* Function which will be used for delays */
usb_opts.init_callback = usb_startup_cb;
usb_opts.shutdown_callback = usb_shutdown_cb;
/* Initialize the usb module */
if (usb_init(&usb_opts) != 0) {
printf("usb_init() failed\n");
while (1);
}
/* Initialize the enumeration module */
if (enum_init() != 0) {
printf("enum_init() failed\n");
while (1);
}
/* Register enumeration data */
enum_register_descriptor(ENUM_DESC_DEVICE, (uint8_t*)&device_descriptor, 0);
enum_register_descriptor(ENUM_DESC_CONFIG, (uint8_t*)&config_descriptor, 0);
enum_register_descriptor(ENUM_DESC_STRING, lang_id_desc, 0);
enum_register_descriptor(ENUM_DESC_STRING, mfg_id_desc, 1);
enum_register_descriptor(ENUM_DESC_STRING, prod_id_desc, 2);
enum_register_descriptor(ENUM_DESC_STRING, serial_id_desc, 3);
/* Handle configuration */
enum_register_callback(ENUM_SETCONFIG, setconfig_callback, NULL);
/* Handle feature set/clear */
enum_register_callback(ENUM_SETFEATURE, setfeature_callback, NULL);
enum_register_callback(ENUM_CLRFEATURE, clrfeature_callback, NULL);
/* Initialize the class driver */
if (msc_init(&config_descriptor.msc_interface_descriptor, &ids, &mem) != 0) {
printf("msc_init() failed\n");
while (1);
}
/* Register callbacks */
usb_event_enable(MAXUSB_EVENT_NOVBUS, event_callback, NULL);
usb_event_enable(MAXUSB_EVENT_VBUS, event_callback, NULL);
/* Start with USB in low power mode */
usb_app_sleep();
NVIC_EnableIRQ(USB_IRQn);
/* Wait for events */
while (1) {
if (suspended || !configured) {
LED_Off(0);
} else {
LED_On(0);
}
if (event_flags) {
/* Display events */
if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_NOVBUS)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_NOVBUS);
printf("VBUS Disconnect\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_VBUS)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_VBUS);
printf("VBUS Connect\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_BRST)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_BRST);
printf("Bus Reset\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_SUSP)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_SUSP);
printf("Suspended\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_DPACT)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_DPACT);
printf("Resume\n");
} else if (MXC_GETBIT(&event_flags, EVENT_ENUM_COMP)) {
MXC_CLRBIT(&event_flags, EVENT_ENUM_COMP);
printf("Enumeration complete.\n");
} else if (MXC_GETBIT(&event_flags, EVENT_REMOTE_WAKE)) {
MXC_CLRBIT(&event_flags, EVENT_REMOTE_WAKE);
printf("Remote Wakeup\n");
}
}
}
}
/******************************************************************************/
static int setconfig_callback(usb_setup_pkt *sud, void *cbdata)
{
/* Confirm the configuration value */
if (sud->wValue == config_descriptor.config_descriptor.bConfigurationValue) {
configured = 1;
MXC_SETBIT(&event_flags, EVENT_ENUM_COMP);
return msc_configure(&msc_cfg); /* Configure the device class */
} else if (sud->wValue == 0) {
configured = 0;
return msc_deconfigure();
}
return -1;
}
/******************************************************************************/
static int setfeature_callback(usb_setup_pkt *sud, void *cbdata)
{
if(sud->wValue == FEAT_REMOTE_WAKE) {
remote_wake_en = 1;
} else {
// Unknown callback
return -1;
}
return 0;
}
/******************************************************************************/
static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata)
{
if(sud->wValue == FEAT_REMOTE_WAKE) {
remote_wake_en = 0;
} else {
// Unknown callback
return -1;
}
return 0;
}
/******************************************************************************/
static void usb_app_sleep(void)
{
/* TODO: Place low-power code here */
suspended = 1;
}
/******************************************************************************/
static void usb_app_wakeup(void)
{
/* TODO: Place low-power code here */
suspended = 0;
}
/******************************************************************************/
static int event_callback(maxusb_event_t evt, void *data)
{
/* Set event flag */
MXC_SETBIT(&event_flags, evt);
printf("event: %d\n", evt);
switch (evt) {
case MAXUSB_EVENT_NOVBUS:
usb_event_disable(MAXUSB_EVENT_BRST);
usb_event_disable(MAXUSB_EVENT_SUSP);
usb_event_disable(MAXUSB_EVENT_DPACT);
usb_disconnect();
configured = 0;
enum_clearconfig();
msc_deconfigure();
usb_app_sleep();
break;
case MAXUSB_EVENT_VBUS:
usb_event_clear(MAXUSB_EVENT_BRST);
usb_event_enable(MAXUSB_EVENT_BRST, event_callback, NULL);
usb_event_clear(MAXUSB_EVENT_SUSP);
usb_event_enable(MAXUSB_EVENT_SUSP, event_callback, NULL);
usb_connect();
usb_app_sleep();
break;
case MAXUSB_EVENT_BRST:
usb_app_wakeup();
enum_clearconfig();
msc_deconfigure();
configured = 0;
suspended = 0;
break;
case MAXUSB_EVENT_SUSP:
usb_app_sleep();
break;
case MAXUSB_EVENT_DPACT:
usb_app_wakeup();
break;
default:
break;
}
return 0;
}
/******************************************************************************/
void USB_IRQHandler(void)
{
usb_event_handler();
}
......@@ -45,292 +45,268 @@
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "mxc_config.h"
#include "mxc_sys.h"
#include "mxc_delay.h"
#include "flc.h"
#include "icc.h"
#include "crc.h"
#include "board.h"
#include "led.h"
#include "usb.h"
#include "usb_event.h"
#include "enumerate.h"
#include "msc.h"
#include "descriptors.h"
#include "mscmem.h"
/***** Definitions *****/
#define EVENT_ENUM_COMP MAXUSB_NUM_EVENTS
#define EVENT_REMOTE_WAKE (EVENT_ENUM_COMP + 1)
#define BUFFER_SIZE 64
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
/***** Global Data *****/
volatile int configured;
volatile int suspended;
volatile unsigned int event_flags;
int remote_wake_en;
/***** Function Prototypes *****/
static int setconfig_callback(usb_setup_pkt *sud, void *cbdata);
static int setfeature_callback(usb_setup_pkt *sud, void *cbdata);
static int clrfeature_callback(usb_setup_pkt *sud, void *cbdata);
static int event_callback(maxusb_event_t evt, void *data);
static void usb_app_sleep(void);
static void usb_app_wakeup(void);
/***** File Scope Variables *****/
/* This EP assignment must match the Configuration Descriptor */
static const msc_cfg_t msc_cfg = {
1, /* EP OUT */
MXC_USBHS_MAX_PACKET, /* OUT max packet size */
2, /* EP IN */
MXC_USBHS_MAX_PACKET, /* IN max packet size */
};
#include "ff.h"
static const msc_idstrings_t ids = {
"MAXIM", /* Vendor string. Maximum of 8 bytes */
"MSC Example", /* Product string. Maximum of 16 bytes */
"1.0" /* Version string. Maximum of 4 bytes */
};
#define GPIO_PORT_IN PORT_1
#define GPIO_PIN_IN PIN_6
/* Functions to control "disk" memory. See msc.h for definitions. */
static const msc_mem_t mem = {
mscmem_init,
mscmem_start,
mscmem_stop,
mscmem_ready,
mscmem_size,
mscmem_read,
mscmem_write,
};
/* This callback is used to allow the driver to call part specific initialization functions. */
int usb_startup_cb()
{
const sys_cfg_usbhs_t sys_usbhs_cfg = NULL;
return SYS_USBHS_Init(&sys_usbhs_cfg);
}
#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)
int usb_shutdown_cb()
{
return SYS_USBHS_Shutdown();
}
extern void run_usbmsc(void);
DIR dir; /* Directory object */
FATFS FatFs;
/* User-supplied function to delay usec micro-seconds */
void delay_us(unsigned int usec)
static void crc_sw(uint32_t *crcval, uint8_t *data, uint8_t len, uint32_t polynomial)
{
/* mxc_delay() takes unsigned long, so can't use it directly */
mxc_delay(usec);
int i, j;
uint32_t temp;
for(i = 0; i < len; ++i) {
temp = (data[i] & 0xFF);
for(j = 0; j < 8; ++j) {
if((temp ^ *crcval) & 1) {
*crcval >>= 1;
*crcval ^= polynomial;
} else {
*crcval >>= 1;
}
temp >>= 1;
}
}
}
/******************************************************************************/
int main(void)
bool mount(void)
{
maxusb_cfg_options_t usb_opts;
printf("\n\n***** " TOSTRING(TARGET) " USB Mass Storage Example *****\n");
printf("Waiting for VBUS...\n");
/* Initialize state */
configured = 0;
suspended = 0;
event_flags = 0;
remote_wake_en = 0;
/* Start out in full speed */
usb_opts.enable_hs = 0;
usb_opts.delay_us = delay_us; /* Function which will be used for delays */
usb_opts.init_callback = usb_startup_cb;
usb_opts.shutdown_callback = usb_shutdown_cb;
/* Initialize the usb module */
if (usb_init(&usb_opts) != 0) {
printf("usb_init() failed\n");
while (1);
}
/* Initialize the enumeration module */
if (enum_init() != 0) {
printf("enum_init() failed\n");
while (1);
FRESULT res;
res=f_mount(&FatFs,"/",0);
if(res != FR_OK) {
printf("f_mount error %d\n", res);
return false;
}
/* Register enumeration data */
enum_register_descriptor(ENUM_DESC_DEVICE, (uint8_t*)&device_descriptor, 0);
enum_register_descriptor(ENUM_DESC_CONFIG, (uint8_t*)&config_descriptor, 0);
enum_register_descriptor(ENUM_DESC_STRING, lang_id_desc, 0);
enum_register_descriptor(ENUM_DESC_STRING, mfg_id_desc, 1);
enum_register_descriptor(ENUM_DESC_STRING, prod_id_desc, 2);
enum_register_descriptor(ENUM_DESC_STRING, serial_id_desc, 3);
/* Handle configuration */
enum_register_callback(ENUM_SETCONFIG, setconfig_callback, NULL);
/* Handle feature set/clear */
enum_register_callback(ENUM_SETFEATURE, setfeature_callback, NULL);
enum_register_callback(ENUM_CLRFEATURE, clrfeature_callback, NULL);
/* Initialize the class driver */
if (msc_init(&config_descriptor.msc_interface_descriptor, &ids, &mem) != 0) {
printf("msc_init() failed\n");
while (1);
res = f_opendir(&dir, "0:");
if(res != FR_OK) {
printf("f_opendir error %d\n", res);
return false;
}
/* Register callbacks */
usb_event_enable(MAXUSB_EVENT_NOVBUS, event_callback, NULL);
usb_event_enable(MAXUSB_EVENT_VBUS, event_callback, NULL);
/* Start with USB in low power mode */
usb_app_sleep();
NVIC_EnableIRQ(USB_IRQn);
return true;
}
/* Wait for events */
while (1) {
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;
}
if (suspended || !configured) {
LED_Off(0);
} else {
LED_On(0);
uint32_t crcval = 0;
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;
}
crc_sw(&crcval, data, readbytes, TPU_CRC_CCITT);
} while (readbytes == sizeof(data));
if (event_flags) {
/* Display events */
if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_NOVBUS)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_NOVBUS);
printf("VBUS Disconnect\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_VBUS)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_VBUS);
printf("VBUS Connect\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_BRST)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_BRST);
printf("Bus Reset\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_SUSP)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_SUSP);
printf("Suspended\n");
} else if (MXC_GETBIT(&event_flags, MAXUSB_EVENT_DPACT)) {
MXC_CLRBIT(&event_flags, MAXUSB_EVENT_DPACT);
printf("Resume\n");
} else if (MXC_GETBIT(&event_flags, EVENT_ENUM_COMP)) {
MXC_CLRBIT(&event_flags, EVENT_ENUM_COMP);
printf("Enumeration complete.\n");
} else if (MXC_GETBIT(&event_flags, EVENT_REMOTE_WAKE)) {
MXC_CLRBIT(&event_flags, EVENT_REMOTE_WAKE);
printf("Remote Wakeup\n");
}
}
f_close(&file);
if(crcval == 0) {
return true;
} else {
printf("CRC check failed. Final CRC: %d\n", crcval);
return true;
return false;
}
}
/******************************************************************************/
static int setconfig_callback(usb_setup_pkt *sud, void *cbdata)
bool is_update_needed(void)
{
/* Confirm the configuration value */
if (sud->wValue == config_descriptor.config_descriptor.bConfigurationValue) {
configured = 1;
MXC_SETBIT(&event_flags, EVENT_ENUM_COMP);
return msc_configure(&msc_cfg); /* Configure the device class */
} else if (sud->wValue == 0) {
configured = 0;
return msc_deconfigure();
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;
}
return -1;
}
uint8_t *partition = (uint8_t *)(intptr_t)PARTITION_START;
bool different = false;