Skip to content
Snippets Groups Projects
Commit 8ad3aa32 authored by schneider's avatar schneider
Browse files

add usb example as base for bootloader

parent 6002c36a
No related branches found
No related tags found
No related merge requests found
file build/max32665.elf
target remote localhost:3333
################################################################################
# Copyright (C) 2017 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.
#
# $Date: 2018-08-10 21:35:48 +0000 (Fri, 10 Aug 2018) $
# $Revision: 36863 $
#
###############################################################################
# This is the name of the build output file
ifeq "$(PROJECT)" ""
PROJECT=max32665
endif
# Specify the target processor
ifeq "$(TARGET)" ""
TARGET=MAX32665
endif
# Create Target name variables
TARGET_UC:=$(shell echo $(TARGET) | tr a-z A-Z)
TARGET_LC:=$(shell echo $(TARGET) | tr A-Z a-z)
# Select 'GCC' or 'IAR' compiler
COMPILER=GCC
# Specify the board used
ifeq "$(BOARD)" ""
BOARD=EvKit_V1
endif
# This is the path to the CMSIS root directory
ifeq "$(MAXIM_PATH)" ""
LIBS_DIR=../sdk/Libraries
else
LIBS_DIR=/$(subst \,/,$(subst :,,$(MAXIM_PATH))/Firmware/$(TARGET_UC)/Libraries)
endif
CMSIS_ROOT=$(LIBS_DIR)/CMSIS
# Source files for this test (add path to VPATH below)
SRCS = main.c
SRCS += mscmem.c
# Where to find source files for this test
VPATH = .
# Where to find header files for this test
IPATH = .
# Enable assertion checking for development
PROJ_CFLAGS+=-DMXC_ASSERT_ENABLE
# Specify the target revision to override default
# "A2" in ASCII
# TARGET_REV=0x4132
# Use this variables to specify and alternate tool path
#TOOL_DIR=/opt/gcc-arm-none-eabi-4_8-2013q4/bin
# Use these variables to add project specific tool options
#PROJ_CFLAGS+=--specs=nano.specs
#PROJ_LDFLAGS+=--specs=nano.specs
# Point this variable to a startup file to override the default file
#STARTUPFILE=start.S
# Set MXC_OPTIMIZE to override the default optimization level
#MXC_OPTIMIZE_CFLAGS=-Og
# Point this variable to a linker file to override the default file
# LINKERFILE=$(CMSIS_ROOT)/Device/Maxim/$(TARGET_UC)/Source/GCC/$(TARGET_LC).ld
################################################################################
# Include external library makefiles here
# Include the BSP
BOARD_DIR=$(LIBS_DIR)/Boards/$(BOARD)
include $(BOARD_DIR)/board.mk
# Include the peripheral driver
PERIPH_DRIVER_DIR=$(LIBS_DIR)/$(TARGET_UC)PeriphDriver
include $(PERIPH_DRIVER_DIR)/periphdriver.mk
MAXUSB_DIR=$(LIBS_DIR)/MAXUSB
include $(MAXUSB_DIR)/maxusb.mk
################################################################################
# Include the rules for building for this target. All other makefiles should be
# included before this one.
include $(CMSIS_ROOT)/Device/Maxim/$(TARGET_UC)/Source/$(COMPILER)/$(TARGET_LC).mk
# The rule to clean out all the build products.
distclean: clean
$(MAKE) -C ${PERIPH_DRIVER_DIR} clean
/*******************************************************************************
* Copyright (C) 2017 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.
*
* Description: Communications Device Class ACM (Serial Port) over USB
* $Id: descriptors.h 31172 2017-10-05 19:05:57Z zach.metzinger $
*
*******************************************************************************
*/
#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_
#include <stdint.h>
#include "usb.h"
#include "hid_kbd.h"
usb_device_descriptor_t __attribute__((aligned(4))) device_descriptor = {
0x12, /* bLength = 18 */
0x01, /* bDescriptorType = Device */
0x0110, /* bcdUSB USB spec rev (BCD) */
0x00, /* bDeviceClass = mass storage (0) */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 is 64 bytes */
0x0B6A, /* idVendor (Maxim Integrated) */
0x4402, /* idProduct */
0x0100, /* bcdDevice */
0x01, /* iManufacturer Descriptor ID */
0x02, /* iProduct Descriptor ID */
0x03, /* iSerialNumber = (0) No string */
0x01 /* bNumConfigurations */
};
__attribute__((aligned(4)))
struct __attribute__((packed)) {
usb_configuration_descriptor_t config_descriptor;
usb_interface_descriptor_t msc_interface_descriptor;
usb_endpoint_descriptor_t endpoint_descriptor_1;
usb_endpoint_descriptor_t endpoint_descriptor_2;
} config_descriptor =
{
{
0x09, /* bLength = 9 */
0x02, /* bDescriptorType = Config (2) */
0x0020, /* wTotalLength(L/H) */
0x01, /* bNumInterfaces */
0x01, /* bConfigValue */
0x00, /* iConfiguration */
0xC0, /* bmAttributes (self-powered, no remote wakeup) */
0x01, /* MaxPower is 2ma (units are 2ma/bit) */
},
{ /* First Interface Descriptor For MSC Interface */
0x09, /* bLength = 9 */
0x04, /* bDescriptorType = Interface (4) */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x02, /* bNumEndpoints (one for INm one for OUT) */
0x08, /* bInterfaceClass = Mass Storage (8) */
0x06, /* bInterfaceSubClass = SCSI Transparent Command Set */
0x50, /* bInterfaceProtocol = Bulk-Only Transport */
0x00, /* iInterface */
},
{ /* OUT Endpoint 1 (Descriptor #1) */
0x07, /* bLength */
0x05, /* bDescriptorType (Endpoint) */
0x01, /* bEndpointAddress (EP1-OUT) */
0x02, /* bmAttributes (bulk) */
0x0040, /* wMaxPacketSize */
0x00, /* bInterval (N/A) */
},
{ /* IN Endpoint 2 (Descriptor #2) */
0x07, /* bLength */
0x05, /* bDescriptorType (Endpoint) */
0x82, /* bEndpointAddress (EP2-IN) */
0x02, /* bmAttributes (bulk) */
0x0040, /* wMaxPacketSize */
0x00 /* bInterval (N/A) */
}
};
__attribute__((aligned(4)))
uint8_t lang_id_desc[] = {
0x04, /* bLength */
0x03, /* bDescriptorType */
0x09, 0x04 /* bString = wLANGID (see usb_20.pdf 9.6.7 String) */
};
__attribute__((aligned(4)))
uint8_t mfg_id_desc[] = {
0x22, /* bLength */
0x03, /* bDescriptorType */
'M', 0,
'a', 0,
'x', 0,
'i', 0,
'm', 0,
' ', 0,
'I', 0,
'n', 0,
't', 0,
'e', 0,
'g', 0,
'r', 0,
'a', 0,
't', 0,
'e', 0,
'd', 0,
};
__attribute__((aligned(4)))
uint8_t prod_id_desc[] = {
0x38, /* bLength */
0x03, /* bDescriptorType */
'M', 0,
'A', 0,
'X', 0,
'U', 0,
'S', 0,
'B', 0,
' ', 0,
'M', 0,
'a', 0,
's', 0,
's', 0,
' ', 0,
'S', 0,
't', 0,
'o', 0,
'r', 0,
'a', 0,
'g', 0,
'e', 0,
' ', 0,
'E', 0,
'x', 0,
'a', 0,
'm', 0,
'p', 0,
'l', 0,
'e', 0,
};
/* Not currently used (see device descriptor), but could be enabled if desired */
__attribute__((aligned(4)))
uint8_t serial_id_desc[] = {
26, /* bLength */
0x03, /* bDescriptorType */
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'1',0
};
#endif /* _DESCRIPTORS_H_ */
/*******************************************************************************
* 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)
#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 */
};
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);
}
/******************************************************************************/
int main(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);
}
/* 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);
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();
}
/******************************************************************************/
void SysTick_Handler(void)
{
mxc_delay_handler();
}
/*******************************************************************************
* Copyright (C) 2017 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.
*
* Description: Communications Device Class ACM (Serial Port) over USB
* $Id: descriptors.h 31172 2017-10-05 19:05:57Z zach.metzinger $
*
*******************************************************************************
*/
/**
* @file mscmem.h
* @brief Memory routines used by the USB Mass Storage Class example.
* See the msc_mem_t structure in msc.h for function details.
* @details Functions are provided for using the internal RAM of the
* device or the external SPI flash memory. Use the SPIXF_DISK
* and RAM_DISK defines to select the desired memory at compile
* time.
*/
#include "mscmem.h"
#include <string.h>
#include <stdio.h>
#include "mx25.h"
/***** Definitions *****/
#define SPIXF_DISK 1
#define RAM_DISK 0
#define LBA_SIZE 512 /* Size of "logical blocks" in bytes */
#define LBA_SIZE_SHIFT 9 /* The shift value used to convert between addresses and block numbers */
/***** Global Data *****/
/***** File Scope Variables *****/
static int initialized = 0;
static int running = 0;
#if SPIXF_DISK
#define MX25_BAUD 5000000 /* SPI clock rate to communicate with the MX25 */
#define MX25_SECTOR_SIZE 4096 /* Number of bytes in one sector of the MX25 */
#define MX25_SECTOR_SIZE_SHIFT 12 /* The shift value used to convert between addresses and block numbers */
#define MX25_NUM_SECTORS 2048 /* Total number of sectors in the MX25 */
#define LBA_PER_SECTOR (MX25_SECTOR_SIZE >> LBA_SIZE_SHIFT)
#define INVALID_SECTOR MX25_NUM_SECTORS /* Use a sector number past the end of memory to indicate invalid */
/***** File Scope Variables *****/
static uint32_t sectorNum = INVALID_SECTOR;
static uint8_t sector[MX25_SECTOR_SIZE];
static int sectorDirty = 0;
/***** Function Prototypes *****/
static uint32_t getSectorNum(uint32_t lba);
static uint32_t getSectorAddr(uint32_t lba);
static uint32_t getSector(uint32_t num);
/******************************************************************************/
static uint32_t getSectorNum(uint32_t lba)
{
/* Absolute_address = lba * LBA_SIZE */
/* Sector_num = Absolute_address / MX25_SECTOR_SIZE */
/* Sector_num = lba * 512 / 4096 */
return lba >> (MX25_SECTOR_SIZE_SHIFT - LBA_SIZE_SHIFT);
}
/******************************************************************************/
static uint32_t getSectorAddr(uint32_t lba)
{
/* eight 512 byte blocks in each sector */
return (lba & (LBA_PER_SECTOR - 1)) << LBA_SIZE_SHIFT;
}
/******************************************************************************/
static uint32_t getSector(uint32_t num)
{
/* New sector requested? */
if(sectorNum != num) {
/* Is the current sector real? */
if(sectorNum != INVALID_SECTOR) {
/* Was it written to after it was read from memory? */
if(sectorDirty) {
/* Erase the old data. */
MX25_Erase(sectorNum << MX25_SECTOR_SIZE_SHIFT, MX25_Erase_4K);
/* Write the new */
MX25_Program_Page(sectorNum << MX25_SECTOR_SIZE_SHIFT, sector, MX25_SECTOR_SIZE, SPIXFC_WIDTH_4);
/* Mark data as clean */
sectorDirty = 0;
}
}
/* Requesting a new valid sector? */
if(num != INVALID_SECTOR) {
MX25_Read(num << MX25_SECTOR_SIZE_SHIFT, sector, MX25_SECTOR_SIZE, SPIXFC_WIDTH_4);
sectorDirty = 0;
sectorNum = num;
}
}
return 0;
}
/******************************************************************************/
int mscmem_init()
{
if(!initialized) {
MX25_Init();
MX25_Reset();
MX25_Quad(1);
initialized = 1;
}
return 0;
}
/******************************************************************************/
uint32_t mscmem_size(void)
{
/* Get number of 512 byte chunks the MX25 contains. */
return (MX25_SECTOR_SIZE >> LBA_SIZE_SHIFT) * MX25_NUM_SECTORS;
}
/******************************************************************************/
int mscmem_read(uint32_t lba, uint8_t* buffer)
{
uint32_t addr;
/* Convert to MX25 sector number. */
uint32_t sNum = getSectorNum(lba);
if(getSector(sNum)) {
/* Failed to write/read from MX25 */
return 1;
}
/* Get the offset into the current sector */
addr = getSectorAddr(lba);
memcpy(buffer, sector + addr, LBA_SIZE);
return 0;
}
/******************************************************************************/
int mscmem_write(uint32_t lba, uint8_t* buffer)
{
uint32_t addr;
/* Convert to MX25 sector number. */
uint32_t sNum = getSectorNum(lba);
if(getSector(sNum)) {
/* Failed to write/read from MX25 */
return 1;
}
/* Get the offset into the current sector */
addr = getSectorAddr(lba);
memcpy(sector + addr, buffer, LBA_SIZE);
sectorDirty = 1;
return 0;
}
/******************************************************************************/
int mscmem_start()
{
/* Turn on the MX25 if it is not already. */
if(!initialized) {
mscmem_init();
}
/* Check if the initialization succeeded. If it has, start running. */
if(initialized) {
running = 1;
}
/* Start should return fail (non-zero) if the memory cannot be initialized. */
return !initialized;
}
/******************************************************************************/
int mscmem_stop()
{
/* TODO - could shut down XIPF interface here. */
/* Flush the currently cached sector if necessary. */
if(getSector(INVALID_SECTOR)) {
return 1;
}
running = 0;
return 0;
}
/******************************************************************************/
int mscmem_ready()
{
return running;
}
#elif RAM_DISK
#define NUM_PAGES 0x100
static uint8_t mem[NUM_PAGES][LBA_SIZE];
/******************************************************************************/
int mscmem_init()
{
if(!initialized) {
initialized = 1;
#if (ERASE_MEMORY_ON_INIT)
memset(mem, 0, sizeof(mem));
#endif
}
return 0;
}
/******************************************************************************/
uint32_t mscmem_size(void)
{
return NUM_PAGES;
}
/******************************************************************************/
int mscmem_read(uint32_t lba, uint8_t* buffer)
{
if(lba >= NUM_PAGES) {
return 1;
}
memcpy(buffer, mem[lba], LBA_SIZE);
return 0;
}
/******************************************************************************/
int mscmem_write(uint32_t lba, uint8_t* buffer)
{
if(lba >= NUM_PAGES) {
return 1;
}
memcpy(mem[lba], buffer, LBA_SIZE);
return 0;
}
/******************************************************************************/
int mscmem_start()
{
/* Not much to do for this implementation. The RAM is always ready. */
if(!initialized) {
mscmem_init();
}
/* Check if the RAM has been initialized. If it has, start running. */
if(initialized) {
running = 1;
}
/* Start should return fail (non-zero) if the memory cannot be initialized. */
return !initialized;
}
/******************************************************************************/
int mscmem_stop()
{
/* Nothing to do for this implementation. All data is written as it is */
/* received so there are no pending writes that need to be flushed. */
running = 0;
return 0;
}
/******************************************************************************/
int mscmem_ready()
{
return running;
}
#else
#error "You must assign either RAM_DISK or SPIXF_DISK to 1."
#endif
/*******************************************************************************
* Copyright (C) 2017 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.
*
* Description: Communications Device Class ACM (Serial Port) over USB
* $Id: descriptors.h 31172 2017-10-05 19:05:57Z zach.metzinger $
*
*******************************************************************************
*/
/**
* @file mscmem.h
* @brief Memory routines used by the USB Mass Storage Class example.
* See the msc_mem_t structure in msc.h for function details.
*/
#ifndef __MSC_MEM_H__
#define __MSC_MEM_H__
#include <stdint.h>
#define ERASE_MEMORY_ON_INIT 1 /* Configuration option to clear the memory (to 0s) on initialization. */
/* Use 1 to clear or 0 to leave untouched. */
int mscmem_init(void);
int mscmem_start(void);
int mscmem_stop(void);
uint32_t mscmem_size(void);
int mscmem_read(uint32_t lba, uint8_t* buffer);
int mscmem_write(uint32_t lba, uint8_t* buffer);
int mscmem_ready(void);
#endif /* __MSC_MEM_H__ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment