From ed65605edc5c1376947a34723b9c750400b5a028 Mon Sep 17 00:00:00 2001 From: Damien Date: Sun, 13 Oct 2013 00:42:20 +0100 Subject: [PATCH] Inital commit of stm32f4xx framework. --- stm/.gitignore | 1 + stm/Makefile | 130 + stm/delay.s | 28 + stm/fatfs/diskio.c | 272 ++ stm/fatfs/diskio.h | 89 + stm/fatfs/ff.c | 4524 +++++++++++++++++++++++ stm/fatfs/ff.h | 342 ++ stm/fatfs/ffconf.h | 212 ++ stm/fatfs/integer.h | 33 + stm/flash.c | 109 + stm/font_petme128_8x8.h | 98 + stm/lib/core_cm4.h | 1757 +++++++++ stm/lib/core_cm4_simd.h | 649 ++++ stm/lib/core_cmFunc.h | 616 ++++ stm/lib/core_cmInstr.h | 618 ++++ stm/lib/stm32f4xx.h | 7155 ++++++++++++++++++++++++++++++++++++ stm/lib/stm32f4xx_conf.h | 94 + stm/lib/stm32f4xx_dma.c | 1302 +++++++ stm/lib/stm32f4xx_dma.h | 609 +++ stm/lib/stm32f4xx_exti.c | 314 ++ stm/lib/stm32f4xx_exti.h | 183 + stm/lib/stm32f4xx_flash.c | 1177 ++++++ stm/lib/stm32f4xx_flash.h | 390 ++ stm/lib/stm32f4xx_gpio.c | 585 +++ stm/lib/stm32f4xx_gpio.h | 423 +++ stm/lib/stm32f4xx_rcc.c | 1873 ++++++++++ stm/lib/stm32f4xx_rcc.h | 545 +++ stm/lib/stm_misc.c | 250 ++ stm/lib/stm_misc.h | 178 + stm/lib/system_stm32f4xx.h | 105 + stm/lib/usb_bsp.c | 183 + stm/lib/usb_bsp.h | 103 + stm/lib/usb_conf.h | 293 ++ stm/lib/usb_core.c | 2162 +++++++++++ stm/lib/usb_core.h | 417 +++ stm/lib/usb_dcd.c | 478 +++ stm/lib/usb_dcd.h | 164 + stm/lib/usb_dcd_int.c | 869 +++++ stm/lib/usb_dcd_int.h | 127 + stm/lib/usb_defines.h | 249 ++ stm/lib/usb_hcd.c | 262 ++ stm/lib/usb_hcd.h | 108 + stm/lib/usb_hcd_int.c | 858 +++++ stm/lib/usb_hcd_int.h | 141 + stm/lib/usb_otg.c | 418 +++ stm/lib/usb_otg.h | 99 + stm/lib/usb_regs.h | 1188 ++++++ stm/lib/usbd_cdc_conf.h | 105 + stm/lib/usbd_cdc_core.c | 818 +++++ stm/lib/usbd_cdc_core.h | 143 + stm/lib/usbd_cdc_vcp.c | 219 ++ stm/lib/usbd_cdc_vcp.h | 52 + stm/lib/usbd_conf.h | 7 + stm/lib/usbd_core.c | 506 +++ stm/lib/usbd_core.h | 120 + stm/lib/usbd_def.h | 157 + stm/lib/usbd_desc.c | 317 ++ stm/lib/usbd_desc.h | 120 + stm/lib/usbd_ioreq.c | 244 ++ stm/lib/usbd_ioreq.h | 121 + stm/lib/usbd_msc_bot.c | 401 ++ stm/lib/usbd_msc_bot.h | 153 + stm/lib/usbd_msc_conf.h | 99 + stm/lib/usbd_msc_core.c | 497 +++ stm/lib/usbd_msc_core.h | 77 + stm/lib/usbd_msc_data.c | 134 + stm/lib/usbd_msc_data.h | 105 + stm/lib/usbd_msc_mem.h | 113 + stm/lib/usbd_msc_scsi.c | 729 ++++ stm/lib/usbd_msc_scsi.h | 195 + stm/lib/usbd_req.c | 868 +++++ stm/lib/usbd_req.h | 108 + stm/lib/usbd_storage_msd.c | 350 ++ stm/lib/usbd_usr.c | 115 + stm/lib/usbd_usr.h | 141 + stm/main.c | 829 +++++ stm/malloc0.c | 38 + stm/mpyconfig.h | 14 + stm/printf.c | 277 ++ stm/startup_stm32f40xx.s | 515 +++ stm/std.h | 21 + stm/stm32f405.ld | 118 + stm/stm32fxxx_it.c | 255 ++ stm/stm32fxxx_it.h | 60 + stm/string0.c | 95 + stm/system_stm32f4xx.c | 561 +++ stm/usb.c | 20 + 87 files changed, 42597 insertions(+) create mode 100644 stm/.gitignore create mode 100644 stm/Makefile create mode 100644 stm/delay.s create mode 100644 stm/fatfs/diskio.c create mode 100644 stm/fatfs/diskio.h create mode 100644 stm/fatfs/ff.c create mode 100644 stm/fatfs/ff.h create mode 100644 stm/fatfs/ffconf.h create mode 100644 stm/fatfs/integer.h create mode 100644 stm/flash.c create mode 100644 stm/font_petme128_8x8.h create mode 100644 stm/lib/core_cm4.h create mode 100644 stm/lib/core_cm4_simd.h create mode 100644 stm/lib/core_cmFunc.h create mode 100644 stm/lib/core_cmInstr.h create mode 100644 stm/lib/stm32f4xx.h create mode 100644 stm/lib/stm32f4xx_conf.h create mode 100644 stm/lib/stm32f4xx_dma.c create mode 100644 stm/lib/stm32f4xx_dma.h create mode 100644 stm/lib/stm32f4xx_exti.c create mode 100644 stm/lib/stm32f4xx_exti.h create mode 100644 stm/lib/stm32f4xx_flash.c create mode 100644 stm/lib/stm32f4xx_flash.h create mode 100644 stm/lib/stm32f4xx_gpio.c create mode 100644 stm/lib/stm32f4xx_gpio.h create mode 100644 stm/lib/stm32f4xx_rcc.c create mode 100644 stm/lib/stm32f4xx_rcc.h create mode 100644 stm/lib/stm_misc.c create mode 100644 stm/lib/stm_misc.h create mode 100644 stm/lib/system_stm32f4xx.h create mode 100644 stm/lib/usb_bsp.c create mode 100644 stm/lib/usb_bsp.h create mode 100644 stm/lib/usb_conf.h create mode 100644 stm/lib/usb_core.c create mode 100644 stm/lib/usb_core.h create mode 100644 stm/lib/usb_dcd.c create mode 100644 stm/lib/usb_dcd.h create mode 100644 stm/lib/usb_dcd_int.c create mode 100644 stm/lib/usb_dcd_int.h create mode 100644 stm/lib/usb_defines.h create mode 100644 stm/lib/usb_hcd.c create mode 100644 stm/lib/usb_hcd.h create mode 100644 stm/lib/usb_hcd_int.c create mode 100644 stm/lib/usb_hcd_int.h create mode 100644 stm/lib/usb_otg.c create mode 100644 stm/lib/usb_otg.h create mode 100644 stm/lib/usb_regs.h create mode 100644 stm/lib/usbd_cdc_conf.h create mode 100644 stm/lib/usbd_cdc_core.c create mode 100644 stm/lib/usbd_cdc_core.h create mode 100644 stm/lib/usbd_cdc_vcp.c create mode 100644 stm/lib/usbd_cdc_vcp.h create mode 100644 stm/lib/usbd_conf.h create mode 100644 stm/lib/usbd_core.c create mode 100644 stm/lib/usbd_core.h create mode 100644 stm/lib/usbd_def.h create mode 100644 stm/lib/usbd_desc.c create mode 100644 stm/lib/usbd_desc.h create mode 100644 stm/lib/usbd_ioreq.c create mode 100644 stm/lib/usbd_ioreq.h create mode 100644 stm/lib/usbd_msc_bot.c create mode 100644 stm/lib/usbd_msc_bot.h create mode 100644 stm/lib/usbd_msc_conf.h create mode 100644 stm/lib/usbd_msc_core.c create mode 100644 stm/lib/usbd_msc_core.h create mode 100644 stm/lib/usbd_msc_data.c create mode 100644 stm/lib/usbd_msc_data.h create mode 100644 stm/lib/usbd_msc_mem.h create mode 100644 stm/lib/usbd_msc_scsi.c create mode 100644 stm/lib/usbd_msc_scsi.h create mode 100644 stm/lib/usbd_req.c create mode 100644 stm/lib/usbd_req.h create mode 100644 stm/lib/usbd_storage_msd.c create mode 100644 stm/lib/usbd_usr.c create mode 100644 stm/lib/usbd_usr.h create mode 100644 stm/main.c create mode 100644 stm/malloc0.c create mode 100644 stm/mpyconfig.h create mode 100644 stm/printf.c create mode 100644 stm/startup_stm32f40xx.s create mode 100644 stm/std.h create mode 100644 stm/stm32f405.ld create mode 100644 stm/stm32fxxx_it.c create mode 100644 stm/stm32fxxx_it.h create mode 100644 stm/string0.c create mode 100644 stm/system_stm32f4xx.c create mode 100644 stm/usb.c diff --git a/stm/.gitignore b/stm/.gitignore new file mode 100644 index 000000000..378eac25d --- /dev/null +++ b/stm/.gitignore @@ -0,0 +1 @@ +build diff --git a/stm/Makefile b/stm/Makefile new file mode 100644 index 000000000..faa0b8869 --- /dev/null +++ b/stm/Makefile @@ -0,0 +1,130 @@ +STMSRC=lib +FATFSSRC=fatfs +PYSRC=../py +BUILD=build + +AS = arm-none-eabi-as +CC = arm-none-eabi-gcc +LD = arm-none-eabi-ld +CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfloat-abi=hard -DSTM32F40XX -DHSE_VALUE=8000000 +CFLAGS = -I. -I$(PYSRC) -I$(FATFSSRC) -I$(STMSRC) -Wall -ansi -std=gnu99 -Os -DNDEBUG $(CFLAGS_CORTEX_M4) +CFLAGS_PY = -DEMIT_ENABLE_THUMB +LDFLAGS = --nostdlib -T stm.ld + +SRC_C = \ + main.c \ + printf.c \ + system_stm32f4xx.c \ + flash.c \ + string0.c \ + malloc0.c \ + stm32fxxx_it.c \ + usb.c \ +# sd.c \ + +SRC_S = \ + delay.s \ + startup_stm32f40xx.s \ + +PY_O = \ +# malloc.o \ + qstr.o \ + misc.o \ + lexer.o \ + parse.o \ + scope.o \ + compile.o \ + emitcommon.o \ + emitpass1.o \ + emitbc.o \ + asmthumb.o \ + emitnthumb.o \ + emitinlinethumb.o \ + runtime.o \ + vm.o \ + +SRC_FATFS = \ + ff.c \ + diskio.c \ + +SRC_STM = \ + stm32f4xx_rcc.c \ + stm32f4xx_flash.c \ + stm32f4xx_dma.c \ + stm32f4xx_exti.c \ + stm32f4xx_gpio.c \ + stm_misc.c \ + usb_core.c \ + usb_dcd.c \ + usb_dcd_int.c \ + usb_bsp.c \ + usbd_core.c \ + usbd_ioreq.c \ + usbd_req.c \ + usbd_usr.c \ + usbd_desc.c \ + usbd_cdc_core.c \ + usbd_cdc_vcp.c \ + usbd_msc_bot.c \ + usbd_msc_core.c \ + usbd_msc_data.c \ + usbd_msc_scsi.c \ + usbd_storage_msd.c \ + +# not needed +# usb_otg.c \ +# usb_hcd.c \ +# usb_hcd_int.c \ + +# for SD card +# stm32f4xx_sdio.c \ +# stm324x7i_eval.c \ +# stm324x7i_eval_sdio_sd.c \ + +OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o) $(PY_O) $(SRC_FATFS:.c=.o) $(SRC_STM:.c=.o)) + +all: $(BUILD) $(BUILD)/flash.dfu + +$(BUILD)/flash.dfu: $(BUILD)/flash.bin + python2 ~/stm/dfu/dfu.py -b 0x08000000:$< $@ + +$(BUILD)/flash.bin: $(BUILD)/flash.elf + arm-none-eabi-objcopy -O binary -j .isr_vector -j .text -j .data $^ $@ + +$(BUILD)/flash.elf: $(OBJ) + $(LD) $(LDFLAGS) -o $@ $(OBJ) + arm-none-eabi-size $@ + +$(BUILD): + mkdir $@ + +$(BUILD)/%.o: %.s + $(AS) -o $@ $< + +$(BUILD)/%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD)/%.o: $(FATFSSRC)/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD)/%.o: $(STMSRC)/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD)/%.o: $(PYSRC)/%.c mpyconfig.h + $(CC) $(CFLAGS) $(CFLAGS_PY) -c -o $@ $< + +$(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h + $(CC) $(CFLAGS) $(CFLAGS_PY) -DN_THUMB -c -o $@ $< + +# optimising vm for speed, adds only a small amount to code size but makes a huge difference to speed (20% faster) +$(BUILD)/vm.o: $(PYSRC)/vm.c + $(CC) $(CFLAGS) $(CFLAGS_PY) -O3 -c -o $@ $< + +$(BUILD)/parse.o: $(PYSRC)/grammar.h +$(BUILD)/compile.o: $(PYSRC)/grammar.h +$(BUILD)/emitbc.o: $(PYSRC)/emit.h + +clean: + /bin/rm -r $(BUILD) + +.PHONY: all clean diff --git a/stm/delay.s b/stm/delay.s new file mode 100644 index 000000000..741dfd894 --- /dev/null +++ b/stm/delay.s @@ -0,0 +1,28 @@ + .syntax unified + .cpu cortex-m4 + .thumb + .text + .align 2 + .global delay_ms + .thumb + .thumb_func + .type delay_ms, %function +@ void delay_ms(int ms) +delay_ms: + @ r0 is argument, trashes r2, r3 + adds r3, r0, #0 + b .L2 +.L5: + movw r2, #55999 + b .L3 +.L4: + subs r2, r2, #1 +.L3: + cmp r2, #0 + bgt .L4 + subs r3, r3, #1 +.L2: + cmp r3, #0 + bgt .L5 + bx lr + .size delay_ms, .-delay_ms diff --git a/stm/fatfs/diskio.c b/stm/fatfs/diskio.c new file mode 100644 index 000000000..3ec986926 --- /dev/null +++ b/stm/fatfs/diskio.c @@ -0,0 +1,272 @@ +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2013 */ +/*-----------------------------------------------------------------------*/ +/* If a working storage control module is available, it should be */ +/* attached to the FatFs via a glue function rather than modifying it. */ +/* This is an example of glue functions to attach various exsisting */ +/* storage control module to the FatFs module with a defined API. */ +/*-----------------------------------------------------------------------*/ + +#include +#include +#include "ff.h" /* FatFs lower layer API */ +#include "diskio.h" /* FatFs lower layer API */ + +PARTITION VolToPart[] = { + {0, 1}, // Logical drive 0 ==> Physical drive 0, 1st partition + /* + {0, 2}, // Logical drive 1 ==> Physical drive 0, 2nd partition + {0, 3}, // Logical drive 2 ==> Physical drive 0, 3rd partition + {1, 0}, // Logical drive 3 ==> Physical drive 1 (auto detection) + */ +}; + +#define PD_FLASH_SECTOR_SIZE (512) +#define PD_FLASH_PART1_START_SECTOR (0x100) +#define PD_FLASH_PART1_NUM_SECTORS (128) // 64k +#define PD_FLASH_MEM_START_ADDR (0x08020000) // 128k above start, first 128k block + +#define PD_FLASH_RAM_BUF (0x10000000) // CCM data RAM, 64k + +static void pd_flash_init() { + printf("IN\n"); + // fill RAM buffer + uint32_t *src = (uint32_t*)PD_FLASH_MEM_START_ADDR; + uint32_t *dest = (uint32_t*)PD_FLASH_RAM_BUF; + for (int i = 0; i < PD_FLASH_PART1_NUM_SECTORS * PD_FLASH_SECTOR_SIZE / 4; i++) { + *dest++ = *src++; + } +} + +extern void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32); + +static void pd_flash_flush() { + printf("FL\n"); + // sync the RAM buffer by writing it to the flash page + flash_write(PD_FLASH_MEM_START_ADDR, (const uint32_t*)PD_FLASH_RAM_BUF, PD_FLASH_PART1_NUM_SECTORS * PD_FLASH_SECTOR_SIZE / 4); +} + +static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_sector, uint32_t num_sectors) { + buf[0] = boot; + + if (num_sectors == 0) { + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + } else { + buf[1] = 0xff; + buf[2] = 0xff; + buf[3] = 0xff; + } + + buf[4] = type; + + if (num_sectors == 0) { + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + } else { + buf[5] = 0xff; + buf[6] = 0xff; + buf[7] = 0xff; + } + + buf[8] = start_sector; + buf[9] = start_sector >> 8; + buf[10] = start_sector >> 16; + buf[11] = start_sector >> 24; + + buf[12] = num_sectors; + buf[13] = num_sectors >> 8; + buf[14] = num_sectors >> 16; + buf[15] = num_sectors >> 24; +} + +static DRESULT pd_flash_read_sector(uint8_t *dest, uint32_t sector) { + //printf("RD %u\n", sector); + if (sector == 0) { + // fake the MBR so we can decide on our own partition table + + for (int i = 0; i < 446; i++) { + dest[i] = 0; + } + + build_partition(dest + 446, 0, 0x01 /* FAT12 */, PD_FLASH_PART1_START_SECTOR, PD_FLASH_PART1_NUM_SECTORS); + build_partition(dest + 462, 0, 0, 0, 0); + build_partition(dest + 478, 0, 0, 0, 0); + build_partition(dest + 494, 0, 0, 0, 0); + + dest[510] = 0x55; + dest[511] = 0xaa; + + return RES_OK; + + } else if (PD_FLASH_PART1_START_SECTOR <= sector && sector < PD_FLASH_PART1_START_SECTOR + PD_FLASH_PART1_NUM_SECTORS) { + // non-MBR sector(s), just copy straight from flash + uint8_t *src = (uint8_t*)PD_FLASH_RAM_BUF + (sector - PD_FLASH_PART1_START_SECTOR) * PD_FLASH_SECTOR_SIZE; + for (int i = PD_FLASH_SECTOR_SIZE; i > 0; i--) { + *dest++ = *src++; + } + return RES_OK; + + } else { + // bad sector number + return RES_ERROR; + } +} + +static DRESULT pd_flash_write_sector(const uint8_t *src, uint32_t sector) { + printf("WR %u\n", sector); + if (sector == 0) { + // can't write MBR, but pretend we did + + return RES_OK; + + } else if (PD_FLASH_PART1_START_SECTOR <= sector && sector < PD_FLASH_PART1_START_SECTOR + PD_FLASH_PART1_NUM_SECTORS) { + // non-MBR sector(s), copy to RAM buffer + uint8_t *dest = (uint8_t*)PD_FLASH_RAM_BUF + (sector - PD_FLASH_PART1_START_SECTOR) * PD_FLASH_SECTOR_SIZE; + for (int i = PD_FLASH_SECTOR_SIZE; i > 0; i--) { + *dest++ = *src++; + } + return RES_OK; + + } else { + // bad sector number + return RES_ERROR; + } +} + +/* Definitions of physical drive number for each media */ +#define PD_FLASH (0) +#define PD_SD (1) + +/*-----------------------------------------------------------------------*/ +/* Initialize a Drive */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_initialize ( + BYTE pdrv /* Physical drive nmuber (0..) */ +) +{ + switch (pdrv) { + case PD_FLASH : + pd_flash_init(); + return 0; + } + + return STA_NOINIT; +} + +/*-----------------------------------------------------------------------*/ +/* Get Disk Status */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_status ( + BYTE pdrv /* Physical drive nmuber (0..) */ +) +{ + switch (pdrv) { + case PD_FLASH : + // flash is ready + return 0; + + case PD_SD: + return STA_NOINIT; + } + + return STA_NOINIT; +} + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Sector address (LBA) */ + UINT count /* Number of sectors to read (1..128) */ +) +{ + DRESULT res; + switch (pdrv) { + case PD_FLASH: + for (int i = 0; i < count; i++) { + if ((res = pd_flash_read_sector(buff + i * PD_FLASH_SECTOR_SIZE, sector + i)) != RES_OK) { + return res; + } + } + return RES_OK; + } + + return RES_PARERR; +} + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ + +#if _USE_WRITE +DRESULT disk_write ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Sector address (LBA) */ + UINT count /* Number of sectors to write (1..128) */ +) +{ + DRESULT res; + switch (pdrv) { + case PD_FLASH: + for (int i = 0; i < count; i++) { + if ((res = pd_flash_write_sector(buff + i * PD_FLASH_SECTOR_SIZE, sector + i)) != RES_OK) { + return res; + } + } + return RES_OK; + } + + return RES_PARERR; +} +#endif + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ + +#if _USE_IOCTL +DRESULT disk_ioctl ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE cmd, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + switch (pdrv) { + case PD_FLASH: + switch (cmd) { + case CTRL_SYNC: + pd_flash_flush(); + return RES_OK; + + case GET_BLOCK_SIZE: + *((DWORD*)buff) = 1; // block erase size in units of the sector size + return RES_OK; + } + } + + return RES_PARERR; +} +#endif + +DWORD get_fattime ( + void +) +{ + int year = 2013; + int month = 10; + int day = 12; + int hour = 21; + int minute = 42; + int second = 13; + return ((year - 1980) << 25) | ((month) << 21) | ((day) << 16) | ((hour) << 11) | ((minute) << 5) | (second / 2); +} diff --git a/stm/fatfs/diskio.h b/stm/fatfs/diskio.h new file mode 100644 index 000000000..966bc89b1 --- /dev/null +++ b/stm/fatfs/diskio.h @@ -0,0 +1,89 @@ +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file (C)ChaN, 2013 +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#define _USE_WRITE 1 /* 1: Enable disk_write function */ +#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ + +#include "integer.h" + + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + + +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, UINT count); +DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); + +DWORD get_fattime (void); + +/* Disk Status Bits (DSTATUS) */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (used by FatFs) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ + +/* Generic command (not used by FatFs) */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_FORMAT 8 /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + + +/* MMC card type flags (MMC_GET_TYPE) */ +#define CT_MMC 0x01 /* MMC ver 3 */ +#define CT_SD1 0x02 /* SD ver 1 */ +#define CT_SD2 0x04 /* SD ver 2 */ +#define CT_SDC (CT_SD1|CT_SD2) /* SD */ +#define CT_BLOCK 0x08 /* Block addressing */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stm/fatfs/ff.c b/stm/fatfs/ff.c new file mode 100644 index 000000000..5c03644e7 --- /dev/null +++ b/stm/fatfs/ff.c @@ -0,0 +1,4524 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - FAT file system module R0.10 (C)ChaN, 2013 +/-----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2013, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------/ +/ Feb 26,'06 R0.00 Prototype. +/ +/ Apr 29,'06 R0.01 First stable version. +/ +/ Jun 01,'06 R0.02 Added FAT12 support. +/ Removed unbuffered mode. +/ Fixed a problem on small (<32M) partition. +/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). +/ +/ Sep 22,'06 R0.03 Added f_rename(). +/ Changed option _FS_MINIMUM to _FS_MINIMIZE. +/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast. +/ Fixed f_mkdir() creates incorrect directory on FAT32. +/ +/ Feb 04,'07 R0.04 Supported multiple drive system. +/ Changed some interfaces for multiple drive system. +/ Changed f_mountdrv() to f_mount(). +/ Added f_mkfs(). +/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. +/ Added a capability of extending file size to f_lseek(). +/ Added minimization level 3. +/ Fixed an endian sensitive code in f_mkfs(). +/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG. +/ Added FSINFO support. +/ Fixed DBCS name can result FR_INVALID_NAME. +/ Fixed short seek (<= csize) collapses the file object. +/ +/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs(). +/ Fixed f_mkfs() on FAT32 creates incorrect FSINFO. +/ Fixed f_mkdir() on FAT32 creates incorrect directory. +/ Feb 03,'08 R0.05a Added f_truncate() and f_utime(). +/ Fixed off by one error at FAT sub-type determination. +/ Fixed btr in f_read() can be mistruncated. +/ Fixed cached sector is not flushed when create and close without write. +/ +/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets(). +/ Improved performance of f_lseek() on moving to the same or following cluster. +/ +/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) +/ Added long file name feature. +/ Added multiple code page feature. +/ Added re-entrancy for multitask operation. +/ Added auto cluster size selection to f_mkfs(). +/ Added rewind option to f_readdir(). +/ Changed result code of critical errors. +/ Renamed string functions to avoid name collision. +/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. +/ Added multiple sector size feature. +/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error. +/ Fixed wrong cache control in f_lseek(). +/ Added relative path feature. +/ Added f_chdir() and f_chdrive(). +/ Added proper case conversion to extended character. +/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h. +/ Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH. +/ Fixed name matching error on the 13 character boundary. +/ Added a configuration option, _LFN_UNICODE. +/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. +/ +/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) +/ Added file lock feature. (_FS_SHARE) +/ Added fast seek feature. (_USE_FASTSEEK) +/ Changed some types on the API, XCHAR->TCHAR. +/ Changed .fname in the FILINFO structure on Unicode cfg. +/ String functions support UTF-8 encoding files on Unicode cfg. +/ Aug 16,'10 R0.08a Added f_getcwd(). +/ Added sector erase feature. (_USE_ERASE) +/ Moved file lock semaphore table from fs object to the bss. +/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. +/ Fixed f_mkfs() creates wrong FAT32 volume. +/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). +/ f_lseek() reports required table size on creating CLMP. +/ Extended format syntax of f_printf(). +/ Ignores duplicated directory separators in given path name. +/ +/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to complete the multiple partition feature. +/ Added f_fdisk(). +/ Aug 27,'12 R0.09a Changed f_open() and f_opendir() reject null object pointer to avoid crash. +/ Changed option name _FS_SHARE to _FS_LOCK. +/ Fixed assertion failure due to OS/2 EA on FAT12/16 volume. +/ Jan 24,'13 R0.09b Added f_setlabel() and f_getlabel(). +/ +/ Oct 02,'13 R0.10 Added selection of character encoding on the file. (_STRF_ENCODE) +/ Added f_closedir(). +/ Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO) +/ Added forced mount feature with changes of f_mount(). +/ Improved behavior of volume auto detection. +/ Improved write throughput of f_puts() and f_printf(). +/ Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). +/ Fixed f_write() can be truncated when the file size is close to 4GB. +/ Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code. +/---------------------------------------------------------------------------*/ + +#include "ff.h" /* Declarations of FatFs API */ +#include "diskio.h" /* Declarations of disk I/O functions */ + + +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if _FATFS != 80960 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* Definitions on sector size */ +#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096 +#error Wrong sector size. +#endif +#if _MAX_SS != 512 +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#else +#define SS(fs) 512U /* Fixed sector size */ +#endif + + +/* Reentrancy related */ +#if _FS_REENTRANT +#if _USE_LFN == 1 +#error Static LFN work area cannot be used at thread-safe configuration. +#endif +#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res +#endif + +#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } + + +/* File access control feature */ +#if _FS_LOCK +#if _FS_READONLY +#error _FS_LOCK must be 0 at read-only cfg. +#endif +typedef struct { + FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ + DWORD clu; /* Object ID 2, directory */ + WORD idx; /* Object ID 3, directory index */ + WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ +} FILESEM; +#endif + + + +/* DBCS code ranges and SBCS extend character conversion table */ + +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ + +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE + +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} + +#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1253 /* Greek (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + +#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#if _USE_LFN +#error Cannot use LFN feature without valid code page. +#endif +#define _DF1S 0 + +#else +#error Unknown code page + +#endif + + +/* Character code support macros */ +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) + +#if _DF1S /* Code page is DBCS */ + +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) +#endif + +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#endif + +#else /* Code page is SBCS */ + +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 + +#endif /* _DF1S */ + + +/* Name status flags */ +#define NS 11 /* Index of name status byte in fn[] */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ + + +/* FAT sub-type boundaries */ +#define MIN_FAT16 4086U /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526U /* Minimum number of clusters for FAT32 */ + + +/* FatFs refers the members in the FAT structures as byte array instead of +/ structure member because the structure is not binary compatible between +/ different platforms */ + +#define BS_jmpBoot 0 /* Jump instruction (3) */ +#define BS_OEMName 3 /* OEM name (8) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ +#define BPB_NumFATs 16 /* Number of FAT copies (1) */ +#define BPB_RootEntCnt 17 /* Number of root directory entries for FAT12/16 (2) */ +#define BPB_TotSec16 19 /* Volume size [sector] (2) */ +#define BPB_Media 21 /* Media descriptor (1) */ +#define BPB_FATSz16 22 /* FAT size [sector] (2) */ +#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ +#define BPB_NumHeads 26 /* Number of heads (2) */ +#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ +#define BPB_TotSec32 32 /* Volume size [sector] (4) */ +#define BS_DrvNum 36 /* Physical drive number (2) */ +#define BS_BootSig 38 /* Extended boot signature (1) */ +#define BS_VolID 39 /* Volume serial number (4) */ +#define BS_VolLab 43 /* Volume label (8) */ +#define BS_FilSysType 54 /* File system type (1) */ +#define BPB_FATSz32 36 /* FAT size [sector] (4) */ +#define BPB_ExtFlags 40 /* Extended flags (2) */ +#define BPB_FSVer 42 /* File system version (2) */ +#define BPB_RootClus 44 /* Root directory first cluster (4) */ +#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */ +#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */ +#define BS_DrvNum32 64 /* Physical drive number (2) */ +#define BS_BootSig32 66 /* Extended boot signature (1) */ +#define BS_VolID32 67 /* Volume serial number (4) */ +#define BS_VolLab32 71 /* Volume label (8) */ +#define BS_FilSysType32 82 /* File system type (1) */ +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ +#define MBR_Table 446 /* MBR: Partition table offset (2) */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define BS_55AA 510 /* Boot sector signature (2) */ + +#define DIR_Name 0 /* Short file name (11) */ +#define DIR_Attr 11 /* Attribute (1) */ +#define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ +#define DIR_CrtTime 14 /* Created time (2) */ +#define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_LstAccDate 18 /* Last accessed date (2) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ +#define DIR_WrtTime 22 /* Modified time (2) */ +#define DIR_WrtDate 24 /* Modified date (2) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ +#define DIR_FileSize 28 /* File size (4) */ +#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ +#define LDIR_Attr 11 /* LFN attribute (1) */ +#define LDIR_Type 12 /* LFN type (1) */ +#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ +#define LDIR_FstClusLO 26 /* Filled by zero (0) */ +#define SZ_DIR 32 /* Size of a directory entry */ +#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ +#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */ +#define NDDE 0x05 /* Replacement of the character collides with DDE */ + + +/*------------------------------------------------------------*/ +/* Module private work area */ +/*------------------------------------------------------------*/ +/* Note that uninitialized variables with static duration are +/ zeroed/nulled at start-up. If not, the compiler or start-up +/ routine is out of ANSI-C standard. +*/ + +#if _VOLUMES +static +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +#else +#error Number of volumes must not be 0. +#endif + +static +WORD Fsid; /* File system mount ID */ + +#if _FS_RPATH && _VOLUMES >= 2 +static +BYTE CurrVol; /* Current drive */ +#endif + +#if _FS_LOCK +static +FILESEM Files[_FS_LOCK]; /* Open object lock semaphores */ +#endif + +#if _USE_LFN == 0 /* No LFN feature */ +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) (dobj).fn = sfn +#define FREE_BUF() + +#elif _USE_LFN == 1 /* LFN feature with static working buffer */ +static +WCHAR LfnBuf[_MAX_LFN+1]; +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() + +#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } +#define FREE_BUF() + +#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn +#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ + if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ + (dobj).lfn = lfn; (dobj).fn = sfn; } +#define FREE_BUF() ff_memfree(lfn) + +#else +#error Wrong LFN configuration. +#endif + + +#ifdef _EXCVT +static +const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for extended characters */ +#endif + + + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +static +void mem_cpy (void* dst, const void* src, UINT cnt) { + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + +#if _WORD_ACCESS == 1 + while (cnt >= sizeof (int)) { + *(int*)d = *(int*)s; + d += sizeof (int); s += sizeof (int); + cnt -= sizeof (int); + } +#endif + while (cnt--) + *d++ = *s++; +} + +/* Fill memory */ +static +void mem_set (void* dst, int val, UINT cnt) { + BYTE *d = (BYTE*)dst; + + while (cnt--) + *d++ = (BYTE)val; +} + +/* Compare memory to memory */ +static +int mem_cmp (const void* dst, const void* src, UINT cnt) { + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; + int r = 0; + + while (cnt-- && (r = *d++ - *s++) == 0) ; + return r; +} + +/* Check if chr is contained in the string */ +static +int chk_chr (const char* str, int chr) { + while (*str && *str != chr) str++; + return *str; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +#if _FS_REENTRANT +static +int lock_fs ( + FATFS* fs /* File system object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static +void unlock_fs ( + FATFS* fs, /* File system object */ + FRESULT res /* Result code to be returned */ +) +{ + if (fs && + res != FR_NOT_ENABLED && + res != FR_INVALID_DRIVE && + res != FR_INVALID_OBJECT && + res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* File lock control functions */ +/*-----------------------------------------------------------------------*/ +#if _FS_LOCK + +static +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR* dp, /* Directory object pointing the file to be checked */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i, be; + + /* Search file semaphore table */ + for (i = be = 0; i < _FS_LOCK; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dp->fs && /* Check if the object matched with an open object */ + Files[i].clu == dp->sclust && + Files[i].idx == dp->index) break; + } else { /* Blank entry */ + be = 1; + } + } + if (i == _FS_LOCK) /* The object is not opened */ + return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new object? */ + + /* The object has been opened. Reject any open against writing file and all write mode open */ + return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static +int enq_lock (void) /* Check if an entry is available for a new object */ +{ + UINT i; + + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + return (i == _FS_LOCK) ? 0 : 1; +} + + +static +UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ + DIR* dp, /* Directory object pointing the file to register or increment */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i; + + + for (i = 0; i < _FS_LOCK; i++) { /* Find the object */ + if (Files[i].fs == dp->fs && + Files[i].clu == dp->sclust && + Files[i].idx == dp->index) break; + } + + if (i == _FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + if (i == _FS_LOCK) return 0; /* No free entry to register (int err) */ + Files[i].fs = dp->fs; + Files[i].clu = dp->sclust; + Files[i].idx = dp->index; + Files[i].ctr = 0; + } + + if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; +} + + +static +FRESULT dec_lock ( /* Decrement object open counter */ + UINT i /* Semaphore index (1..) */ +) +{ + WORD n; + FRESULT res; + + + if (--i < _FS_LOCK) { /* Shift index number origin from 0 */ + n = Files[i].ctr; + if (n == 0x100) n = 0; /* If write mode open, delete the entry */ + if (n) n--; /* Decrement read mode open count */ + Files[i].ctr = n; + if (!n) Files[i].fs = 0; /* Delete the entry if open count gets zero */ + res = FR_OK; + } else { + res = FR_INT_ERR; /* Invalid index nunber */ + } + return res; +} + + +static +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < _FS_LOCK; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Move/Flush disk access window in the file system object */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT sync_window ( + FATFS* fs /* File system object */ +) +{ + DWORD wsect; + UINT nf; + + + if (fs->wflag) { /* Write back the sector if it is dirty */ + wsect = fs->winsect; /* Current sector number */ + if (disk_write(fs->drv, fs->win, wsect, 1)) + return FR_DISK_ERR; + fs->wflag = 0; + if (wsect - fs->fatbase < fs->fsize) { /* Is it in the FAT area? */ + for (nf = fs->n_fats; nf >= 2; nf--) { /* Reflect the change to all FAT copies */ + wsect += fs->fsize; + disk_write(fs->drv, fs->win, wsect, 1); + } + } + } + return FR_OK; +} +#endif + + +static +FRESULT move_window ( + FATFS* fs, /* File system object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) +{ + if (sector != fs->winsect) { /* Changed current window */ +#if !_FS_READONLY + if (sync_window(fs) != FR_OK) + return FR_DISK_ERR; +#endif + if (disk_read(fs->drv, fs->win, sector, 1)) + return FR_DISK_ERR; + fs->winsect = sector; + } + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize file system and strage device */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */ + FATFS* fs /* File system object */ +) +{ + FRESULT res; + + + res = sync_window(fs); + if (res == FR_OK) { + /* Update FSINFO sector if needed */ + if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { + /* Create FSINFO structure */ + mem_set(fs->win, 0, SS(fs)); + ST_WORD(fs->win+BS_55AA, 0xAA55); + ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); + ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); + ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); + ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); + /* Write it into the FSINFO sector */ + fs->winsect = fs->volbase + 1; + disk_write(fs->drv, fs->win, fs->winsect, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the physical drive */ + if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) + res = FR_DISK_ERR; + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Get sector# from cluster# */ +/*-----------------------------------------------------------------------*/ + + +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ + FATFS* fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; + if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ + return clst * fs->csize + fs->database; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + + +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ + FATFS* fs, /* File system object */ + DWORD clst /* Cluster# to get the link information */ +) +{ + UINT wc, bc; + BYTE *p; + + + if (clst < 2 || clst >= fs->n_fatent) /* Check range */ + return 1; + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc = fs->win[bc % SS(fs)]; bc++; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc |= fs->win[bc % SS(fs)] << 8; + return clst & 1 ? wc >> 4 : (wc & 0xFFF); + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; + p = &fs->win[clst * 2 % SS(fs)]; + return LD_WORD(p); + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; + p = &fs->win[clst * 4 % SS(fs)]; + return LD_DWORD(p) & 0x0FFFFFFF; + } + + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY + +FRESULT put_fat ( + FATFS* fs, /* File system object */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ + DWORD val /* New value to mark the cluster */ +) +{ + UINT bc; + BYTE *p; + FRESULT res; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; + bc++; + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); + break; + + case FS_FAT16 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + p = &fs->win[clst * 2 % SS(fs)]; + ST_WORD(p, (WORD)val); + break; + + case FS_FAT32 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + p = &fs->win[clst * 4 % SS(fs)]; + val |= LD_DWORD(p) & 0xF0000000; + ST_DWORD(p, val); + break; + + default : + res = FR_INT_ERR; + } + fs->wflag = 1; + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT remove_chain ( + FATFS* fs, /* File system object */ + DWORD clst /* Cluster# to remove a chain from */ +) +{ + FRESULT res; + DWORD nxt; +#if _USE_ERASE + DWORD scl = clst, ecl = clst, rt[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + res = FR_OK; + while (clst < fs->n_fatent) { /* Not a last link? */ + nxt = get_fat(fs, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ + if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ + res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ + if (res != FR_OK) break; + if (fs->free_clust != 0xFFFFFFFF) { /* Update FSINFO */ + fs->free_clust++; + fs->fsi_flag |= 1; + } +#if _USE_ERASE + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ + ecl = nxt; + } else { /* End of contiguous clusters */ + rt[0] = clust2sect(fs, scl); /* Start sector */ + rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */ + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch or Create a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FATFS* fs, /* File system object */ + DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clust; /* Get suggested start point */ + if (!scl || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch the current chain */ + cs = get_fat(fs, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* It is an invalid cluster */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; + } + + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Wrap around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster */ + } + cs = get_fat(fs, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster */ + if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ + return cs; + if (ncl == scl) return 0; /* No free cluster */ + } + + res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ + } + if (res == FR_OK) { + fs->last_clust = ncl; /* Update FSINFO */ + if (fs->free_clust != 0xFFFFFFFF) { + fs->free_clust--; + fs->fsi_flag |= 1; + } + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; + } + + return ncl; /* Return new cluster number or error code */ +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +#if _USE_FASTSEEK +static +DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + DWORD ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (!ncl) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} +#endif /* _USE_FASTSEEK */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_sdi ( + DIR* dp, /* Pointer to directory object */ + WORD idx /* Index of directory table */ +) +{ + DWORD clst; + WORD ic; + + + dp->index = idx; + clst = dp->sclust; + if (clst == 1 || clst >= dp->fs->n_fatent) /* Check start cluster range */ + return FR_INT_ERR; + if (!clst && dp->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ + clst = dp->fs->dirbase; + + if (clst == 0) { /* Static table (root-directory in FAT12/16) */ + dp->clust = clst; + if (idx >= dp->fs->n_rootdir) /* Index is out of range */ + return FR_INT_ERR; + dp->sect = dp->fs->dirbase + idx / (SS(dp->fs) / SZ_DIR); /* Sector# */ + } + else { /* Dynamic table (sub-dirs or root-directory in FAT32) */ + ic = SS(dp->fs) / SZ_DIR * dp->fs->csize; /* Entries per cluster */ + while (idx >= ic) { /* Follow cluster chain */ + clst = get_fat(dp->fs, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= dp->fs->n_fatent) /* Reached to end of table or int error */ + return FR_INT_ERR; + idx -= ic; + } + dp->clust = clst; + dp->sect = clust2sect(dp->fs, clst) + idx / (SS(dp->fs) / SZ_DIR); /* Sector# */ + } + + dp->dir = dp->fs->win + (idx % (SS(dp->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */ + + return FR_OK; /* Seek succeeded */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory table index next */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD clst; + WORD i; + + + i = dp->index + 1; + if (!i || !dp->sect) /* Report EOT when index has reached 65535 */ + return FR_NO_FILE; + + if (!(i % (SS(dp->fs) / SZ_DIR))) { /* Sector changed? */ + dp->sect++; /* Next sector */ + + if (!dp->clust) { /* Static table */ + if (i >= dp->fs->n_rootdir) /* Report EOT if it reached end of static table */ + return FR_NO_FILE; + } + else { /* Dynamic table */ + if (((i / (SS(dp->fs) / SZ_DIR)) & (dp->fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(dp->fs, dp->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + if (clst >= dp->fs->n_fatent) { /* If it reached end of dynamic table, */ +#if !_FS_READONLY + BYTE c; + if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT */ + clst = create_chain(dp->fs, dp->clust); /* Stretch cluster chain */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + /* Clean-up stretched table */ + if (sync_window(dp->fs)) return FR_DISK_ERR;/* Flush disk access window */ + mem_set(dp->fs->win, 0, SS(dp->fs)); /* Clear window buffer */ + dp->fs->winsect = clust2sect(dp->fs, clst); /* Cluster start sector */ + for (c = 0; c < dp->fs->csize; c++) { /* Fill the new cluster with 0 */ + dp->fs->wflag = 1; + if (sync_window(dp->fs)) return FR_DISK_ERR; + dp->fs->winsect++; + } + dp->fs->winsect -= c; /* Rewind window offset */ +#else + if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT */ + return FR_NO_FILE; /* Report EOT */ +#endif + } + dp->clust = clst; /* Initialize data for new cluster */ + dp->sect = clust2sect(dp->fs, clst); + } + } + } + + dp->index = i; /* Current index */ + dp->dir = dp->fs->win + (i % (SS(dp->fs) / SZ_DIR)) * SZ_DIR; /* Current entry in the window */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Reserve directory entry */ +/*-----------------------------------------------------------------------*/ + +#if !_FS_READONLY +static +FRESULT dir_alloc ( + DIR* dp, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate (1-21) */ +) +{ + FRESULT res; + UINT n; + + + res = dir_sdi(dp, 0); + if (res == FR_OK) { + n = 0; + do { + res = move_window(dp->fs, dp->sect); + if (res != FR_OK) break; + if (dp->dir[0] == DDE || dp->dir[0] == 0) { /* Is it a blank entry? */ + if (++n == nent) break; /* A block of contiguous entries is found */ + } else { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dp, 1); /* Next entry with table stretch enabled */ + } while (res == FR_OK); + } + if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static +DWORD ld_clust ( + FATFS* fs, /* Pointer to the fs object */ + BYTE* dir /* Pointer to the directory entry */ +) +{ + DWORD cl; + + cl = LD_WORD(dir+DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) + cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16; + + return cl; +} + + +#if !_FS_READONLY +static +void st_clust ( + BYTE* dir, /* Pointer to the directory entry */ + DWORD cl /* Value to be set */ +) +{ + ST_WORD(dir+DIR_FstClusLO, cl); + ST_WORD(dir+DIR_FstClusHI, cl >> 16); +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN characters in the directory entry */ + + +static +int cmp_lfn ( /* 1:Matched, 0:Not matched */ + WCHAR* lfnbuf, /* Pointer to the LFN to be compared */ + BYTE* dir /* Pointer to the directory entry containing a part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last character has not been processed */ + wc = ff_wtoupper(uc); /* Convert it to upper case */ + if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ + return 0; /* Not matched */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Repeat until all characters in the entry are checked */ + + if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */ + return 0; + + return 1; /* The part of LFN matched */ +} + + + +static +int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ + WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */ + BYTE* dir /* Pointer to the directory entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last character has not been processed */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Read all character in the entry */ + + if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; +} + + +#if !_FS_READONLY +static +void fit_lfn ( + const WCHAR* lfnbuf, /* Pointer to the LFN buffer */ + BYTE* dir, /* Pointer to the directory entry */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* SFN sum */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set check sum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + ST_WORD(dir+LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective character */ + ST_WORD(dir+LfnOfs[s], wc); /* Put it */ + if (!wc) wc = 0xFFFF; /* Padding characters following last character */ + } while (++s < 13); + if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Create numbered name */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +void gen_numname ( + BYTE* dst, /* Pointer to generated SFN */ + const BYTE* src, /* Pointer to source SFN to be modified */ + const WCHAR* lfn, /* Pointer to LFN */ + WORD seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + + + mem_cpy(dst, src, 11); + + if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ + do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); + } + + /* itoa (hexdecimal) */ + i = 7; + do { + c = (seq % 16) + '0'; + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); + ns[i] = '~'; + + /* Append the number */ + for (j = 0; j < i && dst[j] != ' '; j++) { + if (IsDBCS1(dst[j])) { + if (j == i - 1) break; + j++; + } + } + do { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Calculate sum of an SFN */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +BYTE sum_sfn ( + const BYTE* dir /* Pointer to the SFN entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); + return sum; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_find ( + DIR* dp /* Pointer to the directory object linked to the file name */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dp, 0); /* Rewind directory object */ + if (res != FR_OK) return res; + +#if _USE_LFN + ord = sum = 0xFF; +#endif + do { + res = move_window(dp->fs, dp->sect); + if (res != FR_OK) break; + dir = dp->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (dp->lfn) { + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; /* LFN start order */ + dp->lfn_idx = dp->index; + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ + ord = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */ + if (!(dp->fn[NS] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break; /* SFN matched? */ + } + } +#else /* Non LFN configuration */ + if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dp->fn, 11)) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 +static +FRESULT dir_read ( + DIR* dp, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/directory or 1:volume label */ +) +{ + FRESULT res; + BYTE a, c, *dir; +#if _USE_LFN + BYTE ord = 0xFF, sum = 0xFF; +#endif + + res = FR_NO_FILE; + while (dp->sect) { + res = move_window(dp->fs, dp->sect); + if (res != FR_OK) break; + dir = dp->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ + a = dir[DIR_Attr] & AM_MASK; +#if _USE_LFN /* LFN configuration */ + if (c == DDE || (!_FS_RPATH && c == '.') || (int)(a == AM_VOL) != vol) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; + dp->lfn_idx = dp->index; + } + /* Check LFN validity and capture it */ + ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ + dp->lfn_idx = 0xFFFF; /* It has no LFN. */ + break; + } + } +#else /* Non LFN configuration */ + if (c != DDE && (_FS_RPATH || c != '.') && a != AM_LFN && (int)(a == AM_VOL) == vol) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dp, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dp->sect = 0; + + return res; +} +#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */ + + + + +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ + DIR* dp /* Target directory with object name to be created */ +) +{ + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD n, ne; + BYTE sn[12], *fn, sum; + WCHAR *lfn; + + + fn = dp->fn; lfn = dp->lfn; + mem_cpy(sn, fn, 12); + + if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ + return FR_INVALID_NAME; + + if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + fn[NS] = 0; dp->lfn = 0; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ + res = dir_find(dp); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + fn[NS] = sn[NS]; dp->lfn = lfn; + } + + if (sn[NS] & NS_LFN) { /* When LFN is to be created, allocate entries for an SFN + LFNs. */ + for (n = 0; lfn[n]; n++) ; + ne = (n + 25) / 13; + } else { /* Otherwise allocate an entry for an SFN */ + ne = 1; + } + res = dir_alloc(dp, ne); /* Allocate entries */ + + if (res == FR_OK && --ne) { /* Set LFN entry if needed */ + res = dir_sdi(dp, (WORD)(dp->index - ne)); + if (res == FR_OK) { + sum = sum_sfn(dp->fn); /* Sum value of the SFN tied to the LFN */ + do { /* Store LFN entries in bottom first */ + res = move_window(dp->fs, dp->sect); + if (res != FR_OK) break; + fit_lfn(dp->lfn, dp->dir, (BYTE)ne, sum); + dp->fs->wflag = 1; + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK && --ne); + } + } +#else /* Non LFN configuration */ + res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ +#endif + + if (res == FR_OK) { /* Set SFN entry */ + res = move_window(dp->fs, dp->sect); + if (res == FR_OK) { + mem_set(dp->dir, 0, SZ_DIR); /* Clean the entry */ + mem_cpy(dp->dir, dp->fn, 11); /* Put SFN */ +#if _USE_LFN + dp->dir[DIR_NTres] = dp->fn[NS] & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + dp->fs->wflag = 1; + } + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY && !_FS_MINIMIZE +static +FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ + DIR* dp /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD i; + + i = dp->index; /* SFN index */ + res = dir_sdi(dp, (WORD)((dp->lfn_idx == 0xFFFF) ? i : dp->lfn_idx)); /* Goto the SFN or top of the LFN entries */ + if (res == FR_OK) { + do { + res = move_window(dp->fs, dp->sect); + if (res != FR_OK) break; + *dp->dir = DDE; /* Mark the entry "deleted" */ + dp->fs->wflag = 1; + if (dp->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } + +#else /* Non LFN configuration */ + res = dir_sdi(dp, dp->index); + if (res == FR_OK) { + res = move_window(dp->fs, dp->sect); + if (res == FR_OK) { + *dp->dir = DDE; /* Mark the entry "deleted" */ + dp->fs->wflag = 1; + } + } +#endif + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Pick a segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT create_name ( + DIR* dp, /* Pointer to the directory object */ + const TCHAR** path /* Pointer to pointer to the segment in the path string */ +) +{ +#if _USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + /* Create LFN in Unicode */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + lfn = dp->lfn; + si = di = 0; + for (;;) { + w = p[si++]; /* Get a character */ + if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ + if (di >= _MAX_LFN) /* Reject too long name */ + return FR_INVALID_NAME; +#if !_LFN_UNICODE + w &= 0xFF; + if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + b = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(b)) + return FR_INVALID_NAME; /* Reject invalid sequence */ + w = (w << 8) + b; /* Create a DBC */ + } + w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ + if (!w) return FR_INVALID_NAME; /* Reject invalid code */ +#endif + if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal characters for LFN */ + return FR_INVALID_NAME; + lfn[di++] = w; /* Store the Unicode character */ + } + *path = &p[si]; /* Return pointer to the next segment */ + cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ +#if _FS_RPATH + if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ + (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { + lfn[di] = 0; + for (i = 0; i < 11; i++) + dp->fn[i] = (i < di) ? '.' : ' '; + dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Strip trailing spaces and dots */ + w = lfn[di-1]; + if (w != ' ' && w != '.') break; + di--; + } + if (!di) return FR_INVALID_NAME; /* Reject nul string */ + + lfn[di] = 0; /* LFN is created */ + + /* Create SFN in directory form */ + mem_set(dp->fn, ' ', 11); + for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ + if (si) cf |= NS_LOSS | NS_LFN; + while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + + b = i = 0; ni = 8; + for (;;) { + w = lfn[si++]; /* Get an LFN character */ + if (!w) break; /* Break on end of the LFN */ + if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ + cf |= NS_LOSS | NS_LFN; continue; + } + + if (i >= ni || si == di) { /* Extension or end of SFN */ + if (ni == 11) { /* Long extension */ + cf |= NS_LOSS | NS_LFN; break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + if (si > di) break; /* No extension */ + si = di; i = 8; ni = 11; /* Enter extension section */ + b <<= 2; continue; + } + + if (w >= 0x80) { /* Non ASCII character */ +#ifdef _EXCVT + w = ff_convert(w, 0); /* Unicode -> OEM code */ + if (w) w = ExCvt[w - 0x80]; /* Convert extended character to upper (SBCS) */ +#else + w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ +#endif + cf |= NS_LFN; /* Force create LFN entry */ + } + + if (_DF1S && w >= 0x100) { /* Double byte character (always false on SBCS cfg) */ + if (i >= ni - 1) { + cf |= NS_LOSS | NS_LFN; i = ni; continue; + } + dp->fn[i++] = (BYTE)(w >> 8); + } else { /* Single byte character */ + if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal characters for SFN */ + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(w)) { /* ASCII large capital */ + b |= 2; + } else { + if (IsLower(w)) { /* ASCII small capital */ + b |= 1; w -= 0x20; + } + } + } + } + dp->fn[i++] = (BYTE)w; + } + + if (dp->fn[0] == DDE) dp->fn[0] = NDDE; /* If the first character collides with deleted mark, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ + cf |= NS_LFN; + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ + if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + + dp->fn[NS] = cf; /* SFN is created */ + + return FR_OK; + + +#else /* Non-LFN configuration */ + BYTE b, c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + sfn = dp->fn; + mem_set(sfn, ' ', 11); + si = i = b = 0; ni = 8; +#if _FS_RPATH + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = &p[si]; /* Return pointer to the next segment */ + sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; + if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ + if (c == '.' || i >= ni) { + if (ni != 8 || c != '.') return FR_INVALID_NAME; + i = 8; ni = 11; + b <<= 2; continue; + } + if (c >= 0x80) { /* Extended character? */ + b |= 3; /* Eliminate NT flag */ +#ifdef _EXCVT + c = ExCvt[c - 0x80]; /* To upper extended characters (SBCS cfg) */ +#else +#if !_DF1S + return FR_INVALID_NAME; /* Reject extended characters (ASCII cfg) */ +#endif +#endif + } + if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ + return FR_INVALID_NAME; + sfn[i++] = c; + sfn[i++] = d; + } else { /* Single byte code */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ + return FR_INVALID_NAME; + if (IsUpper(c)) { /* ASCII large capital? */ + b |= 2; + } else { + if (IsLower(c)) { /* ASCII small capital? */ + b |= 1; c -= 0x20; + } + } + sfn[i++] = c; + } + } + *path = &p[si]; /* Return pointer to the next segment */ + c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if (!i) return FR_INVALID_NAME; /* Reject nul string */ + if (sfn[0] == DDE) sfn[0] = NDDE; /* When first character collides with DDE, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ + if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ + + sfn[NS] = c; /* Store NT flag, File name is created */ + + return FR_OK; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 +static +void get_fileinfo ( /* No return code */ + DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ +) +{ + UINT i; + TCHAR *p, c; + + + p = fno->fname; + if (dp->sect) { /* Get SFN */ + BYTE *dir = dp->dir; + + i = 0; + while (i < 11) { /* Copy name body and extension */ + c = (TCHAR)dir[i++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == NDDE) c = (TCHAR)DDE; /* Restore replaced DDE character */ + if (i == 9) *p++ = '.'; /* Insert a . if extension is exist */ +#if _USE_LFN + if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY))) + c += 0x20; /* To lower */ +#if _LFN_UNICODE + if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dir[i])) + c = c << 8 | dir[i++]; + c = ff_convert(c, 1); /* OEM -> Unicode */ + if (!c) c = '?'; +#endif +#endif + *p++ = c; + } + fno->fattrib = dir[DIR_Attr]; /* Attribute */ + fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ + fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ + fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ + } + *p = 0; /* Terminate SFN string by a \0 */ + +#if _USE_LFN + if (fno->lfname) { + WCHAR w, *lfn; + + i = 0; p = fno->lfname; + if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) { /* Get LFN if available */ + lfn = dp->lfn; + while ((w = *lfn++) != 0) { /* Get an LFN character */ +#if !_LFN_UNICODE + w = ff_convert(w, 0); /* Unicode -> OEM */ + if (!w) { i = 0; break; } /* No LFN if it could not be converted */ + if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ + p[i++] = (TCHAR)(w >> 8); +#endif + if (i >= fno->lfsize - 1) { i = 0; break; } /* No LFN if buffer overflow */ + p[i++] = (TCHAR)w; + } + } + p[i] = 0; /* Terminate LFN string by a \0 */ + } +#endif +} +#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2*/ + + + + +/*-----------------------------------------------------------------------*/ +/* Get logical drive number from path name */ +/*-----------------------------------------------------------------------*/ + +static +int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ + const TCHAR** path /* Pointer to pointer to the path name */ +) +{ + int vol = -1; + + + if (*path) { + vol = (*path)[0] - '0'; + if ((UINT)vol < 9 && (*path)[1] == ':') { /* There is a drive number */ + *path += 2; /* Get value and strip it */ + if (vol >= _VOLUMES) vol = -1; /* Check if the drive number is valid */ + } else { /* No drive number use default drive */ +#if _FS_RPATH && _VOLUMES >= 2 + vol = CurrVol; /* Current drive */ +#else + vol = 0; /* Drive 0 */ +#endif + } + } + + return vol; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR* dp, /* Directory object to return last directory and found object */ + const TCHAR* path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE *dir, ns; + + +#if _FS_RPATH + if (*path == '/' || *path == '\\') { /* There is a heading separator */ + path++; dp->sclust = 0; /* Strip it and start from the root directory */ + } else { /* No heading separator */ + dp->sclust = dp->fs->cdir; /* Start from the current directory */ + } +#else + if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ + path++; + dp->sclust = 0; /* Always start from the root directory */ +#endif + + if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ + res = dir_sdi(dp, 0); + dp->dir = 0; + } else { /* Follow path */ + for (;;) { + res = create_name(dp, &path); /* Get a segment name of the path */ + if (res != FR_OK) break; + res = dir_find(dp); /* Find an object with the sagment name */ + ns = dp->fn[NS]; + if (res != FR_OK) { /* Failed to find the object */ + if (res == FR_NO_FILE) { /* Object is not found */ + if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, */ + dp->sclust = 0; dp->dir = 0; /* it is the root directory and stay there */ + if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ + res = FR_OK; /* Ended at the root directroy. Function completed. */ + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ + } + } + break; + } + if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ + dir = dp->dir; /* Follow the sub-directory */ + if (!(dir[DIR_Attr] & AM_DIR)) { /* It is not a sub-directory and cannot follow */ + res = FR_NO_PATH; break; + } + dp->sclust = ld_clust(dp->fs, dir); + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT boot sector */ +/*-----------------------------------------------------------------------*/ + +static +BYTE check_fs ( /* 0:FAT boor sector, 1:Valid boor sector but not FAT, 2:Not a boot sector, 3:Disk error */ + FATFS* fs, /* File system object */ + DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ +) +{ + fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ + if (move_window(fs, sect) != FR_OK) /* Load boot record */ + return 3; + + if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check boot record signature (always placed at offset 510 even if the sector size is >512) */ + return 2; + + if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + + return 1; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Find logical drive and check if the volume is mounted */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ + FATFS** rfs, /* Pointer to pointer to the found file system object */ + const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ + BYTE wmode /* !=0: Check write protection for write access */ +) +{ + BYTE fmt; + int vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat; + WORD nrsv; + FATFS *fs; + + + /* Get logical drive number from the path name */ + *rfs = 0; + vol = get_ldnumber(path); + if (vol < 0) return FR_INVALID_DRIVE; + + /* Check if the file system object is valid or not */ + fs = FatFs[vol]; /* Get pointer to the file system object */ + if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + + ENTER_FF(fs); /* Lock the volume */ + *rfs = fs; /* Return pointer to the file system object */ + + if (fs->fs_type) { /* If the volume has been mounted */ + stat = disk_status(fs->drv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + return FR_OK; /* The file system object is valid */ + } + } + + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ + + fs->fs_type = 0; /* Clear the file system object */ + fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize the physical drive */ + if (stat & STA_NOINIT) /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get sector size (variable sector size cfg only) */ + if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) + return FR_DISK_ERR; +#endif + /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ + bsect = 0; + fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */ + if (fmt == 1 || (!fmt && (LD2PT(vol)))) { /* Not an FAT boot sector or forced partition number */ + UINT i; + DWORD br[4]; + + for (i = 0; i < 4; i++) { /* Get partition offset */ + BYTE *pt = fs->win+MBR_Table + i * SZ_PTE; + br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0; + } + i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ + if (i) i--; + do { /* Find an FAT volume */ + bsect = br[i]; + fmt = bsect ? check_fs(fs, bsect) : 2; /* Check the partition */ + } while (!LD2PT(vol) && fmt && ++i < 4); + } + if (fmt == 3) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found. Following code initializes the file system object */ + + if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + + fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ + if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */ + if (fs->n_fats != 1 && fs->n_fats != 2) /* (Must be 1 or 2) */ + return FR_NO_FILESYSTEM; + fasize *= fs->n_fats; /* Number of sectors for FAT area */ + + fs->csize = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ + if (!fs->csize || (fs->csize & (fs->csize - 1))) /* (Must be power of 2) */ + return FR_NO_FILESYSTEM; + + fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZ_DIR)) /* (Must be sector aligned) */ + return FR_NO_FILESYSTEM; + + tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ + if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); + + nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (!nrsv) return FR_NO_FILESYSTEM; /* (Must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = FS_FAT12; + if (nclst >= MIN_FAT16) fmt = FS_FAT16; + if (nclst >= MIN_FAT32) fmt = FS_FAT32; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->volbase = bsect; /* Volume start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + fs->database = bsect + sysect; /* Data start sector */ + if (fmt == FS_FAT32) { + if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Required FAT size) */ + } else { + if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */ + return FR_NO_FILESYSTEM; + +#if !_FS_READONLY + /* Initialize cluster allocation information */ + fs->last_clust = fs->free_clust = 0xFFFFFFFF; + + /* Get fsinfo if available */ + fs->fsi_flag = 0x80; + if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo is 1 */ + && LD_WORD(fs->win+BPB_FSInfo) == 1 + && move_window(fs, bsect + 1) == FR_OK) + { + fs->fsi_flag = 0; + if (LD_WORD(fs->win+BS_55AA) == 0xAA55 /* Load FSINFO data if available */ + && LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 + && LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) + { +#if !_FS_NOFSINFO + fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); +#endif + fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); + } + } +#endif + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ +#if _FS_RPATH + fs->cdir = 0; /* Current directory (root dir) */ +#endif +#if _FS_LOCK /* Clear file lock semaphores */ + clear_lock(fs); +#endif + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/directory object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ + void* obj /* Pointer to the object FIL/DIR to check validity */ +) +{ + FIL *fil = (FIL*)obj; /* Assuming offset of .fs and .id in the FIL/DIR structure is identical */ + + + if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id) + return FR_INVALID_OBJECT; + + ENTER_FF(fil->fs); /* Lock file system */ + + if (disk_status(fil->fs->drv) & STA_NOINIT) + return FR_NOT_READY; + + return FR_OK; +} + + + + +/*-------------------------------------------------------------------------- + + Public Functions + +--------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mount ( + FATFS* fs, /* Pointer to the file system object (NULL:unmount)*/ + const TCHAR* path, /* Logical drive number to be mounted/unmounted */ + BYTE opt /* 0:Do not mount (delayed mount), 1:Mount immediately */ +) +{ + FATFS *cfs; + int vol; + FRESULT res; + + + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + cfs = FatFs[vol]; /* Pointer to fs object */ + + if (cfs) { +#if _FS_LOCK + clear_lock(cfs); +#endif +#if _FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; +#endif + cfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + if (!fs || opt != 1) return FR_OK; /* Do not mount now, it will be mounted later */ + + res = find_volume(&fs, &path, 0); /* Force mounted the volume */ + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL* fp, /* Pointer to the blank file object */ + const TCHAR* path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + if (!fp) return FR_INVALID_OBJECT; + fp->fs = 0; /* Clear file object */ + + /* Get logical drive number */ +#if !_FS_READONLY + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; + res = find_volume(&dj.fs, &path, (BYTE)(mode & ~FA_READ)); +#else + mode &= FA_READ; + res = find_volume(&dj.fs, &path, 0); +#endif + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + dir = dj.dir; +#if !_FS_READONLY /* R/W configuration */ + if (res == FR_OK) { + if (!dir) /* Default directory itself */ + res = FR_INVALID_NAME; +#if _FS_LOCK + else + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + DWORD dw, cl; + + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ +#if _FS_LOCK + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ + } + else { /* Any object is already existing */ + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) /* Cannot create as new file */ + res = FR_EXIST; + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ + dw = get_fattime(); /* Created time */ + ST_DWORD(dir+DIR_CrtTime, dw); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ + cl = ld_clust(dj.fs, dir); /* Get start cluster */ + st_clust(dir, 0); /* cluster = 0 */ + dj.fs->wflag = 1; + if (cl) { /* Remove the cluster chain if exist */ + dw = dj.fs->winsect; + res = remove_chain(dj.fs, cl); + if (res == FR_OK) { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window(dj.fs, dw); + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Follow succeeded */ + if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ + res = FR_DENIED; + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA__WRITTEN; + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; +#if _FS_LOCK + fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->lockid) res = FR_INT_ERR; +#endif + } + +#else /* R/O configuration */ + if (res == FR_OK) { /* Follow succeeded */ + dir = dj.dir; + if (!dir) { /* Current directory itself */ + res = FR_INVALID_NAME; + } else { + if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ + res = FR_NO_FILE; + } + } +#endif + FREE_BUF(); + + if (res == FR_OK) { + fp->flag = mode; /* File access mode */ + fp->err = 0; /* Clear error flag */ + fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */ + fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; +#if _USE_FASTSEEK + fp->cltbl = 0; /* Normal seek mode */ +#endif + fp->fs = dj.fs; /* Validate file object */ + fp->id = fp->fs->id; + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL* fp, /* Pointer to the file object */ + void* buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT* br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + DWORD clst, sect, remain; + UINT rcnt, cc; + BYTE csect, *rbuff = (BYTE*)buff; + + + *br = 0; /* Clear read byte counter */ + + res = validate(fp); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->err) /* Check error */ + LEAVE_FF(fp->fs, (FRESULT)fp->err); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + remain = fp->fsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until all data read */ + rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ + } + if (clst < 2) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_read(fp->fs->drv, rbuff, sect, cc)) + ABORT(fp->fs, FR_DISK_ERR); +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if _FS_TINY + if (fp->fs->wflag && fp->fs->winsect - sect < cc) + mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); +#else + if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) + mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); +#endif +#endif + rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !_FS_TINY + if (fp->dsect != sect) { /* Load data sector if not in cache */ +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1)) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, sect, 1)) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ + if (rcnt > btr) rcnt = btr; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#else + mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#endif + } + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL* fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT* bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + DWORD clst, sect; + UINT wcnt, cc; + const BYTE *wbuff = (const BYTE*)buff; + BYTE csect; + + + *bw = 0; /* Clear write byte counter */ + + res = validate(fp); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->err) /* Check error */ + LEAVE_FF(fp->fs, (FRESULT)fp->err); + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + if (fp->fptr + btw < fp->fptr) btw = 0; /* File size cannot reach 4GB */ + + for ( ; btw; /* Repeat until all data written */ + wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + if (clst == 0) /* When no cluster is allocated, */ + fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } +#if _FS_TINY + if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) /* Write-back sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#else + if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1)) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_write(fp->fs->drv, wbuff, sect, cc)) + ABORT(fp->fs, FR_DISK_ERR); +#if _FS_MINIMIZE <= 2 +#if _FS_TINY + if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->fs->wflag = 0; + } +#else + if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->flag &= ~FA__DIRTY; + } +#endif +#endif + wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if _FS_TINY + if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ + if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); + fp->fs->winsect = sect; + } +#else + if (fp->dsect != sect) { /* Fill sector cache with file data */ + if (fp->fptr < fp->fsize && + disk_read(fp->fs->drv, fp->buf, sect, 1)) + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ + if (wcnt > btw) wcnt = btw; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->fs->wflag = 1; +#else + mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->flag |= FA__DIRTY; +#endif + } + + if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ + fp->flag |= FA__WRITTEN; /* Set file change flag */ + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD tm; + BYTE *dir; + + + res = validate(fp); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ + /* Write-back dirty buffer */ +#if !_FS_TINY + if (fp->flag & FA__DIRTY) { + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1)) + LEAVE_FF(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + /* Update the directory entry */ + res = move_window(fp->fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ + ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ + st_clust(dir, fp->sclust); /* Update start cluster */ + tm = get_fattime(); /* Update updated time */ + ST_DWORD(dir+DIR_WrtTime, tm); + ST_WORD(dir+DIR_LstAccDate, 0); + fp->flag &= ~FA__WRITTEN; + fp->fs->wflag = 1; + res = sync_fs(fp->fs); + } + } + } + + LEAVE_FF(fp->fs, res); +} + +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL *fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + + +#if _FS_READONLY + res = validate(fp); + { +#if _FS_REENTRANT + FATFS *fs = 0; + if (res == FR_OK) fs = fp->fs; /* Get corresponding file system object */ +#endif + if (res == FR_OK) fp->fs = 0; /* Invalidate file object */ + LEAVE_FF(fs, res); + } +#else + res = f_sync(fp); /* Flush cached data */ +#if _FS_LOCK + if (res == FR_OK) { /* Decrement open counter */ +#if _FS_REENTRANT + res = validate(fp); + if (res == FR_OK) { + res = dec_lock(fp->lockid); + unlock_fs(fp->fs, FR_OK); + } +#else + res = dec_lock(fp->lockid); +#endif + } +#endif + if (res == FR_OK) fp->fs = 0; /* Invalidate file object */ + return res; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Current Directory or Current Drive, Get Current Directory */ +/*-----------------------------------------------------------------------*/ + +#if _FS_RPATH >= 1 +#if _VOLUMES >= 2 +FRESULT f_chdrive ( + const TCHAR* path /* Drive number */ +) +{ + int vol; + + + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + + CurrVol = (BYTE)vol; + + return FR_OK; +} +#endif + + +FRESULT f_chdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMEBUF; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &path, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the path */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (!dj.dir) { + dj.fs->cdir = dj.sclust; /* Start directory itself */ + } else { + if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ + dj.fs->cdir = ld_clust(dj.fs, dj.dir); + else + res = FR_NO_PATH; /* Reached but a file */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(dj.fs, res); +} + + +#if _FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR* buff, /* Pointer to the directory path */ + UINT len /* Size of path */ +) +{ + FRESULT res; + DIR dj; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMEBUF; + + + *buff = 0; + /* Get logical drive number */ + res = find_volume(&dj.fs, (const TCHAR**)&buff, 0); /* Get current volume */ + if (res == FR_OK) { + INIT_BUF(dj); + i = len; /* Bottom of buffer (directory stack base) */ + dj.sclust = dj.fs->cdir; /* Start to follow upper directory from current directory */ + while ((ccl = dj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ + res = dir_sdi(&dj, 1); /* Get parent directory */ + if (res != FR_OK) break; + res = dir_read(&dj, 0); + if (res != FR_OK) break; + dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent directory */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child directory */ + res = dir_read(&dj, 0); + if (res != FR_OK) break; + if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; +#if _USE_LFN + fno.lfname = buff; + fno.lfsize = i; +#endif + get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ + tp = fno.fname; +#if _USE_LFN + if (*buff) tp = buff; +#endif + for (n = 0; tp[n]; n++) ; + if (i < n + 3) { + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) buff[--i] = tp[--n]; + buff[--i] = '/'; + } + tp = buff; + if (res == FR_OK) { +#if _VOLUMES >= 2 + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; +#endif + if (i == len) { /* Root-directory */ + *tp++ = '/'; + } else { /* Sub-directroy */ + do /* Add stacked path str */ + *tp++ = buff[i++]; + while (i < len); + } + } + *tp = 0; + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} +#endif /* _FS_RPATH >= 2 */ +#endif /* _FS_RPATH >= 1 */ + + + +#if _FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File R/W Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL* fp, /* Pointer to the file object */ + DWORD ofs /* File pointer from top of file */ +) +{ + FRESULT res; + + + res = validate(fp); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->err) /* Check error */ + LEAVE_FF(fp->fs, (FRESULT)fp->err); + +#if _USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; + + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->sclust; /* Top of the chain */ + if (cl) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(fp->fs, cl); + if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) + *tbl = 0; /* Terminate table */ + else + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + + } else { /* Fast seek */ + if (ofs > fp->fsize) /* Clip offset at the file size */ + ofs = fp->fsize; + fp->fptr = ofs; /* Set file pointer */ + if (ofs) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clust2sect(fp->fs, fp->clust); + if (!dsc) ABORT(fp->fs, FR_INT_ERR); + dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); + if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1)) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, dsc, 1)) /* Load current sector */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { + DWORD clst, bcs, nsect, ifptr; + + if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ +#if !_FS_READONLY + && !(fp->flag & FA_WRITE) +#endif + ) ofs = fp->fsize; + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs) { + bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->sclust; /* start from the first cluster */ +#if !_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(fp->fs, 0); + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ +#if !_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ + if (clst == 0) { /* When disk gets full, clip file size */ + ofs = bcs; break; + } + } else +#endif + clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); + fp->clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + fp->fptr += ofs; + if (ofs % SS(fp->fs)) { + nsect = clust2sect(fp->fs, clst); /* Current sector */ + if (!nsect) ABORT(fp->fs, FR_INT_ERR); + nsect += ofs / SS(fp->fs); + } + } + } + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1)) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, nsect, 1)) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = nsect; + } +#if !_FS_READONLY + if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ + fp->fsize = fp->fptr; + fp->flag |= FA__WRITTEN; + } +#endif + } + + LEAVE_FF(fp->fs, res); +} + + + +#if _FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directory Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + DIR* dp, /* Pointer to directory object to create */ + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS* fs; + DEF_NAMEBUF; + + + if (!dp) return FR_INVALID_OBJECT; + + /* Get logical drive number */ + res = find_volume(&fs, &path, 0); + if (res == FR_OK) { + dp->fs = fs; + INIT_BUF(*dp); + res = follow_path(dp, path); /* Follow the path to the directory */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (dp->dir) { /* It is not the origin directory itself */ + if (dp->dir[DIR_Attr] & AM_DIR) /* The object is a sub directory */ + dp->sclust = ld_clust(fs, dp->dir); + else /* The object is a file */ + res = FR_NO_PATH; + } + if (res == FR_OK) { + dp->id = fs->id; + res = dir_sdi(dp, 0); /* Rewind directory */ +#if _FS_LOCK + if (res == FR_OK) { + if (dp->sclust) { + dp->lockid = inc_lock(dp, 0); /* Lock the sub directory */ + if (!dp->lockid) + res = FR_TOO_MANY_OPEN_FILES; + } else { + dp->lockid = 0; /* Root directory need not to be locked */ + } + } +#endif + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + if (res != FR_OK) dp->fs = 0; /* Invalidate the directory object if function faild */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Close Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_closedir ( + DIR *dp /* Pointer to the directory object to be closed */ +) +{ + FRESULT res; + + + res = validate(dp); +#if _FS_LOCK + if (res == FR_OK) { /* Decrement open counter */ + if (dp->lockid) + res = dec_lock(dp->lockid); +#if _FS_REENTRANT + unlock_fs(dp->fs, FR_OK); +#endif + } +#endif + if (res == FR_OK) dp->fs = 0; /* Invalidate directory object */ + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entries in Sequence */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DEF_NAMEBUF; + + + res = validate(dp); /* Check validity of the object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dp, 0); /* Rewind the directory object */ + } else { + INIT_BUF(*dp); + res = dir_read(dp, 0); /* Read an item */ + if (res == FR_NO_FILE) { /* Reached end of directory */ + dp->sect = 0; + res = FR_OK; + } + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dp, fno); /* Get the object information */ + res = dir_next(dp, 0); /* Increment index for next */ + if (res == FR_NO_FILE) { + dp->sect = 0; + res = FR_OK; + } + } + FREE_BUF(); + } + } + + LEAVE_FF(dp->fs, res); +} + + + +#if _FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR* path, /* Pointer to the file path */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMEBUF; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &path, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.dir) { /* Found an object */ + if (fno) get_fileinfo(&dj, fno); + } else { /* It is root directory */ + res = FR_INVALID_NAME; + } + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR* path, /* Path name of the logical drive number */ + DWORD* nclst, /* Pointer to a variable to return number of free clusters */ + FATFS** fatfs /* Pointer to return pointer to corresponding file system object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD n, clst, sect, stat; + UINT i; + BYTE fat, *p; + + + /* Get logical drive number */ + res = find_volume(fatfs, &path, 0); + fs = *fatfs; + if (res == FR_OK) { + /* If free_clust is valid, return it without full cluster scan */ + if (fs->free_clust <= fs->n_fatent - 2) { + *nclst = fs->free_clust; + } else { + /* Get number of free clusters */ + fat = fs->fs_type; + n = 0; + if (fat == FS_FAT12) { + clst = 2; + do { + stat = get_fat(fs, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) n++; + } while (++clst < fs->n_fatent); + } else { + clst = fs->n_fatent; + sect = fs->fatbase; + i = 0; p = 0; + do { + if (!i) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + p = fs->win; + i = SS(fs); + } + if (fat == FS_FAT16) { + if (LD_WORD(p) == 0) n++; + p += 2; i -= 2; + } else { + if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; + p += 4; i -= 4; + } + } while (--clst); + } + fs->free_clust = n; + fs->fsi_flag |= 1; + *nclst = n; + } + } + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD ncl; + + + res = validate(fp); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->err) { /* Check error */ + res = (FRESULT)fp->err; + } else { + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + res = FR_DENIED; + } + } + if (res == FR_OK) { + if (fp->fsize > fp->fptr) { + fp->fsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA__WRITTEN; + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(fp->fs, fp->sclust); + fp->sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(fp->fs, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fp->fs->n_fatent) { + res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); + if (res == FR_OK) res = remove_chain(fp->fs, ncl); + } + } +#if !_FS_TINY + if (res == FR_OK && (fp->flag & FA__DIRTY)) { + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1)) + res = FR_DISK_ERR; + else + fp->flag &= ~FA__DIRTY; + } +#endif + } + if (res != FR_OK) fp->err = (FRESULT)res; + } + + LEAVE_FF(fp->fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File or Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR* path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + DIR dj, sdj; + BYTE *dir; + DWORD dclst; + DEF_NAMEBUF; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &path, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; /* Cannot remove dot entry */ +#if _FS_LOCK + if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ +#endif + if (res == FR_OK) { /* The object is accessible */ + dir = dj.dir; + if (!dir) { + res = FR_INVALID_NAME; /* Cannot remove the start directory */ + } else { + if (dir[DIR_Attr] & AM_RDO) + res = FR_DENIED; /* Cannot remove R/O object */ + } + dclst = ld_clust(dj.fs, dir); + if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ + if (dclst < 2) { + res = FR_INT_ERR; + } else { + mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-directory is empty or not */ + sdj.sclust = dclst; + res = dir_sdi(&sdj, 2); /* Exclude dot entries */ + if (res == FR_OK) { + res = dir_read(&sdj, 0); /* Read an item */ + if (res == FR_OK /* Not empty directory */ +#if _FS_RPATH + || dclst == dj.fs->cdir /* Current directory */ +#endif + ) res = FR_DENIED; + if (res == FR_NO_FILE) res = FR_OK; /* Empty */ + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK) { + if (dclst) /* Remove the cluster chain if exist */ + res = remove_chain(dj.fs, dclst); + if (res == FR_OK) res = sync_fs(dj.fs); + } + } + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir, n; + DWORD dsc, dcl, pcl, tm = get_fattime(); + DEF_NAMEBUF; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &path, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_NO_FILE) { /* Can create a new directory */ + dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) /* Flush FAT */ + res = sync_window(dj.fs); + if (res == FR_OK) { /* Initialize the new directory table */ + dsc = clust2sect(dj.fs, dcl); + dir = dj.fs->win; + mem_set(dir, 0, SS(dj.fs)); + mem_set(dir+DIR_Name, ' ', 11); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + ST_DWORD(dir+DIR_WrtTime, tm); + st_clust(dir, dcl); + mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ + dir[SZ_DIR+1] = '.'; pcl = dj.sclust; + if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) + pcl = 0; + st_clust(dir+SZ_DIR, pcl); + for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ + dj.fs->winsect = dsc++; + dj.fs->wflag = 1; + res = sync_window(dj.fs); + if (res != FR_OK) break; + mem_set(dir, 0, SS(dj.fs)); + } + } + if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ + if (res != FR_OK) { + remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ + } else { + dir = dj.dir; + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD(dir+DIR_WrtTime, tm); /* Created time */ + st_clust(dir, dcl); /* Table start cluster */ + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR* path, /* Pointer to the file path */ + BYTE value, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &path, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Is it a root directory? */ + res = FR_INVALID_NAME; + } else { /* File or sub directory */ + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ + dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR* path, /* Pointer to the file/directory name */ + const FILINFO* fno /* Pointer to the time stamp to be set */ +) +{ + FRESULT res; + DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &path, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Root directory */ + res = FR_INVALID_NAME; + } else { /* File or sub-directory */ + ST_WORD(dir+DIR_WrtTime, fno->ftime); + ST_WORD(dir+DIR_WrtDate, fno->fdate); + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR* path_old, /* Pointer to the old name */ + const TCHAR* path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DIR djo, djn; + BYTE buf[21], *dir; + DWORD dw; + DEF_NAMEBUF; + + + /* Get logical drive number of the source object */ + res = find_volume(&djo.fs, &path_old, 1); + if (res == FR_OK) { + djn.fs = djo.fs; + INIT_BUF(djo); + res = follow_path(&djo, path_old); /* Check old object */ + if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; +#if _FS_LOCK + if (res == FR_OK) res = chk_lock(&djo, 2); +#endif + if (res == FR_OK) { /* Old object is found */ + if (!djo.dir) { /* Is root dir? */ + res = FR_NO_FILE; + } else { + mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ + mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */ + res = follow_path(&djn, path_new); + if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ + if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ +/* Start critical section that any interruption can cause a cross-link */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy object information except for name */ + mem_cpy(dir+13, buf+2, 19); + dir[DIR_Attr] = buf[0] | AM_ARC; + djo.fs->wflag = 1; + if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ + dw = clust2sect(djo.fs, ld_clust(djo.fs, dir)); + if (!dw) { + res = FR_INT_ERR; + } else { + res = move_window(djo.fs, dw); + dir = djo.fs->win+SZ_DIR; /* .. entry */ + if (res == FR_OK && dir[1] == '.') { + dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust; + st_clust(dir, dw); + djo.fs->wflag = 1; + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) + res = sync_fs(djo.fs); + } + } +/* End critical section */ + } + } + } + FREE_BUF(); + } + + LEAVE_FF(djo.fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _FS_MINIMIZE == 0 */ +#endif /* _FS_MINIMIZE <= 1 */ +#endif /* _FS_MINIMIZE <= 2 */ + + + +#if _USE_LABEL +/*-----------------------------------------------------------------------*/ +/* Get volume label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getlabel ( + const TCHAR* path, /* Path name of the logical drive number */ + TCHAR* label, /* Pointer to a buffer to return the volume label */ + DWORD* sn /* Pointer to a variable to return the volume serial number */ +) +{ + FRESULT res; + DIR dj; + UINT i, j; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &path, 0); + + /* Get volume label */ + if (res == FR_OK && label) { + dj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ + if (res == FR_OK) { /* A volume label is exist */ +#if _LFN_UNICODE + WCHAR w; + i = j = 0; + do { + w = (i < 11) ? dj.dir[i++] : ' '; + if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i])) + w = w << 8 | dj.dir[i++]; + label[j++] = ff_convert(w, 1); /* OEM -> Unicode */ + } while (j < 11); +#else + mem_cpy(label, dj.dir, 11); +#endif + j = 11; + do { + label[j] = 0; + if (!j) break; + } while (label[--j] == ' '); + } + if (res == FR_NO_FILE) { /* No label, return nul string */ + label[0] = 0; + res = FR_OK; + } + } + } + + /* Get volume serial number */ + if (res == FR_OK && sn) { + res = move_window(dj.fs, dj.fs->volbase); + if (res == FR_OK) { + i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID; + *sn = LD_DWORD(&dj.fs->win[i]); + } + } + + LEAVE_FF(dj.fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Set volume label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setlabel ( + const TCHAR* label /* Pointer to the volume label to set */ +) +{ + FRESULT res; + DIR dj; + BYTE vn[11]; + UINT i, j, sl; + WCHAR w; + DWORD tm; + + + /* Get logical drive number */ + res = find_volume(&dj.fs, &label, 1); + if (res) LEAVE_FF(dj.fs, res); + + /* Create a volume label in directory form */ + vn[0] = 0; + for (sl = 0; label[sl]; sl++) ; /* Get name length */ + for ( ; sl && label[sl-1] == ' '; sl--) ; /* Remove trailing spaces */ + if (sl) { /* Create volume label in directory form */ + i = j = 0; + do { +#if _LFN_UNICODE + w = ff_convert(ff_wtoupper(label[i++]), 0); +#else + w = (BYTE)label[i++]; + if (IsDBCS1(w)) + w = (j < 10 && i < sl && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0; +#if _USE_LFN + w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0); +#else + if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */ +#ifdef _EXCVT + if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */ +#else + if (!_DF1S && w >= 0x80) w = 0; /* Reject extended characters (ASCII cfg) */ +#endif +#endif +#endif + if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid characters for volume label */ + LEAVE_FF(dj.fs, FR_INVALID_NAME); + if (w >= 0x100) vn[j++] = (BYTE)(w >> 8); + vn[j++] = (BYTE)w; + } while (i < sl); + while (j < 11) vn[j++] = ' '; + } + + /* Set volume label */ + dj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ + if (res == FR_OK) { /* A volume label is found */ + if (vn[0]) { + mem_cpy(dj.dir, vn, 11); /* Change the volume label name */ + tm = get_fattime(); + ST_DWORD(dj.dir+DIR_WrtTime, tm); + } else { + dj.dir[0] = DDE; /* Remove the volume label */ + } + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } else { /* No volume label is found or error */ + if (res == FR_NO_FILE) { + res = FR_OK; + if (vn[0]) { /* Create volume label as new */ + res = dir_alloc(&dj, 1); /* Allocate an entry for volume label */ + if (res == FR_OK) { + mem_set(dj.dir, 0, SZ_DIR); /* Set volume label */ + mem_cpy(dj.dir, vn, 11); + dj.dir[DIR_Attr] = AM_VOL; + tm = get_fattime(); + ST_DWORD(dj.dir+DIR_WrtTime, tm); + dj.fs->wflag = 1; + res = sync_fs(dj.fs); + } + } + } + } + } + + LEAVE_FF(dj.fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_LABEL */ + + + +/*-----------------------------------------------------------------------*/ +/* Forward data to the stream directly (available on only tiny cfg) */ +/*-----------------------------------------------------------------------*/ +#if _USE_FORWARD && _FS_TINY + +FRESULT f_forward ( + FIL* fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btf, /* Number of bytes to forward */ + UINT* bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + DWORD remain, clst, sect; + UINT rcnt; + BYTE csect; + + + *bf = 0; /* Clear transfer byte counter */ + + res = validate(fp); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->err) /* Check error */ + LEAVE_FF(fp->fs, (FRESULT)fp->err); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + + remain = fp->fsize - fp->fptr; + if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ + + for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ + fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + if (!csect) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->sclust : get_fat(fp->fs, fp->clust); + if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + if (move_window(fp->fs, sect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + fp->dsect = sect; + rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ + if (rcnt > btf) rcnt = btf; + rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); + if (!rcnt) ABORT(fp->fs, FR_INT_ERR); + } + + LEAVE_FF(fp->fs, FR_OK); +} +#endif /* _USE_FORWARD */ + + + +#if _USE_MKFS && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create File System on the Drive */ +/*-----------------------------------------------------------------------*/ +#define N_ROOTDIR 512 /* Number of root directory entries for FAT12/16 */ +#define N_FATS 1 /* Number of FAT copies (1 or 2) */ + + +FRESULT f_mkfs ( + const TCHAR* path, /* Logical drive number */ + BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ + UINT au /* Allocation unit [bytes] */ +) +{ + static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; + static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; + int vol; + BYTE fmt, md, sys, *tbl, pdrv, part; + DWORD n_clst, vs, n, wsect; + UINT i; + DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ + FATFS *fs; + DSTATUS stat; + + + /* Check mounted drive and clear work area */ + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + if (sfd > 1) return FR_INVALID_PARAMETER; + if (au & (au - 1)) return FR_INVALID_PARAMETER; + fs = FatFs[vol]; + if (!fs) return FR_NOT_ENABLED; + fs->fs_type = 0; + pdrv = LD2PD(vol); /* Physical drive */ + part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ + + /* Get disk statics */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) + return FR_DISK_ERR; +#endif + if (_MULTI_PARTITION && part) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, fs->win, 0, 1)) return FR_DISK_ERR; + if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = LD_DWORD(tbl+8); /* Volume start sector */ + n_vol = LD_DWORD(tbl+12); /* Volume size */ + } else { + /* Create a partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) + return FR_DISK_ERR; + b_vol = (sfd) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; /* Volume size */ + } + + if (!au) { /* AU auto selection */ + vs = n_vol / (2000 / (SS(fs) / 512)); + for (i = 0; vs < vst[i]; i++) ; + au = cst[i]; + } + au /= SS(fs); /* Number of sectors per cluster */ + if (au == 0) au = 1; + if (au > 128) au = 128; + + /* Pre-compute number of clusters and FAT sub-type */ + n_clst = n_vol / au; + fmt = FS_FAT12; + if (n_clst >= MIN_FAT16) fmt = FS_FAT16; + if (n_clst >= MIN_FAT32) fmt = FS_FAT32; + + /* Determine offset and size of FAT structure */ + if (fmt == FS_FAT32) { + n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); + n_rsv = 32; + n_dir = 0; + } else { + n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; + n_fat = (n_fat + SS(fs) - 1) / SS(fs); + n_rsv = 1; + n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); + } + b_fat = b_vol + n_rsv; /* FAT area start sector */ + b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ + b_data = b_dir + n_dir; /* Data area start sector */ + if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ + + /* Align data start sector to erase block boundary (for flash memory media) */ + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; + n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ + n = (n - b_data) / N_FATS; + if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ + n_rsv += n; + b_fat += n; + } else { /* FAT12/16: Expand FAT size */ + n_fat += n; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; + if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) + || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) + return FR_MKFS_ABORTED; + + /* Determine system ID in the partition table */ + if (fmt == FS_FAT32) { + sys = 0x0C; /* FAT32X */ + } else { + if (fmt == FS_FAT12 && n_vol < 0x10000) { + sys = 0x01; /* FAT12(<65536) */ + } else { + sys = (n_vol < 0x10000) ? 0x04 : 0x06; /* FAT16(<65536) : FAT12/16(>=65536) */ + } + } + + if (_MULTI_PARTITION && part) { + /* Update system ID in the partition table */ + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + tbl[4] = sys; + if (disk_write(pdrv, fs->win, 0, 1)) /* Write it to teh MBR */ + return FR_DISK_ERR; + md = 0xF8; + } else { + if (sfd) { /* No partition table (SFD) */ + md = 0xF0; + } else { /* Create partition table (FDISK) */ + mem_set(fs->win, 0, SS(fs)); + tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */ + tbl[1] = 1; /* Partition start head */ + tbl[2] = 1; /* Partition start sector */ + tbl[3] = 0; /* Partition start cylinder */ + tbl[4] = sys; /* System type */ + tbl[5] = 254; /* Partition end head */ + n = (b_vol + n_vol) / 63 / 255; + tbl[6] = (BYTE)(n >> 2 | 63); /* Partition end sector */ + tbl[7] = (BYTE)n; /* End cylinder */ + ST_DWORD(tbl+8, 63); /* Partition start in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ + ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(pdrv, fs->win, 0, 1)) /* Write it to the MBR */ + return FR_DISK_ERR; + md = 0xF8; + } + } + + /* Create BPB in the VBR */ + tbl = fs->win; /* Clear sector */ + mem_set(tbl, 0, SS(fs)); + mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ + i = SS(fs); /* Sector size */ + ST_WORD(tbl+BPB_BytsPerSec, i); + tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ + ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ + tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ + i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of root directory entries */ + ST_WORD(tbl+BPB_RootEntCnt, i); + if (n_vol < 0x10000) { /* Number of total sectors */ + ST_WORD(tbl+BPB_TotSec16, n_vol); + } else { + ST_DWORD(tbl+BPB_TotSec32, n_vol); + } + tbl[BPB_Media] = md; /* Media descriptor */ + ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ + ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ + ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+BS_VolID32, n); /* VSN */ + ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ + ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ + ST_WORD(tbl+BPB_FSInfo, 1); /* FSINFO record offset (VBR+1) */ + ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ + tbl[BS_DrvNum32] = 0x80; /* Drive number */ + tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + ST_DWORD(tbl+BS_VolID, n); /* VSN */ + ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, tbl, b_vol, 1)) /* Write it to the VBR sector */ + return FR_DISK_ERR; + if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ + disk_write(pdrv, tbl, b_vol + 6, 1); + + /* Initialize FAT area */ + wsect = b_fat; + for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ + mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ + n = md; /* Media descriptor byte */ + if (fmt != FS_FAT32) { + n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ + } else { + n |= 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ + ST_DWORD(tbl+4, 0xFFFFFFFF); + ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root directory */ + } + if (disk_write(pdrv, tbl, wsect++, 1)) + return FR_DISK_ERR; + mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ + for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ + if (disk_write(pdrv, tbl, wsect++, 1)) + return FR_DISK_ERR; + } + } + + /* Initialize root directory */ + i = (fmt == FS_FAT32) ? au : n_dir; + do { + if (disk_write(pdrv, tbl, wsect++, 1)) + return FR_DISK_ERR; + } while (--i); + +#if _USE_ERASE /* Erase data area if needed */ + { + DWORD eb[2]; + + eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; + disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); + } +#endif + + /* Create FSINFO if needed */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+FSI_LeadSig, 0x41615252); + ST_DWORD(tbl+FSI_StrucSig, 0x61417272); + ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ + ST_WORD(tbl+BS_55AA, 0xAA55); + disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ + disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + } + + return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; +} + + + +#if _MULTI_PARTITION +/*-----------------------------------------------------------------------*/ +/* Divide Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD szt[], /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine CHS in the table regardless of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, _MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; + if (!p_cyl) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x06; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + ST_DWORD(p + 8, s_part); /* Start sector in LBA */ + ST_DWORD(p + 12, sz_part); /* Partition size */ + + /* Next partition */ + b_cyl += p_cyl; + } + ST_WORD(p, 0xAA55); + + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; +} + + +#endif /* _MULTI_PARTITION */ +#endif /* _USE_MKFS && !_FS_READONLY */ + + + + +#if _USE_STRFUNC +/*-----------------------------------------------------------------------*/ +/* Get a string from the file */ +/*-----------------------------------------------------------------------*/ + +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL* fp /* Pointer to the file object */ +) +{ + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; + + + while (n < len - 1) { /* Read characters until buffer gets filled */ +#if _LFN_UNICODE +#if _STRF_ENCODE == 3 /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; + if (c >= 0x80) { + if (c < 0xC0) continue; /* Skip stray trailer */ + if (c < 0xE0) { /* Two-byte sequence */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = (c & 0x1F) << 6 | (s[0] & 0x3F); + if (c < 0x80) c = '?'; + } else { + if (c < 0xF0) { /* Three-byte sequence */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F); + if (c < 0x800) c = '?'; + } else { /* Reject four-byte sequence */ + c = '?'; + } + } + } +#elif _STRF_ENCODE == 2 /* Read a character in UTF-16BE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = s[1] + (s[0] << 8); +#elif _STRF_ENCODE == 1 /* Read a character in UTF-16LE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = s[0] + (s[1] << 8); +#else /* Read a character in ANSI/OEM */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; + if (IsDBCS1(c)) { + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = (c << 8) + s[0]; + } + c = ff_convert(c, 1); /* OEM -> Unicode */ + if (!c) c = '?'; +#endif +#else /* Read a character without conversion */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; +#endif + if (_USE_STRFUNC == 2 && c == '\r') continue; /* Strip '\r' */ + *p++ = c; + n++; + if (c == '\n') break; /* Break on EOL */ + } + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ +} + + + +#if !_FS_READONLY +#include +/*-----------------------------------------------------------------------*/ +/* Put a character to the file */ +/*-----------------------------------------------------------------------*/ + +typedef struct { + FIL* fp; + int idx, nchr; + BYTE buf[64]; +} putbuff; + + +static +void putc_bfd ( + putbuff* pb, + TCHAR c +) +{ + UINT bw; + int i; + + + if (_USE_STRFUNC == 2 && c == '\n') /* LF -> CRLF conversion */ + putc_bfd(pb, '\r'); + + i = pb->idx; /* Buffer write index (-1:error) */ + if (i < 0) return; + +#if _LFN_UNICODE +#if _STRF_ENCODE == 3 /* Write a character in UTF-8 */ + if (c < 0x80) { /* 7-bit */ + pb->buf[i++] = (BYTE)c; + } else { + if (c < 0x800) { /* 11-bit */ + pb->buf[i++] = (BYTE)(0xC0 | c >> 6); + } else { /* 16-bit */ + pb->buf[i++] = (BYTE)(0xE0 | c >> 12); + pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F)); + } +#elif _STRF_ENCODE == 2 /* Write a character in UTF-16BE */ + pb->buf[i++] = (BYTE)(c >> 8); + pb->buf[i++] = (BYTE)c; +#elif _STRF_ENCODE == 1 /* Write a character in UTF-16LE */ + pb->buf[i++] = (BYTE)c; + pb->buf[i++] = (BYTE)(c >> 8); +#else /* Write a character in ANSI/OEM */ + c = ff_convert(c, 0); /* Unicode -> OEM */ + if (!c) c = '?'; + if (c >= 0x100) + pb->buf[i++] = (BYTE)(c >> 8); + pb->buf[i++] = (BYTE)c; +#endif +#else /* Write a character without conversion */ + pb->buf[i++] = (BYTE)c; +#endif + + if (i >= (int)(sizeof pb->buf) - 3) { /* Write buffered characters to the file */ + f_write(pb->fp, pb->buf, (UINT)i, &bw); + i = (bw == (UINT)i) ? 0 : -1; + } + pb->idx = i; + pb->nchr++; +} + + + +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + UINT nw; + + + pb.fp = fp; /* Initialize output buffer */ + pb.nchr = pb.idx = 0; + + putc_bfd(&pb, c); /* Put a character */ + + if ( pb.idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK + && (UINT)pb.idx == nw) return pb.nchr; + return EOF; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a string to the file */ +/*-----------------------------------------------------------------------*/ + +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + UINT nw; + + + pb.fp = fp; /* Initialize output buffer */ + pb.nchr = pb.idx = 0; + + while (*str) /* Put the string */ + putc_bfd(&pb, *str++); + + if ( pb.idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK + && (UINT)pb.idx == nw) return pb.nchr; + return EOF; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a formatted string to the file */ +/*-----------------------------------------------------------------------*/ + +int f_printf ( + FIL* fp, /* Pointer to the file object */ + const TCHAR* fmt, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + BYTE f, r; + UINT nw, i, j, w; + DWORD v; + TCHAR c, d, s[16], *p; + putbuff pb; + + + pb.fp = fp; /* Initialize output buffer */ + pb.nchr = pb.idx = 0; + + va_start(arp, fmt); + + for (;;) { + c = *fmt++; + if (c == 0) break; /* End of string */ + if (c != '%') { /* Non escape character */ + putc_bfd(&pb, c); + continue; + } + w = f = 0; + c = *fmt++; + if (c == '0') { /* Flag: '0' padding */ + f = 1; c = *fmt++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *fmt++; + } + } + while (IsDigit(c)) { /* Precision */ + w = w * 10 + c - '0'; + c = *fmt++; + } + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ + f |= 4; c = *fmt++; + } + if (!c) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + if (!(f & 2)) { + while (j++ < w) putc_bfd(&pb, ' '); + } + while (*p) putc_bfd(&pb, *p++); + while (j++ < w) putc_bfd(&pb, ' '); + continue; + case 'C' : /* Character */ + putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; + case 'B' : /* Binary */ + r = 2; break; + case 'O' : /* Octal */ + r = 8; break; + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + case 'X' : /* Hexdecimal */ + r = 16; break; + default: /* Unknown type (pass-through) */ + putc_bfd(&pb, c); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + s[i++] = d + '0'; + } while (v && i < sizeof s / sizeof s[0]); + if (f & 8) s[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + while (!(f & 2) && j++ < w) putc_bfd(&pb, d); + do putc_bfd(&pb, s[--i]); while (i); + while (j++ < w) putc_bfd(&pb, d); + } + + va_end(arp); + + if ( pb.idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK + && (UINT)pb.idx == nw) return pb.nchr; + return EOF; +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_STRFUNC */ diff --git a/stm/fatfs/ff.h b/stm/fatfs/ff.h new file mode 100644 index 000000000..626b476ce --- /dev/null +++ b/stm/fatfs/ff.h @@ -0,0 +1,342 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module include file R0.10 (C)ChaN, 2013 +/----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2013, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/----------------------------------------------------------------------------*/ + +#ifndef _FATFS +#define _FATFS 80960 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ + +#if _FATFS != _FFCONF +#error Wrong configuration file (ffconf.h). +#endif + + + +/* Definitions of volume management */ + +#if _MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ + +#else /* Single partition configuration */ +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ + +#endif + + + +/* Type of path name strings on FatFs API */ + +#if _LFN_UNICODE /* Unicode string */ +#if !_USE_LFN +#error _LFN_UNICODE must be 0 in non-LFN cfg. +#endif +#ifndef _INC_TCHAR +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#endif + +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + +#endif + + + +/* File system object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* FAT sub-type (0:Not mounted) */ + BYTE drv; /* Physical drive number */ + BYTE csize; /* Sectors per cluster (1,2,4...128) */ + BYTE n_fats; /* Number of FAT copies (1 or 2) */ + BYTE wflag; /* win[] flag (b0:dirty) */ + BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ +#if _MAX_SS != 512 + WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ +#endif +#if _FS_REENTRANT + _SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !_FS_READONLY + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ +#endif +#if _FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#endif + DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ + DWORD fsize; /* Sectors per FAT */ + DWORD volbase; /* Volume start sector */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +} FATFS; + + + +/* File object structure (FIL) */ + +typedef struct { + FATFS* fs; /* Pointer to the related file system object (**do not change order**) */ + WORD id; /* Owner file system mount ID (**do not change order**) */ + BYTE flag; /* File status flags */ + BYTE err; /* Abort flag (error code) */ + DWORD fptr; /* File read/write pointer (Zeroed on file open) */ + DWORD fsize; /* File size */ + DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */ + DWORD clust; /* Current cluster of fpter */ + DWORD dsect; /* Current data sector of fpter */ +#if !_FS_READONLY + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE* dir_ptr; /* Pointer to the directory entry in the window */ +#endif +#if _USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */ +#endif +#if _FS_LOCK + UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ +#endif +#if !_FS_TINY + BYTE buf[_MAX_SS]; /* File data read/write buffer */ +#endif +} FIL; + + + +/* Directory object structure (DIR) */ + +typedef struct { + FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */ + WORD id; /* Owner file system mount ID (**do not change order**) */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Root dir) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE* dir; /* Pointer to the current SFN entry in the win[] */ + BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ +#if _FS_LOCK + UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ +#endif +#if _USE_LFN + WCHAR* lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ +#endif +} DIR; + + + +/* File status structure (FILINFO) */ + +typedef struct { + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ +#if _USE_LFN + TCHAR* lfname; /* Pointer to the LFN buffer */ + UINT lfsize; /* Size of LFN buffer in TCHAR */ +#endif +} FILINFO; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_close (FIL* fp); /* Close an open file object */ +FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ +FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ +FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ +FRESULT f_truncate (FIL* fp); /* Truncate file */ +FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ +FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ +FRESULT f_closedir (DIR* dp); /* Close an open directory */ +FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ +FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ +FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */ +FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */ +FRESULT f_chdir (const TCHAR* path); /* Change current directory */ +FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ +FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ +FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* sn); /* Get volume label */ +FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ +FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */ +FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ +int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ +int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ +int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ + +#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) +#define f_error(fp) ((fp)->err) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->fsize) + +#ifndef EOF +#define EOF (-1) +#endif + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !_FS_READONLY +DWORD get_fattime (void); +#endif + +/* Unicode support functions */ +#if _USE_LFN /* Unicode - OEM code conversion */ +WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ +WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ +#if _USE_LFN == 3 /* Memory functions */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif +#endif + +/* Sync functions */ +#if _FS_REENTRANT +int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ +int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ +void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ +int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access control and file status flags (FIL.flag) */ + +#define FA_READ 0x01 +#define FA_OPEN_EXISTING 0x00 + +#if !_FS_READONLY +#define FA_WRITE 0x02 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA__WRITTEN 0x20 +#define FA__DIRTY 0x40 +#endif + + +/* FAT sub type (FATFS.fs_type) */ + +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 + + +/* File attribute bits for directory entry */ + +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Fast seek feature */ +#define CREATE_LINKMAP 0xFFFFFFFF + + + +/*--------------------------------*/ +/* Multi-byte word access macros */ + +#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) +#else /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FATFS */ diff --git a/stm/fatfs/ffconf.h b/stm/fatfs/ffconf.h new file mode 100644 index 000000000..182793b17 --- /dev/null +++ b/stm/fatfs/ffconf.h @@ -0,0 +1,212 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file R0.10 (C)ChaN, 2013 +/----------------------------------------------------------------------------/ +/ +/ CAUTION! Do not forget to make clean the project after any changes to +/ the configuration options. +/ +/----------------------------------------------------------------------------*/ +#ifndef _FFCONF +#define _FFCONF 80960 /* Revision ID */ + + +/*---------------------------------------------------------------------------/ +/ Functions and Buffer Configurations +/----------------------------------------------------------------------------*/ + +#define _FS_TINY 1 /* 0:Normal or 1:Tiny */ +/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system +/ object instead of the sector buffer in the individual file object for file +/ data transfer. This reduces memory consumption 512 bytes each file object. */ + + +#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ +/* Setting _FS_READONLY to 1 defines read only configuration. This removes +/ writing functions, f_write(), f_sync(), f_unlink(), f_mkdir(), f_chmod(), +/ f_rename(), f_truncate() and useless f_getfree(). */ + + +#define _FS_MINIMIZE 0 /* 0 to 3 */ +/* The _FS_MINIMIZE option defines minimization level to remove API functions. +/ +/ 0: All basic functions are enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(), +/ f_truncate() and f_rename() function are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ +/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ + + +#define _USE_MKFS 1 /* 0:Disable or 1:Enable */ +/* To enable f_mkfs() function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ + + +#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ +/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ + + +#define _USE_LABEL 0 /* 0:Disable or 1:Enable */ +/* To enable volume label functions, set _USE_LAVEL to 1 */ + + +#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ +/* To enable f_forward() function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/----------------------------------------------------------------------------*/ + +#define _CODE_PAGE 1 +/* The _CODE_PAGE specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII (Valid for only non-LFN cfg.) +*/ + + +#define _USE_LFN 0 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +/* The _USE_LFN option switches the LFN feature. +/ +/ 0: Disable LFN feature. _MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable LFN feature, Unicode handling functions ff_convert() and ff_wtoupper() +/ function must be added to the project. +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When use stack for the +/ working buffer, take care on stack overflow. When use heap memory for the working +/ buffer, memory management functions, ff_memalloc() and ff_memfree(), must be added +/ to the project. */ + + +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +/* To switch the character encoding on the FatFs API to Unicode, enable LFN feature +/ and set _LFN_UNICODE to 1. */ + + +#define _STRF_ENCODE 3 /* 0:ANSI/OEM, 1:UTF-16LE, 2:UTF-16BE, 3:UTF-8 */ +/* When Unicode API is enabled, character encoding on the all FatFs API is switched +/ to Unicode. This option selects the character encoding on the file to be read/written +/ via string functions, f_gets(), f_putc(), f_puts and f_printf(). +/ This option has no effect when _LFN_UNICODE is 0. */ + + +#define _FS_RPATH 0 /* 0 to 2 */ +/* The _FS_RPATH option configures relative path feature. +/ +/ 0: Disable relative path feature and remove related functions. +/ 1: Enable relative path. f_chdrive() and f_chdir() function are available. +/ 2: f_getcwd() function is available in addition to 1. +/ +/ Note that output of the f_readdir() fnction is affected by this option. */ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/----------------------------------------------------------------------------*/ + +#define _VOLUMES 1 +/* Number of volumes (logical drives) to be used. */ + + +#define _MULTI_PARTITION 1 /* 0:Single partition, 1:Enable multiple partition */ +/* When set to 0, each volume is bound to the same physical drive number and +/ it can mount only first primaly partition. When it is set to 1, each volume +/ is tied to the partitions listed in VolToPart[]. */ + + +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +/* Maximum sector size to be handled. +/ Always set 512 for memory card and hard disk but a larger value may be +/ required for on-board flash memory, floppy disk and optical disk. +/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size +/ and GET_SECTOR_SIZE command must be implemented to the disk_ioctl() function. */ + + +#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ +/* To enable sector erase feature, set _USE_ERASE to 1. Also CTRL_ERASE_SECTOR command +/ should be added to the disk_ioctl() function. */ + + +#define _FS_NOFSINFO 0 /* 0 or 1 */ +/* If you need to know the correct free space on the FAT32 volume, set this +/ option to 1 and f_getfree() function at first time after volume mount will +/ force a full FAT scan. +/ +/ 0: Load all informations in the FSINFO if available. +/ 1: Do not trust free cluster count in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/----------------------------------------------------------------------------*/ + +#define _WORD_ACCESS 0 /* 0 or 1 */ +/* The _WORD_ACCESS option is an only platform dependent option. It defines +/ which access method is used to the word data on the FAT volume. +/ +/ 0: Byte-by-byte access. Always compatible with all platforms. +/ 1: Word access. Do not choose this unless under both the following conditions. +/ +/ * Byte order on the memory is little-endian. +/ * Address miss-aligned word access is always allowed for all instructions. +/ +/ If it is the case, _WORD_ACCESS can also be set to 1 to improve performance +/ and reduce code size. +*/ + + +/* A header file that defines sync object types on the O/S, such as +/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ + +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ + +/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs module. +/ +/ 0: Disable re-entrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function must be added to the project. */ + + +#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */ +/* To enable file lock control feature, set _FS_LOCK to 1 or greater. + The value defines how many files can be opened simultaneously. */ + + +#endif /* _FFCONFIG */ diff --git a/stm/fatfs/integer.h b/stm/fatfs/integer.h new file mode 100644 index 000000000..074a46bd5 --- /dev/null +++ b/stm/fatfs/integer.h @@ -0,0 +1,33 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef _FF_INTEGER +#define _FF_INTEGER + +#ifdef _WIN32 /* FatFs development platform */ + +#include +#include + +#else /* Embedded platform */ + +/* This type MUST be 8 bit */ +typedef unsigned char BYTE; + +/* These types MUST be 16 bit */ +typedef short SHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types MUST be 16 bit or 32 bit */ +typedef int INT; +typedef unsigned int UINT; + +/* These types MUST be 32 bit */ +typedef long LONG; +typedef unsigned long DWORD; + +#endif + +#endif diff --git a/stm/flash.c b/stm/flash.c new file mode 100644 index 000000000..15dcea9f0 --- /dev/null +++ b/stm/flash.c @@ -0,0 +1,109 @@ +#include +#include + +/* Base address of the Flash sectors */ +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */ + +static uint32_t GetSector(uint32_t Address); + +void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { + // unlock + FLASH_Unlock(); + + // Clear pending flags (if any) + FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | + FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); + + // Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by word + if (FLASH_EraseSector(GetSector(flash_dest), VoltageRange_3) != FLASH_COMPLETE) { + /* Error occurred while sector erase. + User can add here some code to deal with this error */ + return; + } + + /* Program the user Flash area word by word ********************************/ + + for (int i = 0; i < num_word32; i++) { + if (FLASH_ProgramWord(flash_dest, *src) == FLASH_COMPLETE) + { + flash_dest += 4; + src += 1; + } + else + { + /* Error occurred while writing data in Flash memory. + User can add here some code to deal with this error */ + return; + } + } + + // lock + FLASH_Lock(); +} + +/** + * @brief Gets the sector of a given address + * @param None + * @retval The sector of a given address + */ +static uint32_t GetSector(uint32_t Address) +{ + uint32_t sector = 0; + + if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0)) + { + sector = FLASH_Sector_0; + } + else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1)) + { + sector = FLASH_Sector_1; + } + else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2)) + { + sector = FLASH_Sector_2; + } + else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3)) + { + sector = FLASH_Sector_3; + } + else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4)) + { + sector = FLASH_Sector_4; + } + else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5)) + { + sector = FLASH_Sector_5; + } + else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6)) + { + sector = FLASH_Sector_6; + } + else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7)) + { + sector = FLASH_Sector_7; + } + else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8)) + { + sector = FLASH_Sector_8; + } + else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9)) + { + sector = FLASH_Sector_9; + } + else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10)) + { + sector = FLASH_Sector_10; + } + return sector; +} diff --git a/stm/font_petme128_8x8.h b/stm/font_petme128_8x8.h new file mode 100644 index 000000000..923348ecc --- /dev/null +++ b/stm/font_petme128_8x8.h @@ -0,0 +1,98 @@ +const uint8_t font_petme128_8x8[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 32= + 0x00,0x00,0x00,0x4f,0x4f,0x00,0x00,0x00, // 33=! + 0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, // 34=" + 0x14,0x7f,0x7f,0x14,0x14,0x7f,0x7f,0x14, // 35=# + 0x00,0x24,0x2e,0x6b,0x6b,0x3a,0x12,0x00, // 36=$ + 0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00, // 37=% + 0x00,0x32,0x7f,0x4d,0x4d,0x77,0x72,0x50, // 38=& + 0x00,0x00,0x00,0x04,0x06,0x03,0x01,0x00, // 39=' + 0x00,0x00,0x1c,0x3e,0x63,0x41,0x00,0x00, // 40=( + 0x00,0x00,0x41,0x63,0x3e,0x1c,0x00,0x00, // 41=) + 0x08,0x2a,0x3e,0x1c,0x1c,0x3e,0x2a,0x08, // 42=* + 0x00,0x08,0x08,0x3e,0x3e,0x08,0x08,0x00, // 43=+ + 0x00,0x00,0x80,0xe0,0x60,0x00,0x00,0x00, // 44=, + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, // 45=- + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, // 46=. + 0x00,0x40,0x60,0x30,0x18,0x0c,0x06,0x02, // 47=/ + 0x00,0x3e,0x7f,0x49,0x45,0x7f,0x3e,0x00, // 48=0 + 0x00,0x40,0x44,0x7f,0x7f,0x40,0x40,0x00, // 49=1 + 0x00,0x62,0x73,0x51,0x49,0x4f,0x46,0x00, // 50=2 + 0x00,0x22,0x63,0x49,0x49,0x7f,0x36,0x00, // 51=3 + 0x00,0x18,0x18,0x14,0x16,0x7f,0x7f,0x10, // 52=4 + 0x00,0x27,0x67,0x45,0x45,0x7d,0x39,0x00, // 53=5 + 0x00,0x3e,0x7f,0x49,0x49,0x7b,0x32,0x00, // 54=6 + 0x00,0x03,0x03,0x79,0x7d,0x07,0x03,0x00, // 55=7 + 0x00,0x36,0x7f,0x49,0x49,0x7f,0x36,0x00, // 56=8 + 0x00,0x26,0x6f,0x49,0x49,0x7f,0x3e,0x00, // 57=9 + 0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x00, // 58=: + 0x00,0x00,0x80,0xe4,0x64,0x00,0x00,0x00, // 59=; + 0x00,0x08,0x1c,0x36,0x63,0x41,0x41,0x00, // 60=< + 0x00,0x14,0x14,0x14,0x14,0x14,0x14,0x00, // 61== + 0x00,0x41,0x41,0x63,0x36,0x1c,0x08,0x00, // 62=> + 0x00,0x02,0x03,0x51,0x59,0x0f,0x06,0x00, // 63=? + 0x00,0x3e,0x7f,0x41,0x4d,0x4f,0x2e,0x00, // 64=@ + 0x00,0x7c,0x7e,0x0b,0x0b,0x7e,0x7c,0x00, // 65=A + 0x00,0x7f,0x7f,0x49,0x49,0x7f,0x36,0x00, // 66=B + 0x00,0x3e,0x7f,0x41,0x41,0x63,0x22,0x00, // 67=C + 0x00,0x7f,0x7f,0x41,0x63,0x3e,0x1c,0x00, // 68=D + 0x00,0x7f,0x7f,0x49,0x49,0x41,0x41,0x00, // 69=E + 0x00,0x7f,0x7f,0x09,0x09,0x01,0x01,0x00, // 70=F + 0x00,0x3e,0x7f,0x41,0x49,0x7b,0x3a,0x00, // 71=G + 0x00,0x7f,0x7f,0x08,0x08,0x7f,0x7f,0x00, // 72=H + 0x00,0x00,0x41,0x7f,0x7f,0x41,0x00,0x00, // 73=I + 0x00,0x20,0x60,0x41,0x7f,0x3f,0x01,0x00, // 74=J + 0x00,0x7f,0x7f,0x1c,0x36,0x63,0x41,0x00, // 75=K + 0x00,0x7f,0x7f,0x40,0x40,0x40,0x40,0x00, // 76=L + 0x00,0x7f,0x7f,0x06,0x0c,0x06,0x7f,0x7f, // 77=M + 0x00,0x7f,0x7f,0x0e,0x1c,0x7f,0x7f,0x00, // 78=N + 0x00,0x3e,0x7f,0x41,0x41,0x7f,0x3e,0x00, // 79=O + 0x00,0x7f,0x7f,0x09,0x09,0x0f,0x06,0x00, // 80=P + 0x00,0x1e,0x3f,0x21,0x61,0x7f,0x5e,0x00, // 81=Q + 0x00,0x7f,0x7f,0x19,0x39,0x6f,0x46,0x00, // 82=R + 0x00,0x26,0x6f,0x49,0x49,0x7b,0x32,0x00, // 83=S + 0x00,0x01,0x01,0x7f,0x7f,0x01,0x01,0x00, // 84=T + 0x00,0x3f,0x7f,0x40,0x40,0x7f,0x3f,0x00, // 85=U + 0x00,0x1f,0x3f,0x60,0x60,0x3f,0x1f,0x00, // 86=V + 0x00,0x7f,0x7f,0x30,0x18,0x30,0x7f,0x7f, // 87=W + 0x00,0x63,0x77,0x1c,0x1c,0x77,0x63,0x00, // 88=X + 0x00,0x07,0x0f,0x78,0x78,0x0f,0x07,0x00, // 89=Y + 0x00,0x61,0x71,0x59,0x4d,0x47,0x43,0x00, // 90=Z + 0x00,0x00,0x7f,0x7f,0x41,0x41,0x00,0x00, // 91=[ + 0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0x40, // 92='\' + 0x00,0x00,0x41,0x41,0x7f,0x7f,0x00,0x00, // 93=] + 0x00,0x08,0x0c,0x06,0x06,0x0c,0x08,0x00, // 94=^ + 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, // 95=_ + 0x00,0x00,0x01,0x03,0x06,0x04,0x00,0x00, // 96=` + 0x00,0x20,0x74,0x54,0x54,0x7c,0x78,0x00, // 97=a + 0x00,0x7f,0x7f,0x44,0x44,0x7c,0x38,0x00, // 98=b + 0x00,0x38,0x7c,0x44,0x44,0x6c,0x28,0x00, // 99=c + 0x00,0x38,0x7c,0x44,0x44,0x7f,0x7f,0x00, // 100=d + 0x00,0x38,0x7c,0x54,0x54,0x5c,0x58,0x00, // 101=e + 0x00,0x08,0x7e,0x7f,0x09,0x03,0x02,0x00, // 102=f + 0x00,0x98,0xbc,0xa4,0xa4,0xfc,0x7c,0x00, // 103=g + 0x00,0x7f,0x7f,0x04,0x04,0x7c,0x78,0x00, // 104=h + 0x00,0x00,0x00,0x7d,0x7d,0x00,0x00,0x00, // 105=i + 0x00,0x40,0xc0,0x80,0x80,0xfd,0x7d,0x00, // 106=j + 0x00,0x7f,0x7f,0x30,0x38,0x6c,0x44,0x00, // 107=k + 0x00,0x00,0x41,0x7f,0x7f,0x40,0x00,0x00, // 108=l + 0x00,0x7c,0x7c,0x18,0x30,0x18,0x7c,0x7c, // 109=m + 0x00,0x7c,0x7c,0x04,0x04,0x7c,0x78,0x00, // 110=n + 0x00,0x38,0x7c,0x44,0x44,0x7c,0x38,0x00, // 111=o + 0x00,0xfc,0xfc,0x24,0x24,0x3c,0x18,0x00, // 112=p + 0x00,0x18,0x3c,0x24,0x24,0xfc,0xfc,0x00, // 113=q + 0x00,0x7c,0x7c,0x04,0x04,0x0c,0x08,0x00, // 114=r + 0x00,0x48,0x5c,0x54,0x54,0x74,0x20,0x00, // 115=s + 0x04,0x04,0x3f,0x7f,0x44,0x64,0x20,0x00, // 116=t + 0x00,0x3c,0x7c,0x40,0x40,0x7c,0x3c,0x00, // 117=u + 0x00,0x1c,0x3c,0x60,0x60,0x3c,0x1c,0x00, // 118=v + 0x00,0x1c,0x7c,0x30,0x18,0x30,0x7c,0x1c, // 119=w + 0x00,0x44,0x6c,0x38,0x38,0x6c,0x44,0x00, // 120=x + 0x00,0x9c,0xbc,0xa0,0xa0,0xfc,0x7c,0x00, // 121=y + 0x00,0x44,0x64,0x74,0x5c,0x4c,0x44,0x00, // 122=z + 0x00,0x08,0x08,0x3e,0x77,0x41,0x41,0x00, // 123={ + 0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00, // 124=| + 0x00,0x41,0x41,0x77,0x3e,0x08,0x08,0x00, // 125=} + 0x00,0x02,0x03,0x01,0x03,0x02,0x03,0x01, // 126=~ + 0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55, // 127 +}; diff --git a/stm/lib/core_cm4.h b/stm/lib/core_cm4.h new file mode 100644 index 000000000..024302e4a --- /dev/null +++ b/stm/lib/core_cm4.h @@ -0,0 +1,1757 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V3.01 + * @date 22. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x01) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1 + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0 + #endif + #else + #define __FPU_USED 0 + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ +#include /* Compiler specific SIMD Intrinsics */ + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000 + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0 + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24]; + __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24]; + __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24]; + __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24]; + __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56]; + __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644]; + __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5]; + __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Registers Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Registers Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9 /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8 /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __O union + { + __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864]; + __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15]; + __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15]; + __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29]; + __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43]; + __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6]; + __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1]; + __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1]; + __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1]; + __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2]; + __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55]; + __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131]; + __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759]; + __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1]; + __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39]; + __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8]; + __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1]; + __IO uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IO uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IO uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __I uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __I uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register */ +#define FPU_FPCCR_ASPEN_Pos 31 /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30 /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8 /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6 /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5 /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4 /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3 /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1 /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0 /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL << FPU_FPCCR_LSPACT_Pos) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register */ +#define FPU_FPCAR_ADDRESS_Pos 3 /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register */ +#define FPU_FPDSCR_AHP_Pos 26 /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25 /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24 /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22 /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28 /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24 /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20 /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16 /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12 /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8 /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4 /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0 /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL << FPU_MVFR0_A_SIMD_registers_Pos) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28 /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24 /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4 /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0 /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL << FPU_MVFR1_FtZ_mode_Pos) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register */ +#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** \brief Set Priority Grouping + + The function sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** \brief Get Priority Grouping + + The function reads the priority grouping field from the NVIC Interrupt Controller. + + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ +} + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ +/* NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); enable interrupt */ + NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */ +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Get Active Interrupt + + The function reads the active register in NVIC and returns the active bit. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ + else { + NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ + else { + return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief Encode Priority + + The function encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. + + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + return ( + ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | + ((SubPriority & ((1 << (SubPriorityBits )) - 1))) + ); +} + + +/** \brief Decode Priority + + The function decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. + + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; + SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; + + *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); + *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** \brief ITM Send Character + + The function transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + + \param [in] ch Character to transmit. + + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ + (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0].u32 == 0); + ITM->PORT[0].u8 = (uint8_t) ch; + } + return (ch); +} + + +/** \brief ITM Receive Character + + The function inputs a character via the external variable \ref ITM_RxBuffer. + + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) { + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** \brief ITM Check Character + + The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) { + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { + return (0); /* no character available */ + } else { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/stm/lib/core_cm4_simd.h b/stm/lib/core_cm4_simd.h new file mode 100644 index 000000000..b5140073f --- /dev/null +++ b/stm/lib/core_cm4_simd.h @@ -0,0 +1,649 @@ +/**************************************************************************//** + * @file core_cm4_simd.h + * @brief CMSIS Cortex-M4 SIMD Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM4_SIMD_H +#define __CORE_CM4_SIMD_H + + +/******************************************************************************* + * Hardware Abstraction Layer + ******************************************************************************/ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +#include + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +#include + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SMLALD(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +#define __SMLALDX(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((uint64_t)(ARG3) >> 32), __ARG3_L = (uint32_t)((uint64_t)(ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SMLSLD(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +#define __SMLSLDX(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __ARG1 = (ARG1), __ARG2 = (ARG2), __ARG3_H = (uint32_t)((ARG3) >> 32), __ARG3_L = (uint32_t)((ARG3) & 0xFFFFFFFFUL); \ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (__ARG3_L), "=r" (__ARG3_H) : "r" (__ARG1), "r" (__ARG2), "0" (__ARG3_L), "1" (__ARG3_H) ); \ + (uint64_t)(((uint64_t)__ARG3_H << 32) | __ARG3_L); \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + + +/*------ CM4 SIMD Intrinsics -----------------------------------------------------*/ +/* not yet supported */ +/*-- End CM4 SIMD Intrinsics -----------------------------------------------------*/ + + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CORE_CM4_SIMD_H */ + +#ifdef __cplusplus +} +#endif diff --git a/stm/lib/core_cmFunc.h b/stm/lib/core_cmFunc.h new file mode 100644 index 000000000..adb07b5d3 --- /dev/null +++ b/stm/lib/core_cmFunc.h @@ -0,0 +1,616 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) ); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) ); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/stm/lib/core_cmInstr.h b/stm/lib/core_cmInstr.h new file mode 100644 index 000000000..624c175fd --- /dev/null +++ b/stm/lib/core_cmInstr.h @@ -0,0 +1,618 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + uint32_t result; + + __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + + __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); + return(op1); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint8_t result; + + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint16_t result; + + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint8_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/stm/lib/stm32f4xx.h b/stm/lib/stm32f4xx.h new file mode 100644 index 000000000..082a18e72 --- /dev/null +++ b/stm/lib/stm32f4xx.h @@ -0,0 +1,7155 @@ +/** + ****************************************************************************** + * @file stm32f4xx.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer Header File. + * This file contains all the peripheral register's definitions, bits + * definitions and memory mapping for STM32F4xx devices. + * + * The file is the unique include file that the application programmer + * is using in the C source code, usually in main.c. This file contains: + * - Configuration section that allows to select: + * - The device used in the target application + * - To use or not the peripheral’s drivers in application code(i.e. + * code will be based on direct access to peripheral’s registers + * rather than drivers API), this option is controlled by + * "#define USE_STDPERIPH_DRIVER" + * - To change few application-specific parameters such as the HSE + * crystal frequency + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral’s registers hardware + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx + * @{ + */ + +#ifndef __STM32F4xx_H +#define __STM32F4xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Library_configuration_section + * @{ + */ + +/* Uncomment the line below according to the target STM32 device used in your + application + */ + +#if !defined (STM32F4XX) && !defined (STM32F40XX) && !defined (STM32F427X) + /* #define STM32F40XX */ /*!< STM32F40xx/41xx Devices */ + /* #define STM32F427X */ /*!< STM32F427x/437x Devices*/ +#endif + + +/* Tip: To avoid modifying this file each time you need to switch between these + devices, you can define the device in your toolchain compiler preprocessor. + */ + +#if !defined (STM32F4XX) && !defined (STM32F40XX) && !defined (STM32F427X) + #error "Please select first the target STM32F4xx device used in your application (in stm32f4xx.h file)" +#endif + +#if !defined (USE_STDPERIPH_DRIVER) +/** + * @brief Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ + /*#define USE_STDPERIPH_DRIVER */ +#endif /* USE_STDPERIPH_DRIVER */ + +/** + * @brief In the following line adjust the value of External High Speed oscillator (HSE) + used in your application + + Tip: To avoid modifying this file each time you need to use different HSE, you + can define the HSE value in your toolchain compiler preprocessor. + */ + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +/** + * @brief In the following line adjust the External High Speed oscillator (HSE) Startup + Timeout value + */ +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500) /*!< Time out for HSE start up */ +#endif /* HSE_STARTUP_TIMEOUT */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief STM32F4XX Standard Peripherals Library version number V1.1.0 + */ +#define __STM32F4XX_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32F4XX_STDPERIPH_VERSION_SUB1 (0x01) /*!< [23:16] sub1 version */ +#define __STM32F4XX_STDPERIPH_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __STM32F4XX_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32F4XX_STDPERIPH_VERSION ((__STM32F4XX_STDPERIPH_VERSION_MAIN << 24)\ + |(__STM32F4XX_STDPERIPH_VERSION_SUB1 << 16)\ + |(__STM32F4XX_STDPERIPH_VERSION_SUB2 << 8)\ + |(__STM32F4XX_STDPERIPH_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief Configuration of the Cortex-M4 Processor and Core Peripherals + */ +#define __CM4_REV 0x0001 /*!< Core revision r0p1 */ +#define __MPU_PRESENT 1 /*!< STM32F4XX provides an MPU */ +#define __NVIC_PRIO_BITS 4 /*!< STM32F4XX uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1 /*!< FPU present */ + +/** + * @brief STM32F4XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum IRQn +{ +/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1, ADC2 and ADC3 global Interrupts */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break interrupt and TIM9 global interrupt */ + TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global interrupt */ + TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FSMC_IRQn = 48, /*!< FSMC global Interrupt */ + SDIO_IRQn = 49, /*!< SDIO global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ + CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ + CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ + CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ + OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ + OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ + OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ + OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ + DCMI_IRQn = 78, /*!< DCMI global interrupt */ + CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */ + HASH_RNG_IRQn = 80, /*!< Hash and Rng global interrupt */ + +#ifdef STM32F40XX + FPU_IRQn = 81 /*!< FPU global interrupt */ +#endif /* STM32F40XX */ + +#ifdef STM32F427X + FPU_IRQn = 81, /*!< FPU global interrupt */ + UART7_IRQn = 82, /*!< UART7 global interrupt */ + UART8_IRQn = 83, /*!< UART8 global interrupt */ + SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ + SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ + SPI6_IRQn = 86 /*!< SPI6 global Interrupt */ +#endif /* STM32F427X */ + +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */ +#include "system_stm32f4xx.h" +#include + +/** @addtogroup Exported_types + * @{ + */ +/*!< STM32F10x Standard Peripheral Library old types (maintained for legacy purpose) */ +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; + +typedef const int32_t sc32; /*!< Read Only */ +typedef const int16_t sc16; /*!< Read Only */ +typedef const int8_t sc8; /*!< Read Only */ + +typedef __IO int32_t vs32; +typedef __IO int16_t vs16; +typedef __IO int8_t vs8; + +typedef __I int32_t vsc32; /*!< Read Only */ +typedef __I int16_t vsc16; /*!< Read Only */ +typedef __I int8_t vsc8; /*!< Read Only */ + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef const uint32_t uc32; /*!< Read Only */ +typedef const uint16_t uc16; /*!< Read Only */ +typedef const uint8_t uc8; /*!< Read Only */ + +typedef __IO uint32_t vu32; +typedef __IO uint16_t vu16; +typedef __IO uint8_t vu8; + +typedef __I uint32_t vuc32; /*!< Read Only */ +typedef __I uint16_t vuc16; /*!< Read Only */ +typedef __I uint8_t vuc8; /*!< Read Only */ + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; + +/** + * @} + */ + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t SR; /*!< ADC status register, Address offset: 0x00 */ + __IO uint32_t CR1; /*!< ADC control register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< ADC control register 2, Address offset: 0x08 */ + __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x0C */ + __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x10 */ + __IO uint32_t JOFR1; /*!< ADC injected channel data offset register 1, Address offset: 0x14 */ + __IO uint32_t JOFR2; /*!< ADC injected channel data offset register 2, Address offset: 0x18 */ + __IO uint32_t JOFR3; /*!< ADC injected channel data offset register 3, Address offset: 0x1C */ + __IO uint32_t JOFR4; /*!< ADC injected channel data offset register 4, Address offset: 0x20 */ + __IO uint32_t HTR; /*!< ADC watchdog higher threshold register, Address offset: 0x24 */ + __IO uint32_t LTR; /*!< ADC watchdog lower threshold register, Address offset: 0x28 */ + __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x2C */ + __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x30 */ + __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x34 */ + __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x38*/ + __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x3C */ + __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x40 */ + __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x44 */ + __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x48 */ + __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x4C */ +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1 base address + 0x300 */ + __IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1 base address + 0x304 */ + __IO uint32_t CDR; /*!< ADC common regular data register for dual + AND triple modes, Address offset: ADC1 base address + 0x308 */ +} ADC_Common_TypeDef; + + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */ + __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */ + __IO uint32_t TDLR; /*!< CAN mailbox data low register */ + __IO uint32_t TDHR; /*!< CAN mailbox data high register */ +} CAN_TxMailBox_TypeDef; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */ + __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */ + __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */ + __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */ +} CAN_FIFOMailBox_TypeDef; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; /*!< CAN Filter bank register 1 */ + __IO uint32_t FR2; /*!< CAN Filter bank register 1 */ +} CAN_FilterRegister_TypeDef; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */ + __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */ + __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */ + __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */ + __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ + __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */ + __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ + uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */ + CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */ + CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */ + uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */ + __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */ + __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */ + uint32_t RESERVED2; /*!< Reserved, 0x208 */ + __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */ + uint32_t RESERVED3; /*!< Reserved, 0x210 */ + __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */ + uint32_t RESERVED4; /*!< Reserved, 0x218 */ + __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */ + uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */ + CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */ +} CAN_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ +} CRC_TypeDef; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ +} DAC_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZ; /*!< Debug MCU APB1 freeze register, Address offset: 0x08 */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x0C */ +}DBGMCU_TypeDef; + +/** + * @brief DCMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ + __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA stream x configuration register */ + __IO uint32_t NDTR; /*!< DMA stream x number of data register */ + __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ + __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ + __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ + __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ +} DMA_Stream_TypeDef; + +typedef struct +{ + __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ + __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ + __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ + __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ +} DMA_TypeDef; + +/** + * @brief Ethernet MAC + */ + +typedef struct +{ + __IO uint32_t MACCR; + __IO uint32_t MACFFR; + __IO uint32_t MACHTHR; + __IO uint32_t MACHTLR; + __IO uint32_t MACMIIAR; + __IO uint32_t MACMIIDR; + __IO uint32_t MACFCR; + __IO uint32_t MACVLANTR; /* 8 */ + uint32_t RESERVED0[2]; + __IO uint32_t MACRWUFFR; /* 11 */ + __IO uint32_t MACPMTCSR; + uint32_t RESERVED1[2]; + __IO uint32_t MACSR; /* 15 */ + __IO uint32_t MACIMR; + __IO uint32_t MACA0HR; + __IO uint32_t MACA0LR; + __IO uint32_t MACA1HR; + __IO uint32_t MACA1LR; + __IO uint32_t MACA2HR; + __IO uint32_t MACA2LR; + __IO uint32_t MACA3HR; + __IO uint32_t MACA3LR; /* 24 */ + uint32_t RESERVED2[40]; + __IO uint32_t MMCCR; /* 65 */ + __IO uint32_t MMCRIR; + __IO uint32_t MMCTIR; + __IO uint32_t MMCRIMR; + __IO uint32_t MMCTIMR; /* 69 */ + uint32_t RESERVED3[14]; + __IO uint32_t MMCTGFSCCR; /* 84 */ + __IO uint32_t MMCTGFMSCCR; + uint32_t RESERVED4[5]; + __IO uint32_t MMCTGFCR; + uint32_t RESERVED5[10]; + __IO uint32_t MMCRFCECR; + __IO uint32_t MMCRFAECR; + uint32_t RESERVED6[10]; + __IO uint32_t MMCRGUFCR; + uint32_t RESERVED7[334]; + __IO uint32_t PTPTSCR; + __IO uint32_t PTPSSIR; + __IO uint32_t PTPTSHR; + __IO uint32_t PTPTSLR; + __IO uint32_t PTPTSHUR; + __IO uint32_t PTPTSLUR; + __IO uint32_t PTPTSAR; + __IO uint32_t PTPTTHR; + __IO uint32_t PTPTTLR; + __IO uint32_t RESERVED8; + __IO uint32_t PTPTSSR; + uint32_t RESERVED9[565]; + __IO uint32_t DMABMR; + __IO uint32_t DMATPDR; + __IO uint32_t DMARPDR; + __IO uint32_t DMARDLAR; + __IO uint32_t DMATDLAR; + __IO uint32_t DMASR; + __IO uint32_t DMAOMR; + __IO uint32_t DMAIER; + __IO uint32_t DMAMFBOCR; + __IO uint32_t DMARSWTR; + uint32_t RESERVED10[8]; + __IO uint32_t DMACHTDR; + __IO uint32_t DMACHRDR; + __IO uint32_t DMACHTBAR; + __IO uint32_t DMACHRBAR; +} ETH_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ + __IO uint32_t EMR; /*!< EXTI Event mask register, Address offset: 0x04 */ + __IO uint32_t RTSR; /*!< EXTI Rising trigger selection register, Address offset: 0x08 */ + __IO uint32_t FTSR; /*!< EXTI Falling trigger selection register, Address offset: 0x0C */ + __IO uint32_t SWIER; /*!< EXTI Software interrupt event register, Address offset: 0x10 */ + __IO uint32_t PR; /*!< EXTI Pending register, Address offset: 0x14 */ +} EXTI_TypeDef; + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x04 */ + __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x10 */ + __IO uint32_t OPTCR; /*!< FLASH option control register , Address offset: 0x14 */ + __IO uint32_t OPTCR1; /*!< FLASH option control register 1, Address offset: 0x18 */ +} FLASH_TypeDef; + +/** + * @brief Flexible Static Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FSMC_Bank1_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FSMC_Bank1E_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank2 + */ + +typedef struct +{ + __IO uint32_t PCR2; /*!< NAND Flash control register 2, Address offset: 0x60 */ + __IO uint32_t SR2; /*!< NAND Flash FIFO status and interrupt register 2, Address offset: 0x64 */ + __IO uint32_t PMEM2; /*!< NAND Flash Common memory space timing register 2, Address offset: 0x68 */ + __IO uint32_t PATT2; /*!< NAND Flash Attribute memory space timing register 2, Address offset: 0x6C */ + uint32_t RESERVED0; /*!< Reserved, 0x70 */ + __IO uint32_t ECCR2; /*!< NAND Flash ECC result registers 2, Address offset: 0x74 */ +} FSMC_Bank2_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR3; /*!< NAND Flash control register 3, Address offset: 0x80 */ + __IO uint32_t SR3; /*!< NAND Flash FIFO status and interrupt register 3, Address offset: 0x84 */ + __IO uint32_t PMEM3; /*!< NAND Flash Common memory space timing register 3, Address offset: 0x88 */ + __IO uint32_t PATT3; /*!< NAND Flash Attribute memory space timing register 3, Address offset: 0x8C */ + uint32_t RESERVED0; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR3; /*!< NAND Flash ECC result registers 3, Address offset: 0x94 */ +} FSMC_Bank3_TypeDef; + +/** + * @brief Flexible Static Memory Controller Bank4 + */ + +typedef struct +{ + __IO uint32_t PCR4; /*!< PC Card control register 4, Address offset: 0xA0 */ + __IO uint32_t SR4; /*!< PC Card FIFO status and interrupt register 4, Address offset: 0xA4 */ + __IO uint32_t PMEM4; /*!< PC Card Common memory space timing register 4, Address offset: 0xA8 */ + __IO uint32_t PATT4; /*!< PC Card Attribute memory space timing register 4, Address offset: 0xAC */ + __IO uint32_t PIO4; /*!< PC Card I/O space timing register 4, Address offset: 0xB0 */ +} FSMC_Bank4_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ + __IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ +} GPIO_TypeDef; + +/** + * @brief System configuration controller + */ + +typedef struct +{ + __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */ + __IO uint32_t PMC; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + uint32_t RESERVED[2]; /*!< Reserved, 0x18-0x1C */ + __IO uint32_t CMPCR; /*!< SYSCFG Compensation cell control register, Address offset: 0x20 */ +} SYSCFG_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint16_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + uint16_t RESERVED0; /*!< Reserved, 0x02 */ + __IO uint16_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint16_t OAR1; /*!< I2C Own address register 1, Address offset: 0x08 */ + uint16_t RESERVED2; /*!< Reserved, 0x0A */ + __IO uint16_t OAR2; /*!< I2C Own address register 2, Address offset: 0x0C */ + uint16_t RESERVED3; /*!< Reserved, 0x0E */ + __IO uint16_t DR; /*!< I2C Data register, Address offset: 0x10 */ + uint16_t RESERVED4; /*!< Reserved, 0x12 */ + __IO uint16_t SR1; /*!< I2C Status register 1, Address offset: 0x14 */ + uint16_t RESERVED5; /*!< Reserved, 0x16 */ + __IO uint16_t SR2; /*!< I2C Status register 2, Address offset: 0x18 */ + uint16_t RESERVED6; /*!< Reserved, 0x1A */ + __IO uint16_t CCR; /*!< I2C Clock control register, Address offset: 0x1C */ + uint16_t RESERVED7; /*!< Reserved, 0x1E */ + __IO uint16_t TRISE; /*!< I2C TRISE register, Address offset: 0x20 */ + uint16_t RESERVED8; /*!< Reserved, 0x22 */ + __IO uint16_t FLTR; /*!< I2C FLTR register, Address offset: 0x24 */ + uint16_t RESERVED9; /*!< Reserved, 0x26 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ +} IWDG_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< PWR power control register, Address offset: 0x00 */ + __IO uint32_t CSR; /*!< PWR power control/status register, Address offset: 0x04 */ +} PWR_TypeDef; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ + __IO uint32_t CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */ + uint32_t RESERVED0; /*!< Reserved, 0x1C */ + __IO uint32_t APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x28-0x2C */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */ + uint32_t RESERVED2; /*!< Reserved, 0x3C */ + __IO uint32_t APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */ + uint32_t RESERVED3[2]; /*!< Reserved, 0x48-0x4C */ + __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */ + __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */ + __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */ + uint32_t RESERVED4; /*!< Reserved, 0x5C */ + __IO uint32_t APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */ + __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */ + uint32_t RESERVED5[2]; /*!< Reserved, 0x68-0x6C */ + __IO uint32_t BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + uint32_t RESERVED6[2]; /*!< Reserved, 0x78-0x7C */ + __IO uint32_t SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */ + __IO uint32_t PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */ + +#ifdef STM32F427X + uint32_t RESERVED7; /*!< Reserved, 0x88 */ + __IO uint32_t DCKCFGR; /*!< RCC Dedicated Clocks configuration register, Address offset: 0x8C */ +#endif /* STM32F427X */ + +} RCC_TypeDef; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + __IO uint32_t CALIBR; /*!< RTC calibration register, Address offset: 0x18 */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAFCR; /*!< RTC tamper and alternate function configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR;/*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR;/*!< RTC alarm B sub second register, Address offset: 0x48 */ + uint32_t RESERVED7; /*!< Reserved, 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 1, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ +} RTC_TypeDef; + +/** + * @brief SD host Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDIO power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDI clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDIO argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDIO command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDIO command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDIO response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDIO response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDIO response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDIO response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDIO data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDIO data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDIO data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDIO data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDIO status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDIO interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDIO mask register, Address offset: 0x3C */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */ + __I uint32_t FIFOCNT; /*!< SDIO FIFO counter register, Address offset: 0x48 */ + uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */ + __IO uint32_t FIFO; /*!< SDIO data FIFO register, Address offset: 0x80 */ +} SDIO_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint16_t CR1; /*!< SPI control register 1 (not used in I2S mode), Address offset: 0x00 */ + uint16_t RESERVED0; /*!< Reserved, 0x02 */ + __IO uint16_t CR2; /*!< SPI control register 2, Address offset: 0x04 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint16_t SR; /*!< SPI status register, Address offset: 0x08 */ + uint16_t RESERVED2; /*!< Reserved, 0x0A */ + __IO uint16_t DR; /*!< SPI data register, Address offset: 0x0C */ + uint16_t RESERVED3; /*!< Reserved, 0x0E */ + __IO uint16_t CRCPR; /*!< SPI CRC polynomial register (not used in I2S mode), Address offset: 0x10 */ + uint16_t RESERVED4; /*!< Reserved, 0x12 */ + __IO uint16_t RXCRCR; /*!< SPI RX CRC register (not used in I2S mode), Address offset: 0x14 */ + uint16_t RESERVED5; /*!< Reserved, 0x16 */ + __IO uint16_t TXCRCR; /*!< SPI TX CRC register (not used in I2S mode), Address offset: 0x18 */ + uint16_t RESERVED6; /*!< Reserved, 0x1A */ + __IO uint16_t I2SCFGR; /*!< SPI_I2S configuration register, Address offset: 0x1C */ + uint16_t RESERVED7; /*!< Reserved, 0x1E */ + __IO uint16_t I2SPR; /*!< SPI_I2S prescaler register, Address offset: 0x20 */ + uint16_t RESERVED8; /*!< Reserved, 0x22 */ +} SPI_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint16_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + uint16_t RESERVED0; /*!< Reserved, 0x02 */ + __IO uint16_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint16_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + uint16_t RESERVED2; /*!< Reserved, 0x0A */ + __IO uint16_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + uint16_t RESERVED3; /*!< Reserved, 0x0E */ + __IO uint16_t SR; /*!< TIM status register, Address offset: 0x10 */ + uint16_t RESERVED4; /*!< Reserved, 0x12 */ + __IO uint16_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + uint16_t RESERVED5; /*!< Reserved, 0x16 */ + __IO uint16_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + uint16_t RESERVED6; /*!< Reserved, 0x1A */ + __IO uint16_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + uint16_t RESERVED7; /*!< Reserved, 0x1E */ + __IO uint16_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + uint16_t RESERVED8; /*!< Reserved, 0x22 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint16_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + uint16_t RESERVED9; /*!< Reserved, 0x2A */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint16_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + uint16_t RESERVED10; /*!< Reserved, 0x32 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint16_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + uint16_t RESERVED11; /*!< Reserved, 0x46 */ + __IO uint16_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + uint16_t RESERVED12; /*!< Reserved, 0x4A */ + __IO uint16_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + uint16_t RESERVED13; /*!< Reserved, 0x4E */ + __IO uint16_t OR; /*!< TIM option register, Address offset: 0x50 */ + uint16_t RESERVED14; /*!< Reserved, 0x52 */ +} TIM_TypeDef; + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint16_t SR; /*!< USART Status register, Address offset: 0x00 */ + uint16_t RESERVED0; /*!< Reserved, 0x02 */ + __IO uint16_t DR; /*!< USART Data register, Address offset: 0x04 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint16_t BRR; /*!< USART Baud rate register, Address offset: 0x08 */ + uint16_t RESERVED2; /*!< Reserved, 0x0A */ + __IO uint16_t CR1; /*!< USART Control register 1, Address offset: 0x0C */ + uint16_t RESERVED3; /*!< Reserved, 0x0E */ + __IO uint16_t CR2; /*!< USART Control register 2, Address offset: 0x10 */ + uint16_t RESERVED4; /*!< Reserved, 0x12 */ + __IO uint16_t CR3; /*!< USART Control register 3, Address offset: 0x14 */ + uint16_t RESERVED5; /*!< Reserved, 0x16 */ + __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x18 */ + uint16_t RESERVED6; /*!< Reserved, 0x1A */ +} USART_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + +/** + * @brief Crypto Processor + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CRYP control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< CRYP status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< CRYP data input register, Address offset: 0x08 */ + __IO uint32_t DOUT; /*!< CRYP data output register, Address offset: 0x0C */ + __IO uint32_t DMACR; /*!< CRYP DMA control register, Address offset: 0x10 */ + __IO uint32_t IMSCR; /*!< CRYP interrupt mask set/clear register, Address offset: 0x14 */ + __IO uint32_t RISR; /*!< CRYP raw interrupt status register, Address offset: 0x18 */ + __IO uint32_t MISR; /*!< CRYP masked interrupt status register, Address offset: 0x1C */ + __IO uint32_t K0LR; /*!< CRYP key left register 0, Address offset: 0x20 */ + __IO uint32_t K0RR; /*!< CRYP key right register 0, Address offset: 0x24 */ + __IO uint32_t K1LR; /*!< CRYP key left register 1, Address offset: 0x28 */ + __IO uint32_t K1RR; /*!< CRYP key right register 1, Address offset: 0x2C */ + __IO uint32_t K2LR; /*!< CRYP key left register 2, Address offset: 0x30 */ + __IO uint32_t K2RR; /*!< CRYP key right register 2, Address offset: 0x34 */ + __IO uint32_t K3LR; /*!< CRYP key left register 3, Address offset: 0x38 */ + __IO uint32_t K3RR; /*!< CRYP key right register 3, Address offset: 0x3C */ + __IO uint32_t IV0LR; /*!< CRYP initialization vector left-word register 0, Address offset: 0x40 */ + __IO uint32_t IV0RR; /*!< CRYP initialization vector right-word register 0, Address offset: 0x44 */ + __IO uint32_t IV1LR; /*!< CRYP initialization vector left-word register 1, Address offset: 0x48 */ + __IO uint32_t IV1RR; /*!< CRYP initialization vector right-word register 1, Address offset: 0x4C */ + __IO uint32_t CSGCMCCM0R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 0, Address offset: 0x50 */ + __IO uint32_t CSGCMCCM1R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 1, Address offset: 0x54 */ + __IO uint32_t CSGCMCCM2R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 2, Address offset: 0x58 */ + __IO uint32_t CSGCMCCM3R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 3, Address offset: 0x5C */ + __IO uint32_t CSGCMCCM4R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 4, Address offset: 0x60 */ + __IO uint32_t CSGCMCCM5R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 5, Address offset: 0x64 */ + __IO uint32_t CSGCMCCM6R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 6, Address offset: 0x68 */ + __IO uint32_t CSGCMCCM7R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 7, Address offset: 0x6C */ + __IO uint32_t CSGCM0R; /*!< CRYP GCM/GMAC context swap register 0, Address offset: 0x70 */ + __IO uint32_t CSGCM1R; /*!< CRYP GCM/GMAC context swap register 1, Address offset: 0x74 */ + __IO uint32_t CSGCM2R; /*!< CRYP GCM/GMAC context swap register 2, Address offset: 0x78 */ + __IO uint32_t CSGCM3R; /*!< CRYP GCM/GMAC context swap register 3, Address offset: 0x7C */ + __IO uint32_t CSGCM4R; /*!< CRYP GCM/GMAC context swap register 4, Address offset: 0x80 */ + __IO uint32_t CSGCM5R; /*!< CRYP GCM/GMAC context swap register 5, Address offset: 0x84 */ + __IO uint32_t CSGCM6R; /*!< CRYP GCM/GMAC context swap register 6, Address offset: 0x88 */ + __IO uint32_t CSGCM7R; /*!< CRYP GCM/GMAC context swap register 7, Address offset: 0x8C */ +} CRYP_TypeDef; + +/** + * @brief HASH + */ + +typedef struct +{ + __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */ + __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */ + __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */ + __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */ + __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */ + __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */ + uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */ + __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */ +} HASH_TypeDef; + +/** + * @brief HASH_DIGEST + */ + +typedef struct +{ + __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */ +} HASH_DIGEST_TypeDef; + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ +} RNG_TypeDef; + +/** + * @} + */ + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define FLASH_BASE ((uint32_t)0x08000000) /*!< FLASH(up to 1 MB) base address in the alias region */ +#define CCMDATARAM_BASE ((uint32_t)0x10000000) /*!< CCM(core coupled memory) data RAM(64 KB) base address in the alias region */ +#define SRAM1_BASE ((uint32_t)0x20000000) /*!< SRAM1(112 KB) base address in the alias region */ +#define SRAM2_BASE ((uint32_t)0x2001C000) /*!< SRAM2(16 KB) base address in the alias region */ +#define SRAM3_BASE ((uint32_t)0x20020000) /*!< SRAM3(64 KB) base address in the alias region */ +#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */ +#define BKPSRAM_BASE ((uint32_t)0x40024000) /*!< Backup SRAM(4 KB) base address in the alias region */ +#define FSMC_R_BASE ((uint32_t)0xA0000000) /*!< FSMC registers base address */ + +#define CCMDATARAM_BB_BASE ((uint32_t)0x12000000) /*!< CCM(core coupled memory) data RAM(64 KB) base address in the bit-band region */ +#define SRAM1_BB_BASE ((uint32_t)0x22000000) /*!< SRAM1(112 KB) base address in the bit-band region */ +#define SRAM2_BB_BASE ((uint32_t)0x2201C000) /*!< SRAM2(16 KB) base address in the bit-band region */ +#define SRAM3_BB_BASE ((uint32_t)0x22020000) /*!< SRAM3(64 KB) base address in the bit-band region */ +#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */ +#define BKPSRAM_BB_BASE ((uint32_t)0x42024000) /*!< Backup SRAM(4 KB) base address in the bit-band region */ + +/* Legacy defines */ +#define SRAM_BASE SRAM1_BASE +#define SRAM_BB_BASE SRAM1_BB_BASE + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000) + +/*!< APB1 peripherals */ +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400) +#define TIM12_BASE (APB1PERIPH_BASE + 0x1800) +#define TIM13_BASE (APB1PERIPH_BASE + 0x1C00) +#define TIM14_BASE (APB1PERIPH_BASE + 0x2000) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000) +#define I2S2ext_BASE (APB1PERIPH_BASE + 0x3400) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00) +#define I2S3ext_BASE (APB1PERIPH_BASE + 0x4000) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800) +#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400) +#define CAN2_BASE (APB1PERIPH_BASE + 0x6800) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400) +#define UART7_BASE (APB1PERIPH_BASE + 0x7800) +#define UART8_BASE (APB1PERIPH_BASE + 0x7C00) + +/*!< APB2 peripherals */ +#define TIM1_BASE (APB2PERIPH_BASE + 0x0000) +#define TIM8_BASE (APB2PERIPH_BASE + 0x0400) +#define USART1_BASE (APB2PERIPH_BASE + 0x1000) +#define USART6_BASE (APB2PERIPH_BASE + 0x1400) +#define ADC1_BASE (APB2PERIPH_BASE + 0x2000) +#define ADC2_BASE (APB2PERIPH_BASE + 0x2100) +#define ADC3_BASE (APB2PERIPH_BASE + 0x2200) +#define ADC_BASE (APB2PERIPH_BASE + 0x2300) +#define SDIO_BASE (APB2PERIPH_BASE + 0x2C00) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000) +#define SPI4_BASE (APB2PERIPH_BASE + 0x3400) +#define SYSCFG_BASE (APB2PERIPH_BASE + 0x3800) +#define EXTI_BASE (APB2PERIPH_BASE + 0x3C00) +#define TIM9_BASE (APB2PERIPH_BASE + 0x4000) +#define TIM10_BASE (APB2PERIPH_BASE + 0x4400) +#define TIM11_BASE (APB2PERIPH_BASE + 0x4800) +#define SPI5_BASE (APB2PERIPH_BASE + 0x5000) +#define SPI6_BASE (APB2PERIPH_BASE + 0x5400) + +/*!< AHB1 peripherals */ +#define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000) +#define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400) +#define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800) +#define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00) +#define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000) +#define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400) +#define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800) +#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00) +#define GPIOI_BASE (AHB1PERIPH_BASE + 0x2000) + +#define CRC_BASE (AHB1PERIPH_BASE + 0x3000) +#define RCC_BASE (AHB1PERIPH_BASE + 0x3800) +#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x3C00) +#define DMA1_BASE (AHB1PERIPH_BASE + 0x6000) +#define DMA1_Stream0_BASE (DMA1_BASE + 0x010) +#define DMA1_Stream1_BASE (DMA1_BASE + 0x028) +#define DMA1_Stream2_BASE (DMA1_BASE + 0x040) +#define DMA1_Stream3_BASE (DMA1_BASE + 0x058) +#define DMA1_Stream4_BASE (DMA1_BASE + 0x070) +#define DMA1_Stream5_BASE (DMA1_BASE + 0x088) +#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0) +#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8) +#define DMA2_BASE (AHB1PERIPH_BASE + 0x6400) +#define DMA2_Stream0_BASE (DMA2_BASE + 0x010) +#define DMA2_Stream1_BASE (DMA2_BASE + 0x028) +#define DMA2_Stream2_BASE (DMA2_BASE + 0x040) +#define DMA2_Stream3_BASE (DMA2_BASE + 0x058) +#define DMA2_Stream4_BASE (DMA2_BASE + 0x070) +#define DMA2_Stream5_BASE (DMA2_BASE + 0x088) +#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0) +#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8) +#define ETH_BASE (AHB1PERIPH_BASE + 0x8000) +#define ETH_MAC_BASE (ETH_BASE) +#define ETH_MMC_BASE (ETH_BASE + 0x0100) +#define ETH_PTP_BASE (ETH_BASE + 0x0700) +#define ETH_DMA_BASE (ETH_BASE + 0x1000) + +/*!< AHB2 peripherals */ +#define DCMI_BASE (AHB2PERIPH_BASE + 0x50000) +#define CRYP_BASE (AHB2PERIPH_BASE + 0x60000) +#define HASH_BASE (AHB2PERIPH_BASE + 0x60400) +#define HASH_DIGEST_BASE (AHB2PERIPH_BASE + 0x60710) +#define RNG_BASE (AHB2PERIPH_BASE + 0x60800) + +/*!< FSMC Bankx registers base address */ +#define FSMC_Bank1_R_BASE (FSMC_R_BASE + 0x0000) +#define FSMC_Bank1E_R_BASE (FSMC_R_BASE + 0x0104) +#define FSMC_Bank2_R_BASE (FSMC_R_BASE + 0x0060) +#define FSMC_Bank3_R_BASE (FSMC_R_BASE + 0x0080) +#define FSMC_Bank4_R_BASE (FSMC_R_BASE + 0x00A0) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE ((uint32_t )0xE0042000) + +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG ((WWDG_TypeDef *) WWDG_BASE) +#define IWDG ((IWDG_TypeDef *) IWDG_BASE) +#define I2S2ext ((SPI_TypeDef *) I2S2ext_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define I2S3ext ((SPI_TypeDef *) I2S3ext_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define CAN1 ((CAN_TypeDef *) CAN1_BASE) +#define CAN2 ((CAN_TypeDef *) CAN2_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC ((DAC_TypeDef *) DAC_BASE) +#define UART7 ((USART_TypeDef *) UART7_BASE) +#define UART8 ((USART_TypeDef *) UART8_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define USART6 ((USART_TypeDef *) USART6_BASE) +#define ADC ((ADC_Common_TypeDef *) ADC_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define SDIO ((SDIO_TypeDef *) SDIO_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define SPI4 ((SPI_TypeDef *) SPI4_BASE) +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define TIM9 ((TIM_TypeDef *) TIM9_BASE) +#define TIM10 ((TIM_TypeDef *) TIM10_BASE) +#define TIM11 ((TIM_TypeDef *) TIM11_BASE) +#define SPI5 ((SPI_TypeDef *) SPI5_BASE) +#define SPI6 ((SPI_TypeDef *) SPI6_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define GPIOI ((GPIO_TypeDef *) GPIOI_BASE) + +#define CRC ((CRC_TypeDef *) CRC_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) +#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) +#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) +#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) +#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) +#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) +#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) +#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) +#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) +#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) +#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) +#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) +#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) +#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) +#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) +#define ETH ((ETH_TypeDef *) ETH_BASE) +#define DCMI ((DCMI_TypeDef *) DCMI_BASE) +#define CRYP ((CRYP_TypeDef *) CRYP_BASE) +#define HASH ((HASH_TypeDef *) HASH_BASE) +#define HASH_DIGEST ((HASH_DIGEST_TypeDef *) HASH_DIGEST_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) +#define FSMC_Bank1 ((FSMC_Bank1_TypeDef *) FSMC_Bank1_R_BASE) +#define FSMC_Bank1E ((FSMC_Bank1E_TypeDef *) FSMC_Bank1E_R_BASE) +#define FSMC_Bank2 ((FSMC_Bank2_TypeDef *) FSMC_Bank2_R_BASE) +#define FSMC_Bank3 ((FSMC_Bank3_TypeDef *) FSMC_Bank3_R_BASE) +#define FSMC_Bank4 ((FSMC_Bank4_TypeDef *) FSMC_Bank4_R_BASE) +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ +/******************** Bit definition for ADC_SR register ********************/ +#define ADC_SR_AWD ((uint8_t)0x01) /*!
© COPYRIGHT 2013 STMicroelectronics
+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_CONF_H +#define __STM32F4xx_CONF_H + +/* Includes ------------------------------------------------------------------*/ +/* Uncomment the line below to enable peripheral header file inclusion */ +//#include "stm32f4xx_adc.h" +//#include "stm32f4xx_can.h" +//#include "stm32f4xx_crc.h" +//#include "stm32f4xx_cryp.h" +//#include "stm32f4xx_dac.h" +//#include "stm32f4xx_dbgmcu.h" +//#include "stm32f4xx_dcmi.h" +//#include "stm32f4xx_dma.h" +//#include "stm32f4xx_exti.h" +//#include "stm32f4xx_flash.h" +//#include "stm32f4xx_fsmc.h" +//#include "stm32f4xx_hash.h" +//#include "stm32f4xx_gpio.h" +//#include "stm32f4xx_i2c.h" +//#include "stm32f4xx_iwdg.h" +//#include "stm32f4xx_pwr.h" +//#include "stm32f4xx_rcc.h" +//#include "stm32f4xx_rng.h" +//#include "stm32f4xx_rtc.h" +//#include "stm32f4xx_sdio.h" +//#include "stm32f4xx_spi.h" +//#include "stm32f4xx_syscfg.h" +//#include "stm32f4xx_tim.h" +//#include "stm32f4xx_usart.h" +//#include "stm32f4xx_wwdg.h" +//#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* If an external clock source is used, then the value of the following define + should be set to the value of the external clock source, else, if no external + clock is used, keep this define commented */ +/*#define I2S_EXTERNAL_CLOCK_VAL 12288000 */ /* Value of the external clock in Hz */ + + +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +/* #define USE_FULL_ASSERT 1 */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#endif /* __STM32F4xx_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_dma.c b/stm/lib/stm32f4xx_dma.c new file mode 100644 index 000000000..856ec4bc3 --- /dev/null +++ b/stm/lib/stm32f4xx_dma.c @@ -0,0 +1,1302 @@ +/** + ****************************************************************************** + * @file stm32f4xx_dma.c + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file provides firmware functions to manage the following + * functionalities of the Direct Memory Access controller (DMA): + * + Initialization and Configuration + * + Data Counter + * + Double Buffer mode configuration and command + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + (#) Enable The DMA controller clock using RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA1, ENABLE) + function for DMA1 or using RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE) + function for DMA2. + + (#) Enable and configure the peripheral to be connected to the DMA Stream + (except for internal SRAM / FLASH memories: no initialization is + necessary). + + (#) For a given Stream, program the required configuration through following parameters: + Source and Destination addresses, Transfer Direction, Transfer size, Source and Destination + data formats, Circular or Normal mode, Stream Priority level, Source and Destination + Incrementation mode, FIFO mode and its Threshold (if needed), Burst + mode for Source and/or Destination (if needed) using the DMA_Init() function. + To avoid filling unneccessary fields, you can call DMA_StructInit() function + to initialize a given structure with default values (reset values), the modify + only necessary fields + (ie. Source and Destination addresses, Transfer size and Data Formats). + + (#) Enable the NVIC and the corresponding interrupt(s) using the function + DMA_ITConfig() if you need to use DMA interrupts. + + (#) Optionally, if the Circular mode is enabled, you can use the Double buffer mode by configuring + the second Memory address and the first Memory to be used through the function + DMA_DoubleBufferModeConfig(). Then enable the Double buffer mode through the function + DMA_DoubleBufferModeCmd(). These operations must be done before step 6. + + (#) Enable the DMA stream using the DMA_Cmd() function. + + (#) Activate the needed Stream Request using PPP_DMACmd() function for + any PPP peripheral except internal SRAM and FLASH (ie. SPI, USART ...) + The function allowing this operation is provided in each PPP peripheral + driver (ie. SPI_DMACmd for SPI peripheral). + Once the Stream is enabled, it is not possible to modify its configuration + unless the stream is stopped and disabled. + After enabling the Stream, it is advised to monitor the EN bit status using + the function DMA_GetCmdStatus(). In case of configuration errors or bus errors + this bit will remain reset and all transfers on this Stream will remain on hold. + + (#) Optionally, you can configure the number of data to be transferred + when the Stream is disabled (ie. after each Transfer Complete event + or when a Transfer Error occurs) using the function DMA_SetCurrDataCounter(). + And you can get the number of remaining data to be transferred using + the function DMA_GetCurrDataCounter() at run time (when the DMA Stream is + enabled and running). + + (#) To control DMA events you can use one of the following two methods: + (##) Check on DMA Stream flags using the function DMA_GetFlagStatus(). + (##) Use DMA interrupts through the function DMA_ITConfig() at initialization + phase and DMA_GetITStatus() function into interrupt routines in + communication phase. + [..] + After checking on a flag you should clear it using DMA_ClearFlag() + function. And after checking on an interrupt event you should + clear it using DMA_ClearITPendingBit() function. + + (#) Optionally, if Circular mode and Double Buffer mode are enabled, you can modify + the Memory Addresses using the function DMA_MemoryTargetConfig(). Make sure that + the Memory Address to be modified is not the one currently in use by DMA Stream. + This condition can be monitored using the function DMA_GetCurrentMemoryTarget(). + + (#) Optionally, Pause-Resume operations may be performed: + The DMA_Cmd() function may be used to perform Pause-Resume operation. + When a transfer is ongoing, calling this function to disable the + Stream will cause the transfer to be paused. All configuration registers + and the number of remaining data will be preserved. When calling again + this function to re-enable the Stream, the transfer will be resumed from + the point where it was paused. + + -@- Memory-to-Memory transfer is possible by setting the address of the memory into + the Peripheral registers. In this mode, Circular mode and Double Buffer mode + are not allowed. + + -@- The FIFO is used mainly to reduce bus usage and to allow data + packing/unpacking: it is possible to set different Data Sizes for + the Peripheral and the Memory (ie. you can set Half-Word data size + for the peripheral to access its data register and set Word data size + for the Memory to gain in access time. Each two Half-words will be + packed and written in a single access to a Word in the Memory). + + -@- When FIFO is disabled, it is not allowed to configure different + Data Sizes for Source and Destination. In this case the Peripheral + Data Size will be applied to both Source and Destination. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_conf.h" +#include "stm32f4xx_dma.h" +#include "stm32f4xx_rcc.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup DMA + * @brief DMA driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* Masks Definition */ +#define TRANSFER_IT_ENABLE_MASK (uint32_t)(DMA_SxCR_TCIE | DMA_SxCR_HTIE | \ + DMA_SxCR_TEIE | DMA_SxCR_DMEIE) + +#define DMA_Stream0_IT_MASK (uint32_t)(DMA_LISR_FEIF0 | DMA_LISR_DMEIF0 | \ + DMA_LISR_TEIF0 | DMA_LISR_HTIF0 | \ + DMA_LISR_TCIF0) + +#define DMA_Stream1_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK << 6) +#define DMA_Stream2_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK << 16) +#define DMA_Stream3_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK << 22) +#define DMA_Stream4_IT_MASK (uint32_t)(DMA_Stream0_IT_MASK | (uint32_t)0x20000000) +#define DMA_Stream5_IT_MASK (uint32_t)(DMA_Stream1_IT_MASK | (uint32_t)0x20000000) +#define DMA_Stream6_IT_MASK (uint32_t)(DMA_Stream2_IT_MASK | (uint32_t)0x20000000) +#define DMA_Stream7_IT_MASK (uint32_t)(DMA_Stream3_IT_MASK | (uint32_t)0x20000000) +#define TRANSFER_IT_MASK (uint32_t)0x0F3C0F3C +#define HIGH_ISR_MASK (uint32_t)0x20000000 +#define RESERVED_MASK (uint32_t)0x0F7D0F7D + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + + +/** @defgroup DMA_Private_Functions + * @{ + */ + +/** @defgroup DMA_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to initialize the DMA Stream source + and destination addresses, incrementation and data sizes, transfer direction, + buffer size, circular/normal mode selection, memory-to-memory mode selection + and Stream priority value. + [..] + The DMA_Init() function follows the DMA configuration procedures as described in + reference manual (RM0090) except the first point: waiting on EN bit to be reset. + This condition should be checked by user application using the function DMA_GetCmdStatus() + before calling the DMA_Init() function. + +@endverbatim + * @{ + */ + +/** + * @brief Deinitialize the DMAy Streamx registers to their default reset values. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @retval None + */ +void DMA_DeInit(DMA_Stream_TypeDef* DMAy_Streamx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + + /* Disable the selected DMAy Streamx */ + DMAy_Streamx->CR &= ~((uint32_t)DMA_SxCR_EN); + + /* Reset DMAy Streamx control register */ + DMAy_Streamx->CR = 0; + + /* Reset DMAy Streamx Number of Data to Transfer register */ + DMAy_Streamx->NDTR = 0; + + /* Reset DMAy Streamx peripheral address register */ + DMAy_Streamx->PAR = 0; + + /* Reset DMAy Streamx memory 0 address register */ + DMAy_Streamx->M0AR = 0; + + /* Reset DMAy Streamx memory 1 address register */ + DMAy_Streamx->M1AR = 0; + + /* Reset DMAy Streamx FIFO control register */ + DMAy_Streamx->FCR = (uint32_t)0x00000021; + + /* Reset interrupt pending bits for the selected stream */ + if (DMAy_Streamx == DMA1_Stream0) + { + /* Reset interrupt pending bits for DMA1 Stream0 */ + DMA1->LIFCR = DMA_Stream0_IT_MASK; + } + else if (DMAy_Streamx == DMA1_Stream1) + { + /* Reset interrupt pending bits for DMA1 Stream1 */ + DMA1->LIFCR = DMA_Stream1_IT_MASK; + } + else if (DMAy_Streamx == DMA1_Stream2) + { + /* Reset interrupt pending bits for DMA1 Stream2 */ + DMA1->LIFCR = DMA_Stream2_IT_MASK; + } + else if (DMAy_Streamx == DMA1_Stream3) + { + /* Reset interrupt pending bits for DMA1 Stream3 */ + DMA1->LIFCR = DMA_Stream3_IT_MASK; + } + else if (DMAy_Streamx == DMA1_Stream4) + { + /* Reset interrupt pending bits for DMA1 Stream4 */ + DMA1->HIFCR = DMA_Stream4_IT_MASK; + } + else if (DMAy_Streamx == DMA1_Stream5) + { + /* Reset interrupt pending bits for DMA1 Stream5 */ + DMA1->HIFCR = DMA_Stream5_IT_MASK; + } + else if (DMAy_Streamx == DMA1_Stream6) + { + /* Reset interrupt pending bits for DMA1 Stream6 */ + DMA1->HIFCR = (uint32_t)DMA_Stream6_IT_MASK; + } + else if (DMAy_Streamx == DMA1_Stream7) + { + /* Reset interrupt pending bits for DMA1 Stream7 */ + DMA1->HIFCR = DMA_Stream7_IT_MASK; + } + else if (DMAy_Streamx == DMA2_Stream0) + { + /* Reset interrupt pending bits for DMA2 Stream0 */ + DMA2->LIFCR = DMA_Stream0_IT_MASK; + } + else if (DMAy_Streamx == DMA2_Stream1) + { + /* Reset interrupt pending bits for DMA2 Stream1 */ + DMA2->LIFCR = DMA_Stream1_IT_MASK; + } + else if (DMAy_Streamx == DMA2_Stream2) + { + /* Reset interrupt pending bits for DMA2 Stream2 */ + DMA2->LIFCR = DMA_Stream2_IT_MASK; + } + else if (DMAy_Streamx == DMA2_Stream3) + { + /* Reset interrupt pending bits for DMA2 Stream3 */ + DMA2->LIFCR = DMA_Stream3_IT_MASK; + } + else if (DMAy_Streamx == DMA2_Stream4) + { + /* Reset interrupt pending bits for DMA2 Stream4 */ + DMA2->HIFCR = DMA_Stream4_IT_MASK; + } + else if (DMAy_Streamx == DMA2_Stream5) + { + /* Reset interrupt pending bits for DMA2 Stream5 */ + DMA2->HIFCR = DMA_Stream5_IT_MASK; + } + else if (DMAy_Streamx == DMA2_Stream6) + { + /* Reset interrupt pending bits for DMA2 Stream6 */ + DMA2->HIFCR = DMA_Stream6_IT_MASK; + } + else + { + if (DMAy_Streamx == DMA2_Stream7) + { + /* Reset interrupt pending bits for DMA2 Stream7 */ + DMA2->HIFCR = DMA_Stream7_IT_MASK; + } + } +} + +/** + * @brief Initializes the DMAy Streamx according to the specified parameters in + * the DMA_InitStruct structure. + * @note Before calling this function, it is recommended to check that the Stream + * is actually disabled using the function DMA_GetCmdStatus(). + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_InitStruct: pointer to a DMA_InitTypeDef structure that contains + * the configuration information for the specified DMA Stream. + * @retval None + */ +void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_CHANNEL(DMA_InitStruct->DMA_Channel)); + assert_param(IS_DMA_DIRECTION(DMA_InitStruct->DMA_DIR)); + assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize)); + assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc)); + assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc)); + assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(DMA_InitStruct->DMA_PeripheralDataSize)); + assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitStruct->DMA_MemoryDataSize)); + assert_param(IS_DMA_MODE(DMA_InitStruct->DMA_Mode)); + assert_param(IS_DMA_PRIORITY(DMA_InitStruct->DMA_Priority)); + assert_param(IS_DMA_FIFO_MODE_STATE(DMA_InitStruct->DMA_FIFOMode)); + assert_param(IS_DMA_FIFO_THRESHOLD(DMA_InitStruct->DMA_FIFOThreshold)); + assert_param(IS_DMA_MEMORY_BURST(DMA_InitStruct->DMA_MemoryBurst)); + assert_param(IS_DMA_PERIPHERAL_BURST(DMA_InitStruct->DMA_PeripheralBurst)); + + /*------------------------- DMAy Streamx CR Configuration ------------------*/ + /* Get the DMAy_Streamx CR value */ + tmpreg = DMAy_Streamx->CR; + + /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ + tmpreg &= ((uint32_t)~(DMA_SxCR_CHSEL | DMA_SxCR_MBURST | DMA_SxCR_PBURST | \ + DMA_SxCR_PL | DMA_SxCR_MSIZE | DMA_SxCR_PSIZE | \ + DMA_SxCR_MINC | DMA_SxCR_PINC | DMA_SxCR_CIRC | \ + DMA_SxCR_DIR)); + + /* Configure DMAy Streamx: */ + /* Set CHSEL bits according to DMA_CHSEL value */ + /* Set DIR bits according to DMA_DIR value */ + /* Set PINC bit according to DMA_PeripheralInc value */ + /* Set MINC bit according to DMA_MemoryInc value */ + /* Set PSIZE bits according to DMA_PeripheralDataSize value */ + /* Set MSIZE bits according to DMA_MemoryDataSize value */ + /* Set CIRC bit according to DMA_Mode value */ + /* Set PL bits according to DMA_Priority value */ + /* Set MBURST bits according to DMA_MemoryBurst value */ + /* Set PBURST bits according to DMA_PeripheralBurst value */ + tmpreg |= DMA_InitStruct->DMA_Channel | DMA_InitStruct->DMA_DIR | + DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc | + DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize | + DMA_InitStruct->DMA_Mode | DMA_InitStruct->DMA_Priority | + DMA_InitStruct->DMA_MemoryBurst | DMA_InitStruct->DMA_PeripheralBurst; + + /* Write to DMAy Streamx CR register */ + DMAy_Streamx->CR = tmpreg; + + /*------------------------- DMAy Streamx FCR Configuration -----------------*/ + /* Get the DMAy_Streamx FCR value */ + tmpreg = DMAy_Streamx->FCR; + + /* Clear DMDIS and FTH bits */ + tmpreg &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); + + /* Configure DMAy Streamx FIFO: + Set DMDIS bits according to DMA_FIFOMode value + Set FTH bits according to DMA_FIFOThreshold value */ + tmpreg |= DMA_InitStruct->DMA_FIFOMode | DMA_InitStruct->DMA_FIFOThreshold; + + /* Write to DMAy Streamx CR */ + DMAy_Streamx->FCR = tmpreg; + + /*------------------------- DMAy Streamx NDTR Configuration ----------------*/ + /* Write to DMAy Streamx NDTR register */ + DMAy_Streamx->NDTR = DMA_InitStruct->DMA_BufferSize; + + /*------------------------- DMAy Streamx PAR Configuration -----------------*/ + /* Write to DMAy Streamx PAR */ + DMAy_Streamx->PAR = DMA_InitStruct->DMA_PeripheralBaseAddr; + + /*------------------------- DMAy Streamx M0AR Configuration ----------------*/ + /* Write to DMAy Streamx M0AR */ + DMAy_Streamx->M0AR = DMA_InitStruct->DMA_Memory0BaseAddr; +} + +/** + * @brief Fills each DMA_InitStruct member with its default value. + * @param DMA_InitStruct : pointer to a DMA_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct) +{ + /*-------------- Reset DMA init structure parameters values ----------------*/ + /* Initialize the DMA_Channel member */ + DMA_InitStruct->DMA_Channel = 0; + + /* Initialize the DMA_PeripheralBaseAddr member */ + DMA_InitStruct->DMA_PeripheralBaseAddr = 0; + + /* Initialize the DMA_Memory0BaseAddr member */ + DMA_InitStruct->DMA_Memory0BaseAddr = 0; + + /* Initialize the DMA_DIR member */ + DMA_InitStruct->DMA_DIR = DMA_DIR_PeripheralToMemory; + + /* Initialize the DMA_BufferSize member */ + DMA_InitStruct->DMA_BufferSize = 0; + + /* Initialize the DMA_PeripheralInc member */ + DMA_InitStruct->DMA_PeripheralInc = DMA_PeripheralInc_Disable; + + /* Initialize the DMA_MemoryInc member */ + DMA_InitStruct->DMA_MemoryInc = DMA_MemoryInc_Disable; + + /* Initialize the DMA_PeripheralDataSize member */ + DMA_InitStruct->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + + /* Initialize the DMA_MemoryDataSize member */ + DMA_InitStruct->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + + /* Initialize the DMA_Mode member */ + DMA_InitStruct->DMA_Mode = DMA_Mode_Normal; + + /* Initialize the DMA_Priority member */ + DMA_InitStruct->DMA_Priority = DMA_Priority_Low; + + /* Initialize the DMA_FIFOMode member */ + DMA_InitStruct->DMA_FIFOMode = DMA_FIFOMode_Disable; + + /* Initialize the DMA_FIFOThreshold member */ + DMA_InitStruct->DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; + + /* Initialize the DMA_MemoryBurst member */ + DMA_InitStruct->DMA_MemoryBurst = DMA_MemoryBurst_Single; + + /* Initialize the DMA_PeripheralBurst member */ + DMA_InitStruct->DMA_PeripheralBurst = DMA_PeripheralBurst_Single; +} + +/** + * @brief Enables or disables the specified DMAy Streamx. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param NewState: new state of the DMAy Streamx. + * This parameter can be: ENABLE or DISABLE. + * + * @note This function may be used to perform Pause-Resume operation. When a + * transfer is ongoing, calling this function to disable the Stream will + * cause the transfer to be paused. All configuration registers and the + * number of remaining data will be preserved. When calling again this + * function to re-enable the Stream, the transfer will be resumed from + * the point where it was paused. + * + * @note After configuring the DMA Stream (DMA_Init() function) and enabling the + * stream, it is recommended to check (or wait until) the DMA Stream is + * effectively enabled. A Stream may remain disabled if a configuration + * parameter is wrong. + * After disabling a DMA Stream, it is also recommended to check (or wait + * until) the DMA Stream is effectively disabled. If a Stream is disabled + * while a data transfer is ongoing, the current data will be transferred + * and the Stream will be effectively disabled only after the transfer of + * this single data is finished. + * + * @retval None + */ +void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DMAy Streamx by setting EN bit */ + DMAy_Streamx->CR |= (uint32_t)DMA_SxCR_EN; + } + else + { + /* Disable the selected DMAy Streamx by clearing EN bit */ + DMAy_Streamx->CR &= ~(uint32_t)DMA_SxCR_EN; + } +} + +/** + * @brief Configures, when the PINC (Peripheral Increment address mode) bit is + * set, if the peripheral address should be incremented with the data + * size (configured with PSIZE bits) or by a fixed offset equal to 4 + * (32-bit aligned addresses). + * + * @note This function has no effect if the Peripheral Increment mode is disabled. + * + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_Pincos: specifies the Peripheral increment offset size. + * This parameter can be one of the following values: + * @arg DMA_PINCOS_Psize: Peripheral address increment is done + * accordingly to PSIZE parameter. + * @arg DMA_PINCOS_WordAligned: Peripheral address increment offset is + * fixed to 4 (32-bit aligned addresses). + * @retval None + */ +void DMA_PeriphIncOffsetSizeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_Pincos) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_PINCOS_SIZE(DMA_Pincos)); + + /* Check the needed Peripheral increment offset */ + if(DMA_Pincos != DMA_PINCOS_Psize) + { + /* Configure DMA_SxCR_PINCOS bit with the input parameter */ + DMAy_Streamx->CR |= (uint32_t)DMA_SxCR_PINCOS; + } + else + { + /* Clear the PINCOS bit: Peripheral address incremented according to PSIZE */ + DMAy_Streamx->CR &= ~(uint32_t)DMA_SxCR_PINCOS; + } +} + +/** + * @brief Configures, when the DMAy Streamx is disabled, the flow controller for + * the next transactions (Peripheral or Memory). + * + * @note Before enabling this feature, check if the used peripheral supports + * the Flow Controller mode or not. + * + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_FlowCtrl: specifies the DMA flow controller. + * This parameter can be one of the following values: + * @arg DMA_FlowCtrl_Memory: DMAy_Streamx transactions flow controller is + * the DMA controller. + * @arg DMA_FlowCtrl_Peripheral: DMAy_Streamx transactions flow controller + * is the peripheral. + * @retval None + */ +void DMA_FlowControllerConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FlowCtrl) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_FLOW_CTRL(DMA_FlowCtrl)); + + /* Check the needed flow controller */ + if(DMA_FlowCtrl != DMA_FlowCtrl_Memory) + { + /* Configure DMA_SxCR_PFCTRL bit with the input parameter */ + DMAy_Streamx->CR |= (uint32_t)DMA_SxCR_PFCTRL; + } + else + { + /* Clear the PFCTRL bit: Memory is the flow controller */ + DMAy_Streamx->CR &= ~(uint32_t)DMA_SxCR_PFCTRL; + } +} +/** + * @} + */ + +/** @defgroup DMA_Group2 Data Counter functions + * @brief Data Counter functions + * +@verbatim + =============================================================================== + ##### Data Counter functions ##### + =============================================================================== + [..] + This subsection provides function allowing to configure and read the buffer size + (number of data to be transferred). + [..] + The DMA data counter can be written only when the DMA Stream is disabled + (ie. after transfer complete event). + [..] + The following function can be used to write the Stream data counter value: + (+) void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter); + -@- It is advised to use this function rather than DMA_Init() in situations + where only the Data buffer needs to be reloaded. + -@- If the Source and Destination Data Sizes are different, then the value + written in data counter, expressing the number of transfers, is relative + to the number of transfers from the Peripheral point of view. + ie. If Memory data size is Word, Peripheral data size is Half-Words, + then the value to be configured in the data counter is the number + of Half-Words to be transferred from/to the peripheral. + [..] + The DMA data counter can be read to indicate the number of remaining transfers for + the relative DMA Stream. This counter is decremented at the end of each data + transfer and when the transfer is complete: + (+) If Normal mode is selected: the counter is set to 0. + (+) If Circular mode is selected: the counter is reloaded with the initial value + (configured before enabling the DMA Stream) + [..] + The following function can be used to read the Stream data counter value: + (+) uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx); + +@endverbatim + * @{ + */ + +/** + * @brief Writes the number of data units to be transferred on the DMAy Streamx. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param Counter: Number of data units to be transferred (from 0 to 65535) + * Number of data items depends only on the Peripheral data format. + * + * @note If Peripheral data format is Bytes: number of data units is equal + * to total number of bytes to be transferred. + * + * @note If Peripheral data format is Half-Word: number of data units is + * equal to total number of bytes to be transferred / 2. + * + * @note If Peripheral data format is Word: number of data units is equal + * to total number of bytes to be transferred / 4. + * + * @note In Memory-to-Memory transfer mode, the memory buffer pointed by + * DMAy_SxPAR register is considered as Peripheral. + * + * @retval The number of remaining data units in the current DMAy Streamx transfer. + */ +void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + + /* Write the number of data units to be transferred */ + DMAy_Streamx->NDTR = (uint16_t)Counter; +} + +/** + * @brief Returns the number of remaining data units in the current DMAy Streamx transfer. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @retval The number of remaining data units in the current DMAy Streamx transfer. + */ +uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + + /* Return the number of remaining data units for DMAy Streamx */ + return ((uint16_t)(DMAy_Streamx->NDTR)); +} +/** + * @} + */ + +/** @defgroup DMA_Group3 Double Buffer mode functions + * @brief Double Buffer mode functions + * +@verbatim + =============================================================================== + ##### Double Buffer mode functions ##### + =============================================================================== + [..] + This subsection provides function allowing to configure and control the double + buffer mode parameters. + + [..] + The Double Buffer mode can be used only when Circular mode is enabled. + The Double Buffer mode cannot be used when transferring data from Memory to Memory. + + [..] + The Double Buffer mode allows to set two different Memory addresses from/to which + the DMA controller will access alternatively (after completing transfer to/from + target memory 0, it will start transfer to/from target memory 1). + This allows to reduce software overhead for double buffering and reduce the CPU + access time. + + [..] + Two functions must be called before calling the DMA_Init() function: + (+) void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, + uint32_t Memory1BaseAddr, uint32_t DMA_CurrentMemory); + (+) void DMA_DoubleBufferModeCmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState); + + [..] + DMA_DoubleBufferModeConfig() is called to configure the Memory 1 base address + and the first Memory target from/to which the transfer will start after + enabling the DMA Stream. Then DMA_DoubleBufferModeCmd() must be called + to enable the Double Buffer mode (or disable it when it should not be used). + + [..] + Two functions can be called dynamically when the transfer is ongoing (or when the DMA Stream is + stopped) to modify on of the target Memories addresses or to check wich Memory target is currently + used: + (+) void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, + uint32_t MemoryBaseAddr, uint32_t DMA_MemoryTarget); + (+) uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx); + + [..] + DMA_MemoryTargetConfig() can be called to modify the base address of one of + the two target Memories. + The Memory of which the base address will be modified must not be currently + be used by the DMA Stream (ie. if the DMA Stream is currently transferring + from Memory 1 then you can only modify base address of target Memory 0 and vice versa). + To check this condition, it is recommended to use the function DMA_GetCurrentMemoryTarget() which + returns the index of the Memory target currently in use by the DMA Stream. + +@endverbatim + * @{ + */ + +/** + * @brief Configures, when the DMAy Streamx is disabled, the double buffer mode + * and the current memory target. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param Memory1BaseAddr: the base address of the second buffer (Memory 1) + * @param DMA_CurrentMemory: specifies which memory will be first buffer for + * the transactions when the Stream will be enabled. + * This parameter can be one of the following values: + * @arg DMA_Memory_0: Memory 0 is the current buffer. + * @arg DMA_Memory_1: Memory 1 is the current buffer. + * + * @note Memory0BaseAddr is set by the DMA structure configuration in DMA_Init(). + * + * @retval None + */ +void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t Memory1BaseAddr, + uint32_t DMA_CurrentMemory) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_CURRENT_MEM(DMA_CurrentMemory)); + + if (DMA_CurrentMemory != DMA_Memory_0) + { + /* Set Memory 1 as current memory address */ + DMAy_Streamx->CR |= (uint32_t)(DMA_SxCR_CT); + } + else + { + /* Set Memory 0 as current memory address */ + DMAy_Streamx->CR &= ~(uint32_t)(DMA_SxCR_CT); + } + + /* Write to DMAy Streamx M1AR */ + DMAy_Streamx->M1AR = Memory1BaseAddr; +} + +/** + * @brief Enables or disables the double buffer mode for the selected DMA stream. + * @note This function can be called only when the DMA Stream is disabled. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param NewState: new state of the DMAy Streamx double buffer mode. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DMA_DoubleBufferModeCmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + /* Configure the Double Buffer mode */ + if (NewState != DISABLE) + { + /* Enable the Double buffer mode */ + DMAy_Streamx->CR |= (uint32_t)DMA_SxCR_DBM; + } + else + { + /* Disable the Double buffer mode */ + DMAy_Streamx->CR &= ~(uint32_t)DMA_SxCR_DBM; + } +} + +/** + * @brief Configures the Memory address for the next buffer transfer in double + * buffer mode (for dynamic use). This function can be called when the + * DMA Stream is enabled and when the transfer is ongoing. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param MemoryBaseAddr: The base address of the target memory buffer + * @param DMA_MemoryTarget: Next memory target to be used. + * This parameter can be one of the following values: + * @arg DMA_Memory_0: To use the memory address 0 + * @arg DMA_Memory_1: To use the memory address 1 + * + * @note It is not allowed to modify the Base Address of a target Memory when + * this target is involved in the current transfer. ie. If the DMA Stream + * is currently transferring to/from Memory 1, then it not possible to + * modify Base address of Memory 1, but it is possible to modify Base + * address of Memory 0. + * To know which Memory is currently used, you can use the function + * DMA_GetCurrentMemoryTarget(). + * + * @retval None + */ +void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t MemoryBaseAddr, + uint32_t DMA_MemoryTarget) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_CURRENT_MEM(DMA_MemoryTarget)); + + /* Check the Memory target to be configured */ + if (DMA_MemoryTarget != DMA_Memory_0) + { + /* Write to DMAy Streamx M1AR */ + DMAy_Streamx->M1AR = MemoryBaseAddr; + } + else + { + /* Write to DMAy Streamx M0AR */ + DMAy_Streamx->M0AR = MemoryBaseAddr; + } +} + +/** + * @brief Returns the current memory target used by double buffer transfer. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @retval The memory target number: 0 for Memory0 or 1 for Memory1. + */ +uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + + /* Get the current memory target */ + if ((DMAy_Streamx->CR & DMA_SxCR_CT) != 0) + { + /* Current memory buffer used is Memory 1 */ + tmp = 1; + } + else + { + /* Current memory buffer used is Memory 0 */ + tmp = 0; + } + return tmp; +} +/** + * @} + */ + +/** @defgroup DMA_Group4 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the DMA enable status + (+) Check the FIFO status + (+) Configure the DMA Interrupts sources and check or clear the flags or + pending bits status. + + [..] + (#) DMA Enable status: + After configuring the DMA Stream (DMA_Init() function) and enabling + the stream, it is recommended to check (or wait until) the DMA Stream + is effectively enabled. A Stream may remain disabled if a configuration + parameter is wrong. After disabling a DMA Stream, it is also recommended + to check (or wait until) the DMA Stream is effectively disabled. + If a Stream is disabled while a data transfer is ongoing, the current + data will be transferred and the Stream will be effectively disabled + only after this data transfer completion. + To monitor this state it is possible to use the following function: + (++) FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx); + + (#) FIFO Status: + It is possible to monitor the FIFO status when a transfer is ongoing + using the following function: + (++) uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx); + + (#) DMA Interrupts and Flags: + The user should identify which mode will be used in his application + to manage the DMA controller events: Polling mode or Interrupt mode. + + *** Polling Mode *** + ==================== + [..] + Each DMA stream can be managed through 4 event Flags: + (x : DMA Stream number ) + (#) DMA_FLAG_FEIFx : to indicate that a FIFO Mode Transfer Error event occurred. + (#) DMA_FLAG_DMEIFx : to indicate that a Direct Mode Transfer Error event occurred. + (#) DMA_FLAG_TEIFx : to indicate that a Transfer Error event occurred. + (#) DMA_FLAG_HTIFx : to indicate that a Half-Transfer Complete event occurred. + (#) DMA_FLAG_TCIFx : to indicate that a Transfer Complete event occurred . + [..] + In this Mode it is advised to use the following functions: + (+) FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG); + (+) void DMA_ClearFlag(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG); + + *** Interrupt Mode *** + ====================== + [..] + Each DMA Stream can be managed through 4 Interrupts: + + *** Interrupt Source *** + ======================== + [..] + (#) DMA_IT_FEIFx : specifies the interrupt source for the FIFO Mode Transfer Error event. + (#) DMA_IT_DMEIFx : specifies the interrupt source for the Direct Mode Transfer Error event. + (#) DMA_IT_TEIFx : specifies the interrupt source for the Transfer Error event. + (#) DMA_IT_HTIFx : specifies the interrupt source for the Half-Transfer Complete event. + (#) DMA_IT_TCIFx : specifies the interrupt source for the a Transfer Complete event. + [..] + In this Mode it is advised to use the following functions: + (+) void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState); + (+) ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT); + (+) void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT); + +@endverbatim + * @{ + */ + +/** + * @brief Returns the status of EN bit for the specified DMAy Streamx. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * + * @note After configuring the DMA Stream (DMA_Init() function) and enabling + * the stream, it is recommended to check (or wait until) the DMA Stream + * is effectively enabled. A Stream may remain disabled if a configuration + * parameter is wrong. + * After disabling a DMA Stream, it is also recommended to check (or wait + * until) the DMA Stream is effectively disabled. If a Stream is disabled + * while a data transfer is ongoing, the current data will be transferred + * and the Stream will be effectively disabled only after the transfer + * of this single data is finished. + * + * @retval Current state of the DMAy Streamx (ENABLE or DISABLE). + */ +FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx) +{ + FunctionalState state = DISABLE; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + + if ((DMAy_Streamx->CR & (uint32_t)DMA_SxCR_EN) != 0) + { + /* The selected DMAy Streamx EN bit is set (DMA is still transferring) */ + state = ENABLE; + } + else + { + /* The selected DMAy Streamx EN bit is cleared (DMA is disabled and + all transfers are complete) */ + state = DISABLE; + } + return state; +} + +/** + * @brief Returns the current DMAy Streamx FIFO filled level. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @retval The FIFO filling state. + * - DMA_FIFOStatus_Less1QuarterFull: when FIFO is less than 1 quarter-full + * and not empty. + * - DMA_FIFOStatus_1QuarterFull: if more than 1 quarter-full. + * - DMA_FIFOStatus_HalfFull: if more than 1 half-full. + * - DMA_FIFOStatus_3QuartersFull: if more than 3 quarters-full. + * - DMA_FIFOStatus_Empty: when FIFO is empty + * - DMA_FIFOStatus_Full: when FIFO is full + */ +uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + + /* Get the FIFO level bits */ + tmpreg = (uint32_t)((DMAy_Streamx->FCR & DMA_SxFCR_FS)); + + return tmpreg; +} + +/** + * @brief Checks whether the specified DMAy Streamx flag is set or not. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg DMA_FLAG_TCIFx: Streamx transfer complete flag + * @arg DMA_FLAG_HTIFx: Streamx half transfer complete flag + * @arg DMA_FLAG_TEIFx: Streamx transfer error flag + * @arg DMA_FLAG_DMEIFx: Streamx direct mode error flag + * @arg DMA_FLAG_FEIFx: Streamx FIFO error flag + * Where x can be 0 to 7 to select the DMA Stream. + * @retval The new state of DMA_FLAG (SET or RESET). + */ +FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG) +{ + FlagStatus bitstatus = RESET; + DMA_TypeDef* DMAy; + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_GET_FLAG(DMA_FLAG)); + + /* Determine the DMA to which belongs the stream */ + if (DMAy_Streamx < DMA2_Stream0) + { + /* DMAy_Streamx belongs to DMA1 */ + DMAy = DMA1; + } + else + { + /* DMAy_Streamx belongs to DMA2 */ + DMAy = DMA2; + } + + /* Check if the flag is in HISR or LISR */ + if ((DMA_FLAG & HIGH_ISR_MASK) != (uint32_t)RESET) + { + /* Get DMAy HISR register value */ + tmpreg = DMAy->HISR; + } + else + { + /* Get DMAy LISR register value */ + tmpreg = DMAy->LISR; + } + + /* Mask the reserved bits */ + tmpreg &= (uint32_t)RESERVED_MASK; + + /* Check the status of the specified DMA flag */ + if ((tmpreg & DMA_FLAG) != (uint32_t)RESET) + { + /* DMA_FLAG is set */ + bitstatus = SET; + } + else + { + /* DMA_FLAG is reset */ + bitstatus = RESET; + } + + /* Return the DMA_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Streamx's pending flags. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_FLAG: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DMA_FLAG_TCIFx: Streamx transfer complete flag + * @arg DMA_FLAG_HTIFx: Streamx half transfer complete flag + * @arg DMA_FLAG_TEIFx: Streamx transfer error flag + * @arg DMA_FLAG_DMEIFx: Streamx direct mode error flag + * @arg DMA_FLAG_FEIFx: Streamx FIFO error flag + * Where x can be 0 to 7 to select the DMA Stream. + * @retval None + */ +void DMA_ClearFlag(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG) +{ + DMA_TypeDef* DMAy; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_CLEAR_FLAG(DMA_FLAG)); + + /* Determine the DMA to which belongs the stream */ + if (DMAy_Streamx < DMA2_Stream0) + { + /* DMAy_Streamx belongs to DMA1 */ + DMAy = DMA1; + } + else + { + /* DMAy_Streamx belongs to DMA2 */ + DMAy = DMA2; + } + + /* Check if LIFCR or HIFCR register is targeted */ + if ((DMA_FLAG & HIGH_ISR_MASK) != (uint32_t)RESET) + { + /* Set DMAy HIFCR register clear flag bits */ + DMAy->HIFCR = (uint32_t)(DMA_FLAG & RESERVED_MASK); + } + else + { + /* Set DMAy LIFCR register clear flag bits */ + DMAy->LIFCR = (uint32_t)(DMA_FLAG & RESERVED_MASK); + } +} + +/** + * @brief Enables or disables the specified DMAy Streamx interrupts. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_IT: specifies the DMA interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer complete interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @arg DMA_IT_FE: FIFO error interrupt mask + * @param NewState: new state of the specified DMA interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_CONFIG_IT(DMA_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + /* Check if the DMA_IT parameter contains a FIFO interrupt */ + if ((DMA_IT & DMA_IT_FE) != 0) + { + if (NewState != DISABLE) + { + /* Enable the selected DMA FIFO interrupts */ + DMAy_Streamx->FCR |= (uint32_t)DMA_IT_FE; + } + else + { + /* Disable the selected DMA FIFO interrupts */ + DMAy_Streamx->FCR &= ~(uint32_t)DMA_IT_FE; + } + } + + /* Check if the DMA_IT parameter contains a Transfer interrupt */ + if (DMA_IT != DMA_IT_FE) + { + if (NewState != DISABLE) + { + /* Enable the selected DMA transfer interrupts */ + DMAy_Streamx->CR |= (uint32_t)(DMA_IT & TRANSFER_IT_ENABLE_MASK); + } + else + { + /* Disable the selected DMA transfer interrupts */ + DMAy_Streamx->CR &= ~(uint32_t)(DMA_IT & TRANSFER_IT_ENABLE_MASK); + } + } +} + +/** + * @brief Checks whether the specified DMAy Streamx interrupt has occurred or not. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_IT: specifies the DMA interrupt source to check. + * This parameter can be one of the following values: + * @arg DMA_IT_TCIFx: Streamx transfer complete interrupt + * @arg DMA_IT_HTIFx: Streamx half transfer complete interrupt + * @arg DMA_IT_TEIFx: Streamx transfer error interrupt + * @arg DMA_IT_DMEIFx: Streamx direct mode error interrupt + * @arg DMA_IT_FEIFx: Streamx FIFO error interrupt + * Where x can be 0 to 7 to select the DMA Stream. + * @retval The new state of DMA_IT (SET or RESET). + */ +ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT) +{ + ITStatus bitstatus = RESET; + DMA_TypeDef* DMAy; + uint32_t tmpreg = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_GET_IT(DMA_IT)); + + /* Determine the DMA to which belongs the stream */ + if (DMAy_Streamx < DMA2_Stream0) + { + /* DMAy_Streamx belongs to DMA1 */ + DMAy = DMA1; + } + else + { + /* DMAy_Streamx belongs to DMA2 */ + DMAy = DMA2; + } + + /* Check if the interrupt enable bit is in the CR or FCR register */ + if ((DMA_IT & TRANSFER_IT_MASK) != (uint32_t)RESET) + { + /* Get the interrupt enable position mask in CR register */ + tmpreg = (uint32_t)((DMA_IT >> 11) & TRANSFER_IT_ENABLE_MASK); + + /* Check the enable bit in CR register */ + enablestatus = (uint32_t)(DMAy_Streamx->CR & tmpreg); + } + else + { + /* Check the enable bit in FCR register */ + enablestatus = (uint32_t)(DMAy_Streamx->FCR & DMA_IT_FE); + } + + /* Check if the interrupt pending flag is in LISR or HISR */ + if ((DMA_IT & HIGH_ISR_MASK) != (uint32_t)RESET) + { + /* Get DMAy HISR register value */ + tmpreg = DMAy->HISR ; + } + else + { + /* Get DMAy LISR register value */ + tmpreg = DMAy->LISR ; + } + + /* mask all reserved bits */ + tmpreg &= (uint32_t)RESERVED_MASK; + + /* Check the status of the specified DMA interrupt */ + if (((tmpreg & DMA_IT) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET)) + { + /* DMA_IT is set */ + bitstatus = SET; + } + else + { + /* DMA_IT is reset */ + bitstatus = RESET; + } + + /* Return the DMA_IT status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Streamx's interrupt pending bits. + * @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0 + * to 7 to select the DMA Stream. + * @param DMA_IT: specifies the DMA interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TCIFx: Streamx transfer complete interrupt + * @arg DMA_IT_HTIFx: Streamx half transfer complete interrupt + * @arg DMA_IT_TEIFx: Streamx transfer error interrupt + * @arg DMA_IT_DMEIFx: Streamx direct mode error interrupt + * @arg DMA_IT_FEIFx: Streamx FIFO error interrupt + * Where x can be 0 to 7 to select the DMA Stream. + * @retval None + */ +void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT) +{ + DMA_TypeDef* DMAy; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Streamx)); + assert_param(IS_DMA_CLEAR_IT(DMA_IT)); + + /* Determine the DMA to which belongs the stream */ + if (DMAy_Streamx < DMA2_Stream0) + { + /* DMAy_Streamx belongs to DMA1 */ + DMAy = DMA1; + } + else + { + /* DMAy_Streamx belongs to DMA2 */ + DMAy = DMA2; + } + + /* Check if LIFCR or HIFCR register is targeted */ + if ((DMA_IT & HIGH_ISR_MASK) != (uint32_t)RESET) + { + /* Set DMAy HIFCR register clear interrupt bits */ + DMAy->HIFCR = (uint32_t)(DMA_IT & RESERVED_MASK); + } + else + { + /* Set DMAy LIFCR register clear interrupt bits */ + DMAy->LIFCR = (uint32_t)(DMA_IT & RESERVED_MASK); + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_dma.h b/stm/lib/stm32f4xx_dma.h new file mode 100644 index 000000000..d7e987e47 --- /dev/null +++ b/stm/lib/stm32f4xx_dma.h @@ -0,0 +1,609 @@ +/** + ****************************************************************************** + * @file stm32f4xx_dma.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file contains all the functions prototypes for the DMA firmware + * library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_DMA_H +#define __STM32F4xx_DMA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DMA + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief DMA Init structure definition + */ + +typedef struct +{ + uint32_t DMA_Channel; /*!< Specifies the channel used for the specified stream. + This parameter can be a value of @ref DMA_channel */ + + uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Streamx. */ + + uint32_t DMA_Memory0BaseAddr; /*!< Specifies the memory 0 base address for DMAy Streamx. + This memory is the default memory used when double buffer mode is + not enabled. */ + + uint32_t DMA_DIR; /*!< Specifies if the data will be transferred from memory to peripheral, + from memory to memory or from peripheral to memory. + This parameter can be a value of @ref DMA_data_transfer_direction */ + + uint32_t DMA_BufferSize; /*!< Specifies the buffer size, in data unit, of the specified Stream. + The data unit is equal to the configuration set in DMA_PeripheralDataSize + or DMA_MemoryDataSize members depending in the transfer direction. */ + + uint32_t DMA_PeripheralInc; /*!< Specifies whether the Peripheral address register should be incremented or not. + This parameter can be a value of @ref DMA_peripheral_incremented_mode */ + + uint32_t DMA_MemoryInc; /*!< Specifies whether the memory address register should be incremented or not. + This parameter can be a value of @ref DMA_memory_incremented_mode */ + + uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width. + This parameter can be a value of @ref DMA_peripheral_data_size */ + + uint32_t DMA_MemoryDataSize; /*!< Specifies the Memory data width. + This parameter can be a value of @ref DMA_memory_data_size */ + + uint32_t DMA_Mode; /*!< Specifies the operation mode of the DMAy Streamx. + This parameter can be a value of @ref DMA_circular_normal_mode + @note The circular buffer mode cannot be used if the memory-to-memory + data transfer is configured on the selected Stream */ + + uint32_t DMA_Priority; /*!< Specifies the software priority for the DMAy Streamx. + This parameter can be a value of @ref DMA_priority_level */ + + uint32_t DMA_FIFOMode; /*!< Specifies if the FIFO mode or Direct mode will be used for the specified Stream. + This parameter can be a value of @ref DMA_fifo_direct_mode + @note The Direct mode (FIFO mode disabled) cannot be used if the + memory-to-memory data transfer is configured on the selected Stream */ + + uint32_t DMA_FIFOThreshold; /*!< Specifies the FIFO threshold level. + This parameter can be a value of @ref DMA_fifo_threshold_level */ + + uint32_t DMA_MemoryBurst; /*!< Specifies the Burst transfer configuration for the memory transfers. + It specifies the amount of data to be transferred in a single non interruptable + transaction. This parameter can be a value of @ref DMA_memory_burst + @note The burst mode is possible only if the address Increment mode is enabled. */ + + uint32_t DMA_PeripheralBurst; /*!< Specifies the Burst transfer configuration for the peripheral transfers. + It specifies the amount of data to be transferred in a single non interruptable + transaction. This parameter can be a value of @ref DMA_peripheral_burst + @note The burst mode is possible only if the address Increment mode is enabled. */ +}DMA_InitTypeDef; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup DMA_Exported_Constants + * @{ + */ + +#define IS_DMA_ALL_PERIPH(PERIPH) (((PERIPH) == DMA1_Stream0) || \ + ((PERIPH) == DMA1_Stream1) || \ + ((PERIPH) == DMA1_Stream2) || \ + ((PERIPH) == DMA1_Stream3) || \ + ((PERIPH) == DMA1_Stream4) || \ + ((PERIPH) == DMA1_Stream5) || \ + ((PERIPH) == DMA1_Stream6) || \ + ((PERIPH) == DMA1_Stream7) || \ + ((PERIPH) == DMA2_Stream0) || \ + ((PERIPH) == DMA2_Stream1) || \ + ((PERIPH) == DMA2_Stream2) || \ + ((PERIPH) == DMA2_Stream3) || \ + ((PERIPH) == DMA2_Stream4) || \ + ((PERIPH) == DMA2_Stream5) || \ + ((PERIPH) == DMA2_Stream6) || \ + ((PERIPH) == DMA2_Stream7)) + +#define IS_DMA_ALL_CONTROLLER(CONTROLLER) (((CONTROLLER) == DMA1) || \ + ((CONTROLLER) == DMA2)) + +/** @defgroup DMA_channel + * @{ + */ +#define DMA_Channel_0 ((uint32_t)0x00000000) +#define DMA_Channel_1 ((uint32_t)0x02000000) +#define DMA_Channel_2 ((uint32_t)0x04000000) +#define DMA_Channel_3 ((uint32_t)0x06000000) +#define DMA_Channel_4 ((uint32_t)0x08000000) +#define DMA_Channel_5 ((uint32_t)0x0A000000) +#define DMA_Channel_6 ((uint32_t)0x0C000000) +#define DMA_Channel_7 ((uint32_t)0x0E000000) + +#define IS_DMA_CHANNEL(CHANNEL) (((CHANNEL) == DMA_Channel_0) || \ + ((CHANNEL) == DMA_Channel_1) || \ + ((CHANNEL) == DMA_Channel_2) || \ + ((CHANNEL) == DMA_Channel_3) || \ + ((CHANNEL) == DMA_Channel_4) || \ + ((CHANNEL) == DMA_Channel_5) || \ + ((CHANNEL) == DMA_Channel_6) || \ + ((CHANNEL) == DMA_Channel_7)) +/** + * @} + */ + + +/** @defgroup DMA_data_transfer_direction + * @{ + */ +#define DMA_DIR_PeripheralToMemory ((uint32_t)0x00000000) +#define DMA_DIR_MemoryToPeripheral ((uint32_t)0x00000040) +#define DMA_DIR_MemoryToMemory ((uint32_t)0x00000080) + +#define IS_DMA_DIRECTION(DIRECTION) (((DIRECTION) == DMA_DIR_PeripheralToMemory ) || \ + ((DIRECTION) == DMA_DIR_MemoryToPeripheral) || \ + ((DIRECTION) == DMA_DIR_MemoryToMemory)) +/** + * @} + */ + + +/** @defgroup DMA_data_buffer_size + * @{ + */ +#define IS_DMA_BUFFER_SIZE(SIZE) (((SIZE) >= 0x1) && ((SIZE) < 0x10000)) +/** + * @} + */ + + +/** @defgroup DMA_peripheral_incremented_mode + * @{ + */ +#define DMA_PeripheralInc_Enable ((uint32_t)0x00000200) +#define DMA_PeripheralInc_Disable ((uint32_t)0x00000000) + +#define IS_DMA_PERIPHERAL_INC_STATE(STATE) (((STATE) == DMA_PeripheralInc_Enable) || \ + ((STATE) == DMA_PeripheralInc_Disable)) +/** + * @} + */ + + +/** @defgroup DMA_memory_incremented_mode + * @{ + */ +#define DMA_MemoryInc_Enable ((uint32_t)0x00000400) +#define DMA_MemoryInc_Disable ((uint32_t)0x00000000) + +#define IS_DMA_MEMORY_INC_STATE(STATE) (((STATE) == DMA_MemoryInc_Enable) || \ + ((STATE) == DMA_MemoryInc_Disable)) +/** + * @} + */ + + +/** @defgroup DMA_peripheral_data_size + * @{ + */ +#define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) +#define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000800) +#define DMA_PeripheralDataSize_Word ((uint32_t)0x00001000) + +#define IS_DMA_PERIPHERAL_DATA_SIZE(SIZE) (((SIZE) == DMA_PeripheralDataSize_Byte) || \ + ((SIZE) == DMA_PeripheralDataSize_HalfWord) || \ + ((SIZE) == DMA_PeripheralDataSize_Word)) +/** + * @} + */ + + +/** @defgroup DMA_memory_data_size + * @{ + */ +#define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) +#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00002000) +#define DMA_MemoryDataSize_Word ((uint32_t)0x00004000) + +#define IS_DMA_MEMORY_DATA_SIZE(SIZE) (((SIZE) == DMA_MemoryDataSize_Byte) || \ + ((SIZE) == DMA_MemoryDataSize_HalfWord) || \ + ((SIZE) == DMA_MemoryDataSize_Word )) +/** + * @} + */ + + +/** @defgroup DMA_circular_normal_mode + * @{ + */ +#define DMA_Mode_Normal ((uint32_t)0x00000000) +#define DMA_Mode_Circular ((uint32_t)0x00000100) + +#define IS_DMA_MODE(MODE) (((MODE) == DMA_Mode_Normal ) || \ + ((MODE) == DMA_Mode_Circular)) +/** + * @} + */ + + +/** @defgroup DMA_priority_level + * @{ + */ +#define DMA_Priority_Low ((uint32_t)0x00000000) +#define DMA_Priority_Medium ((uint32_t)0x00010000) +#define DMA_Priority_High ((uint32_t)0x00020000) +#define DMA_Priority_VeryHigh ((uint32_t)0x00030000) + +#define IS_DMA_PRIORITY(PRIORITY) (((PRIORITY) == DMA_Priority_Low ) || \ + ((PRIORITY) == DMA_Priority_Medium) || \ + ((PRIORITY) == DMA_Priority_High) || \ + ((PRIORITY) == DMA_Priority_VeryHigh)) +/** + * @} + */ + + +/** @defgroup DMA_fifo_direct_mode + * @{ + */ +#define DMA_FIFOMode_Disable ((uint32_t)0x00000000) +#define DMA_FIFOMode_Enable ((uint32_t)0x00000004) + +#define IS_DMA_FIFO_MODE_STATE(STATE) (((STATE) == DMA_FIFOMode_Disable ) || \ + ((STATE) == DMA_FIFOMode_Enable)) +/** + * @} + */ + + +/** @defgroup DMA_fifo_threshold_level + * @{ + */ +#define DMA_FIFOThreshold_1QuarterFull ((uint32_t)0x00000000) +#define DMA_FIFOThreshold_HalfFull ((uint32_t)0x00000001) +#define DMA_FIFOThreshold_3QuartersFull ((uint32_t)0x00000002) +#define DMA_FIFOThreshold_Full ((uint32_t)0x00000003) + +#define IS_DMA_FIFO_THRESHOLD(THRESHOLD) (((THRESHOLD) == DMA_FIFOThreshold_1QuarterFull ) || \ + ((THRESHOLD) == DMA_FIFOThreshold_HalfFull) || \ + ((THRESHOLD) == DMA_FIFOThreshold_3QuartersFull) || \ + ((THRESHOLD) == DMA_FIFOThreshold_Full)) +/** + * @} + */ + + +/** @defgroup DMA_memory_burst + * @{ + */ +#define DMA_MemoryBurst_Single ((uint32_t)0x00000000) +#define DMA_MemoryBurst_INC4 ((uint32_t)0x00800000) +#define DMA_MemoryBurst_INC8 ((uint32_t)0x01000000) +#define DMA_MemoryBurst_INC16 ((uint32_t)0x01800000) + +#define IS_DMA_MEMORY_BURST(BURST) (((BURST) == DMA_MemoryBurst_Single) || \ + ((BURST) == DMA_MemoryBurst_INC4) || \ + ((BURST) == DMA_MemoryBurst_INC8) || \ + ((BURST) == DMA_MemoryBurst_INC16)) +/** + * @} + */ + + +/** @defgroup DMA_peripheral_burst + * @{ + */ +#define DMA_PeripheralBurst_Single ((uint32_t)0x00000000) +#define DMA_PeripheralBurst_INC4 ((uint32_t)0x00200000) +#define DMA_PeripheralBurst_INC8 ((uint32_t)0x00400000) +#define DMA_PeripheralBurst_INC16 ((uint32_t)0x00600000) + +#define IS_DMA_PERIPHERAL_BURST(BURST) (((BURST) == DMA_PeripheralBurst_Single) || \ + ((BURST) == DMA_PeripheralBurst_INC4) || \ + ((BURST) == DMA_PeripheralBurst_INC8) || \ + ((BURST) == DMA_PeripheralBurst_INC16)) +/** + * @} + */ + + +/** @defgroup DMA_fifo_status_level + * @{ + */ +#define DMA_FIFOStatus_Less1QuarterFull ((uint32_t)0x00000000 << 3) +#define DMA_FIFOStatus_1QuarterFull ((uint32_t)0x00000001 << 3) +#define DMA_FIFOStatus_HalfFull ((uint32_t)0x00000002 << 3) +#define DMA_FIFOStatus_3QuartersFull ((uint32_t)0x00000003 << 3) +#define DMA_FIFOStatus_Empty ((uint32_t)0x00000004 << 3) +#define DMA_FIFOStatus_Full ((uint32_t)0x00000005 << 3) + +#define IS_DMA_FIFO_STATUS(STATUS) (((STATUS) == DMA_FIFOStatus_Less1QuarterFull ) || \ + ((STATUS) == DMA_FIFOStatus_HalfFull) || \ + ((STATUS) == DMA_FIFOStatus_1QuarterFull) || \ + ((STATUS) == DMA_FIFOStatus_3QuartersFull) || \ + ((STATUS) == DMA_FIFOStatus_Full) || \ + ((STATUS) == DMA_FIFOStatus_Empty)) +/** + * @} + */ + +/** @defgroup DMA_flags_definition + * @{ + */ +#define DMA_FLAG_FEIF0 ((uint32_t)0x10800001) +#define DMA_FLAG_DMEIF0 ((uint32_t)0x10800004) +#define DMA_FLAG_TEIF0 ((uint32_t)0x10000008) +#define DMA_FLAG_HTIF0 ((uint32_t)0x10000010) +#define DMA_FLAG_TCIF0 ((uint32_t)0x10000020) +#define DMA_FLAG_FEIF1 ((uint32_t)0x10000040) +#define DMA_FLAG_DMEIF1 ((uint32_t)0x10000100) +#define DMA_FLAG_TEIF1 ((uint32_t)0x10000200) +#define DMA_FLAG_HTIF1 ((uint32_t)0x10000400) +#define DMA_FLAG_TCIF1 ((uint32_t)0x10000800) +#define DMA_FLAG_FEIF2 ((uint32_t)0x10010000) +#define DMA_FLAG_DMEIF2 ((uint32_t)0x10040000) +#define DMA_FLAG_TEIF2 ((uint32_t)0x10080000) +#define DMA_FLAG_HTIF2 ((uint32_t)0x10100000) +#define DMA_FLAG_TCIF2 ((uint32_t)0x10200000) +#define DMA_FLAG_FEIF3 ((uint32_t)0x10400000) +#define DMA_FLAG_DMEIF3 ((uint32_t)0x11000000) +#define DMA_FLAG_TEIF3 ((uint32_t)0x12000000) +#define DMA_FLAG_HTIF3 ((uint32_t)0x14000000) +#define DMA_FLAG_TCIF3 ((uint32_t)0x18000000) +#define DMA_FLAG_FEIF4 ((uint32_t)0x20000001) +#define DMA_FLAG_DMEIF4 ((uint32_t)0x20000004) +#define DMA_FLAG_TEIF4 ((uint32_t)0x20000008) +#define DMA_FLAG_HTIF4 ((uint32_t)0x20000010) +#define DMA_FLAG_TCIF4 ((uint32_t)0x20000020) +#define DMA_FLAG_FEIF5 ((uint32_t)0x20000040) +#define DMA_FLAG_DMEIF5 ((uint32_t)0x20000100) +#define DMA_FLAG_TEIF5 ((uint32_t)0x20000200) +#define DMA_FLAG_HTIF5 ((uint32_t)0x20000400) +#define DMA_FLAG_TCIF5 ((uint32_t)0x20000800) +#define DMA_FLAG_FEIF6 ((uint32_t)0x20010000) +#define DMA_FLAG_DMEIF6 ((uint32_t)0x20040000) +#define DMA_FLAG_TEIF6 ((uint32_t)0x20080000) +#define DMA_FLAG_HTIF6 ((uint32_t)0x20100000) +#define DMA_FLAG_TCIF6 ((uint32_t)0x20200000) +#define DMA_FLAG_FEIF7 ((uint32_t)0x20400000) +#define DMA_FLAG_DMEIF7 ((uint32_t)0x21000000) +#define DMA_FLAG_TEIF7 ((uint32_t)0x22000000) +#define DMA_FLAG_HTIF7 ((uint32_t)0x24000000) +#define DMA_FLAG_TCIF7 ((uint32_t)0x28000000) + +#define IS_DMA_CLEAR_FLAG(FLAG) ((((FLAG) & 0x30000000) != 0x30000000) && (((FLAG) & 0x30000000) != 0) && \ + (((FLAG) & 0xC002F082) == 0x00) && ((FLAG) != 0x00)) + +#define IS_DMA_GET_FLAG(FLAG) (((FLAG) == DMA_FLAG_TCIF0) || ((FLAG) == DMA_FLAG_HTIF0) || \ + ((FLAG) == DMA_FLAG_TEIF0) || ((FLAG) == DMA_FLAG_DMEIF0) || \ + ((FLAG) == DMA_FLAG_FEIF0) || ((FLAG) == DMA_FLAG_TCIF1) || \ + ((FLAG) == DMA_FLAG_HTIF1) || ((FLAG) == DMA_FLAG_TEIF1) || \ + ((FLAG) == DMA_FLAG_DMEIF1) || ((FLAG) == DMA_FLAG_FEIF1) || \ + ((FLAG) == DMA_FLAG_TCIF2) || ((FLAG) == DMA_FLAG_HTIF2) || \ + ((FLAG) == DMA_FLAG_TEIF2) || ((FLAG) == DMA_FLAG_DMEIF2) || \ + ((FLAG) == DMA_FLAG_FEIF2) || ((FLAG) == DMA_FLAG_TCIF3) || \ + ((FLAG) == DMA_FLAG_HTIF3) || ((FLAG) == DMA_FLAG_TEIF3) || \ + ((FLAG) == DMA_FLAG_DMEIF3) || ((FLAG) == DMA_FLAG_FEIF3) || \ + ((FLAG) == DMA_FLAG_TCIF4) || ((FLAG) == DMA_FLAG_HTIF4) || \ + ((FLAG) == DMA_FLAG_TEIF4) || ((FLAG) == DMA_FLAG_DMEIF4) || \ + ((FLAG) == DMA_FLAG_FEIF4) || ((FLAG) == DMA_FLAG_TCIF5) || \ + ((FLAG) == DMA_FLAG_HTIF5) || ((FLAG) == DMA_FLAG_TEIF5) || \ + ((FLAG) == DMA_FLAG_DMEIF5) || ((FLAG) == DMA_FLAG_FEIF5) || \ + ((FLAG) == DMA_FLAG_TCIF6) || ((FLAG) == DMA_FLAG_HTIF6) || \ + ((FLAG) == DMA_FLAG_TEIF6) || ((FLAG) == DMA_FLAG_DMEIF6) || \ + ((FLAG) == DMA_FLAG_FEIF6) || ((FLAG) == DMA_FLAG_TCIF7) || \ + ((FLAG) == DMA_FLAG_HTIF7) || ((FLAG) == DMA_FLAG_TEIF7) || \ + ((FLAG) == DMA_FLAG_DMEIF7) || ((FLAG) == DMA_FLAG_FEIF7)) +/** + * @} + */ + + +/** @defgroup DMA_interrupt_enable_definitions + * @{ + */ +#define DMA_IT_TC ((uint32_t)0x00000010) +#define DMA_IT_HT ((uint32_t)0x00000008) +#define DMA_IT_TE ((uint32_t)0x00000004) +#define DMA_IT_DME ((uint32_t)0x00000002) +#define DMA_IT_FE ((uint32_t)0x00000080) + +#define IS_DMA_CONFIG_IT(IT) ((((IT) & 0xFFFFFF61) == 0x00) && ((IT) != 0x00)) +/** + * @} + */ + + +/** @defgroup DMA_interrupts_definitions + * @{ + */ +#define DMA_IT_FEIF0 ((uint32_t)0x90000001) +#define DMA_IT_DMEIF0 ((uint32_t)0x10001004) +#define DMA_IT_TEIF0 ((uint32_t)0x10002008) +#define DMA_IT_HTIF0 ((uint32_t)0x10004010) +#define DMA_IT_TCIF0 ((uint32_t)0x10008020) +#define DMA_IT_FEIF1 ((uint32_t)0x90000040) +#define DMA_IT_DMEIF1 ((uint32_t)0x10001100) +#define DMA_IT_TEIF1 ((uint32_t)0x10002200) +#define DMA_IT_HTIF1 ((uint32_t)0x10004400) +#define DMA_IT_TCIF1 ((uint32_t)0x10008800) +#define DMA_IT_FEIF2 ((uint32_t)0x90010000) +#define DMA_IT_DMEIF2 ((uint32_t)0x10041000) +#define DMA_IT_TEIF2 ((uint32_t)0x10082000) +#define DMA_IT_HTIF2 ((uint32_t)0x10104000) +#define DMA_IT_TCIF2 ((uint32_t)0x10208000) +#define DMA_IT_FEIF3 ((uint32_t)0x90400000) +#define DMA_IT_DMEIF3 ((uint32_t)0x11001000) +#define DMA_IT_TEIF3 ((uint32_t)0x12002000) +#define DMA_IT_HTIF3 ((uint32_t)0x14004000) +#define DMA_IT_TCIF3 ((uint32_t)0x18008000) +#define DMA_IT_FEIF4 ((uint32_t)0xA0000001) +#define DMA_IT_DMEIF4 ((uint32_t)0x20001004) +#define DMA_IT_TEIF4 ((uint32_t)0x20002008) +#define DMA_IT_HTIF4 ((uint32_t)0x20004010) +#define DMA_IT_TCIF4 ((uint32_t)0x20008020) +#define DMA_IT_FEIF5 ((uint32_t)0xA0000040) +#define DMA_IT_DMEIF5 ((uint32_t)0x20001100) +#define DMA_IT_TEIF5 ((uint32_t)0x20002200) +#define DMA_IT_HTIF5 ((uint32_t)0x20004400) +#define DMA_IT_TCIF5 ((uint32_t)0x20008800) +#define DMA_IT_FEIF6 ((uint32_t)0xA0010000) +#define DMA_IT_DMEIF6 ((uint32_t)0x20041000) +#define DMA_IT_TEIF6 ((uint32_t)0x20082000) +#define DMA_IT_HTIF6 ((uint32_t)0x20104000) +#define DMA_IT_TCIF6 ((uint32_t)0x20208000) +#define DMA_IT_FEIF7 ((uint32_t)0xA0400000) +#define DMA_IT_DMEIF7 ((uint32_t)0x21001000) +#define DMA_IT_TEIF7 ((uint32_t)0x22002000) +#define DMA_IT_HTIF7 ((uint32_t)0x24004000) +#define DMA_IT_TCIF7 ((uint32_t)0x28008000) + +#define IS_DMA_CLEAR_IT(IT) ((((IT) & 0x30000000) != 0x30000000) && \ + (((IT) & 0x30000000) != 0) && ((IT) != 0x00) && \ + (((IT) & 0x40820082) == 0x00)) + +#define IS_DMA_GET_IT(IT) (((IT) == DMA_IT_TCIF0) || ((IT) == DMA_IT_HTIF0) || \ + ((IT) == DMA_IT_TEIF0) || ((IT) == DMA_IT_DMEIF0) || \ + ((IT) == DMA_IT_FEIF0) || ((IT) == DMA_IT_TCIF1) || \ + ((IT) == DMA_IT_HTIF1) || ((IT) == DMA_IT_TEIF1) || \ + ((IT) == DMA_IT_DMEIF1)|| ((IT) == DMA_IT_FEIF1) || \ + ((IT) == DMA_IT_TCIF2) || ((IT) == DMA_IT_HTIF2) || \ + ((IT) == DMA_IT_TEIF2) || ((IT) == DMA_IT_DMEIF2) || \ + ((IT) == DMA_IT_FEIF2) || ((IT) == DMA_IT_TCIF3) || \ + ((IT) == DMA_IT_HTIF3) || ((IT) == DMA_IT_TEIF3) || \ + ((IT) == DMA_IT_DMEIF3)|| ((IT) == DMA_IT_FEIF3) || \ + ((IT) == DMA_IT_TCIF4) || ((IT) == DMA_IT_HTIF4) || \ + ((IT) == DMA_IT_TEIF4) || ((IT) == DMA_IT_DMEIF4) || \ + ((IT) == DMA_IT_FEIF4) || ((IT) == DMA_IT_TCIF5) || \ + ((IT) == DMA_IT_HTIF5) || ((IT) == DMA_IT_TEIF5) || \ + ((IT) == DMA_IT_DMEIF5)|| ((IT) == DMA_IT_FEIF5) || \ + ((IT) == DMA_IT_TCIF6) || ((IT) == DMA_IT_HTIF6) || \ + ((IT) == DMA_IT_TEIF6) || ((IT) == DMA_IT_DMEIF6) || \ + ((IT) == DMA_IT_FEIF6) || ((IT) == DMA_IT_TCIF7) || \ + ((IT) == DMA_IT_HTIF7) || ((IT) == DMA_IT_TEIF7) || \ + ((IT) == DMA_IT_DMEIF7)|| ((IT) == DMA_IT_FEIF7)) +/** + * @} + */ + + +/** @defgroup DMA_peripheral_increment_offset + * @{ + */ +#define DMA_PINCOS_Psize ((uint32_t)0x00000000) +#define DMA_PINCOS_WordAligned ((uint32_t)0x00008000) + +#define IS_DMA_PINCOS_SIZE(SIZE) (((SIZE) == DMA_PINCOS_Psize) || \ + ((SIZE) == DMA_PINCOS_WordAligned)) +/** + * @} + */ + + +/** @defgroup DMA_flow_controller_definitions + * @{ + */ +#define DMA_FlowCtrl_Memory ((uint32_t)0x00000000) +#define DMA_FlowCtrl_Peripheral ((uint32_t)0x00000020) + +#define IS_DMA_FLOW_CTRL(CTRL) (((CTRL) == DMA_FlowCtrl_Memory) || \ + ((CTRL) == DMA_FlowCtrl_Peripheral)) +/** + * @} + */ + + +/** @defgroup DMA_memory_targets_definitions + * @{ + */ +#define DMA_Memory_0 ((uint32_t)0x00000000) +#define DMA_Memory_1 ((uint32_t)0x00080000) + +#define IS_DMA_CURRENT_MEM(MEM) (((MEM) == DMA_Memory_0) || ((MEM) == DMA_Memory_1)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Function used to set the DMA configuration to the default reset state *****/ +void DMA_DeInit(DMA_Stream_TypeDef* DMAy_Streamx); + +/* Initialization and Configuration functions *********************************/ +void DMA_Init(DMA_Stream_TypeDef* DMAy_Streamx, DMA_InitTypeDef* DMA_InitStruct); +void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct); +void DMA_Cmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState); + +/* Optional Configuration functions *******************************************/ +void DMA_PeriphIncOffsetSizeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_Pincos); +void DMA_FlowControllerConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FlowCtrl); + +/* Data Counter functions *****************************************************/ +void DMA_SetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx, uint16_t Counter); +uint16_t DMA_GetCurrDataCounter(DMA_Stream_TypeDef* DMAy_Streamx); + +/* Double Buffer mode functions ***********************************************/ +void DMA_DoubleBufferModeConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t Memory1BaseAddr, + uint32_t DMA_CurrentMemory); +void DMA_DoubleBufferModeCmd(DMA_Stream_TypeDef* DMAy_Streamx, FunctionalState NewState); +void DMA_MemoryTargetConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t MemoryBaseAddr, + uint32_t DMA_MemoryTarget); +uint32_t DMA_GetCurrentMemoryTarget(DMA_Stream_TypeDef* DMAy_Streamx); + +/* Interrupts and flags management functions **********************************/ +FunctionalState DMA_GetCmdStatus(DMA_Stream_TypeDef* DMAy_Streamx); +uint32_t DMA_GetFIFOStatus(DMA_Stream_TypeDef* DMAy_Streamx); +FlagStatus DMA_GetFlagStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG); +void DMA_ClearFlag(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_FLAG); +void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState); +ITStatus DMA_GetITStatus(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT); +void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F4xx_DMA_H */ + +/** + * @} + */ + +/** + * @} + */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_exti.c b/stm/lib/stm32f4xx_exti.c new file mode 100644 index 000000000..6160cbd7b --- /dev/null +++ b/stm/lib/stm32f4xx_exti.c @@ -0,0 +1,314 @@ +/** + ****************************************************************************** + * @file stm32f4xx_exti.c + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file provides firmware functions to manage the following + * functionalities of the EXTI peripheral: + * + Initialization and Configuration + * + Interrupts and flags management + * +@verbatim + + =================================================================== + ##### EXTI features ##### + =================================================================== + + [..] External interrupt/event lines are mapped as following: + (#) All available GPIO pins are connected to the 16 external + interrupt/event lines from EXTI0 to EXTI15. + (#) EXTI line 16 is connected to the PVD Output + (#) EXTI line 17 is connected to the RTC Alarm event + (#) EXTI line 18 is connected to the USB OTG FS Wakeup from suspend event + (#) EXTI line 19 is connected to the Ethernet Wakeup event + (#) EXTI line 20 is connected to the USB OTG HS (configured in FS) Wakeup event + (#) EXTI line 21 is connected to the RTC Tamper and Time Stamp events + (#) EXTI line 22 is connected to the RTC Wakeup event + + + ##### How to use this driver ##### + =================================================================== + + [..] In order to use an I/O pin as an external interrupt source, follow steps + below: + (#) Configure the I/O in input mode using GPIO_Init() + (#) Select the input source pin for the EXTI line using SYSCFG_EXTILineConfig() + (#) Select the mode(interrupt, event) and configure the trigger + selection (Rising, falling or both) using EXTI_Init() + (#) Configure NVIC IRQ channel mapped to the EXTI line using NVIC_Init() + + [..] + (@) SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx + registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); + +@endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_conf.h" +#include "stm32f4xx_exti.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup EXTI + * @brief EXTI driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +#define EXTI_LINENONE ((uint32_t)0x00000) /* No interrupt selected */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup EXTI_Private_Functions + * @{ + */ + +/** @defgroup EXTI_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the EXTI peripheral registers to their default reset values. + * @param None + * @retval None + */ +void EXTI_DeInit(void) +{ + EXTI->IMR = 0x00000000; + EXTI->EMR = 0x00000000; + EXTI->RTSR = 0x00000000; + EXTI->FTSR = 0x00000000; + EXTI->PR = 0x007FFFFF; +} + +/** + * @brief Initializes the EXTI peripheral according to the specified + * parameters in the EXTI_InitStruct. + * @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure + * that contains the configuration information for the EXTI peripheral. + * @retval None + */ +void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode)); + assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger)); + assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line)); + assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd)); + + tmp = (uint32_t)EXTI_BASE; + + if (EXTI_InitStruct->EXTI_LineCmd != DISABLE) + { + /* Clear EXTI line configuration */ + EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line; + EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line; + + tmp += EXTI_InitStruct->EXTI_Mode; + + *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line; + + /* Clear Rising Falling edge configuration */ + EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line; + EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line; + + /* Select the trigger for the selected external interrupts */ + if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling) + { + /* Rising Falling edge */ + EXTI->RTSR |= EXTI_InitStruct->EXTI_Line; + EXTI->FTSR |= EXTI_InitStruct->EXTI_Line; + } + else + { + tmp = (uint32_t)EXTI_BASE; + tmp += EXTI_InitStruct->EXTI_Trigger; + + *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line; + } + } + else + { + tmp += EXTI_InitStruct->EXTI_Mode; + + /* Disable the selected external lines */ + *(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line; + } +} + +/** + * @brief Fills each EXTI_InitStruct member with its reset value. + * @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct) +{ + EXTI_InitStruct->EXTI_Line = EXTI_LINENONE; + EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling; + EXTI_InitStruct->EXTI_LineCmd = DISABLE; +} + +/** + * @brief Generates a Software interrupt on selected EXTI line. + * @param EXTI_Line: specifies the EXTI line on which the software interrupt + * will be generated. + * This parameter can be any combination of EXTI_Linex where x can be (0..22) + * @retval None + */ +void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->SWIER |= EXTI_Line; +} + +/** + * @} + */ + +/** @defgroup EXTI_Group2 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Checks whether the specified EXTI line flag is set or not. + * @param EXTI_Line: specifies the EXTI line flag to check. + * This parameter can be EXTI_Linex where x can be(0..22) + * @retval The new state of EXTI_Line (SET or RESET). + */ +FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + if ((EXTI->PR & EXTI_Line) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending flags. + * @param EXTI_Line: specifies the EXTI lines flags to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..22) + * @retval None + */ +void EXTI_ClearFlag(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PR = EXTI_Line; +} + +/** + * @brief Checks whether the specified EXTI line is asserted or not. + * @param EXTI_Line: specifies the EXTI line to check. + * This parameter can be EXTI_Linex where x can be(0..22) + * @retval The new state of EXTI_Line (SET or RESET). + */ +ITStatus EXTI_GetITStatus(uint32_t EXTI_Line) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + enablestatus = EXTI->IMR & EXTI_Line; + if (((EXTI->PR & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending bits. + * @param EXTI_Line: specifies the EXTI lines to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..22) + * @retval None + */ +void EXTI_ClearITPendingBit(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PR = EXTI_Line; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_exti.h b/stm/lib/stm32f4xx_exti.h new file mode 100644 index 000000000..b6eb85395 --- /dev/null +++ b/stm/lib/stm32f4xx_exti.h @@ -0,0 +1,183 @@ +/** + ****************************************************************************** + * @file stm32f4xx_exti.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file contains all the functions prototypes for the EXTI firmware + * library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_EXTI_H +#define __STM32F4xx_EXTI_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup EXTI + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief EXTI mode enumeration + */ + +typedef enum +{ + EXTI_Mode_Interrupt = 0x00, + EXTI_Mode_Event = 0x04 +}EXTIMode_TypeDef; + +#define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event)) + +/** + * @brief EXTI Trigger enumeration + */ + +typedef enum +{ + EXTI_Trigger_Rising = 0x08, + EXTI_Trigger_Falling = 0x0C, + EXTI_Trigger_Rising_Falling = 0x10 +}EXTITrigger_TypeDef; + +#define IS_EXTI_TRIGGER(TRIGGER) (((TRIGGER) == EXTI_Trigger_Rising) || \ + ((TRIGGER) == EXTI_Trigger_Falling) || \ + ((TRIGGER) == EXTI_Trigger_Rising_Falling)) +/** + * @brief EXTI Init Structure definition + */ + +typedef struct +{ + uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled. + This parameter can be any combination value of @ref EXTI_Lines */ + + EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines. + This parameter can be a value of @ref EXTIMode_TypeDef */ + + EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. + This parameter can be a value of @ref EXTITrigger_TypeDef */ + + FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines. + This parameter can be set either to ENABLE or DISABLE */ +}EXTI_InitTypeDef; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup EXTI_Exported_Constants + * @{ + */ + +/** @defgroup EXTI_Lines + * @{ + */ + +#define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */ +#define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */ +#define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */ +#define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */ +#define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */ +#define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */ +#define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */ +#define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */ +#define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */ +#define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */ +#define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */ +#define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */ +#define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */ +#define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */ +#define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */ +#define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */ +#define EXTI_Line16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */ +#define EXTI_Line17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */ +#define EXTI_Line18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB OTG FS Wakeup from suspend event */ +#define EXTI_Line19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */ +#define EXTI_Line20 ((uint32_t)0x00100000) /*!< External interrupt line 20 Connected to the USB OTG HS (configured in FS) Wakeup event */ +#define EXTI_Line21 ((uint32_t)0x00200000) /*!< External interrupt line 21 Connected to the RTC Tamper and Time Stamp events */ +#define EXTI_Line22 ((uint32_t)0x00400000) /*!< External interrupt line 22 Connected to the RTC Wakeup event */ + +#define IS_EXTI_LINE(LINE) ((((LINE) & (uint32_t)0xFF800000) == 0x00) && ((LINE) != (uint16_t)0x00)) + +#define IS_GET_EXTI_LINE(LINE) (((LINE) == EXTI_Line0) || ((LINE) == EXTI_Line1) || \ + ((LINE) == EXTI_Line2) || ((LINE) == EXTI_Line3) || \ + ((LINE) == EXTI_Line4) || ((LINE) == EXTI_Line5) || \ + ((LINE) == EXTI_Line6) || ((LINE) == EXTI_Line7) || \ + ((LINE) == EXTI_Line8) || ((LINE) == EXTI_Line9) || \ + ((LINE) == EXTI_Line10) || ((LINE) == EXTI_Line11) || \ + ((LINE) == EXTI_Line12) || ((LINE) == EXTI_Line13) || \ + ((LINE) == EXTI_Line14) || ((LINE) == EXTI_Line15) || \ + ((LINE) == EXTI_Line16) || ((LINE) == EXTI_Line17) || \ + ((LINE) == EXTI_Line18) || ((LINE) == EXTI_Line19) || \ + ((LINE) == EXTI_Line20) || ((LINE) == EXTI_Line21) ||\ + ((LINE) == EXTI_Line22)) + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Function used to set the EXTI configuration to the default reset state *****/ +void EXTI_DeInit(void); + +/* Initialization and Configuration functions *********************************/ +void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); +void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct); +void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line); + +/* Interrupts and flags management functions **********************************/ +FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); +void EXTI_ClearFlag(uint32_t EXTI_Line); +ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); +void EXTI_ClearITPendingBit(uint32_t EXTI_Line); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_EXTI_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_flash.c b/stm/lib/stm32f4xx_flash.c new file mode 100644 index 000000000..ba16c3f57 --- /dev/null +++ b/stm/lib/stm32f4xx_flash.c @@ -0,0 +1,1177 @@ +/** + ****************************************************************************** + * @file stm32f4xx_flash.c + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file provides firmware functions to manage the following + * functionalities of the FLASH peripheral: + * + FLASH Interface configuration + * + FLASH Memory Programming + * + Option Bytes Programming + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + This driver provides functions to configure and program the FLASH memory + of all STM32F4xx devices. These functions are split in 4 groups: + + (#) FLASH Interface configuration functions: this group includes the + management of the following features: + (++) Set the latency + (++) Enable/Disable the prefetch buffer + (++) Enable/Disable the Instruction cache and the Data cache + (++) Reset the Instruction cache and the Data cache + + (#) FLASH Memory Programming functions: this group includes all needed + functions to erase and program the main memory: + (++) Lock and Unlock the FLASH interface + (++) Erase function: Erase sector, erase all sectors + (++) Program functions: byte, half word, word and double word + + (#) Option Bytes Programming functions: this group includes all needed + functions to manage the Option Bytes: + (++) Set/Reset the write protection + (++) Set the Read protection Level + (++) Set the BOR level + (++) Program the user Option Bytes + (++) Launch the Option Bytes loader + + (#) Interrupts and flags management functions: this group + includes all needed functions to: + (++) Enable/Disable the FLASH interrupt sources + (++) Get flags status + (++) Clear flags + (++) Get FLASH operation status + (++) Wait for last FLASH operation + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_flash.h" +#include "stm32f4xx_conf.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup FLASH + * @brief FLASH driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define SECTOR_MASK ((uint32_t)0xFFFFFF07) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup FLASH_Private_Functions + * @{ + */ + +/** @defgroup FLASH_Group1 FLASH Interface configuration functions + * @brief FLASH Interface configuration functions + * + +@verbatim + =============================================================================== + ##### FLASH Interface configuration functions ##### + =============================================================================== + [..] + This group includes the following functions: + (+) void FLASH_SetLatency(uint32_t FLASH_Latency) + To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. + +-------------------------------------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |---------------------------------------------------------------------| + | | voltage range | voltage range | voltage range | voltage range | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | + |---------------|----------------|----------------|-----------------|-----------------| + |0WS(1CPU cycle)|0 < HCLK <= 30 |0 < HCLK <= 24 |0 < HCLK <= 22 |0 < HCLK <= 20 | + |---------------|----------------|----------------|-----------------|-----------------| + |1WS(2CPU cycle)|30 < HCLK <= 60 |24 < HCLK <= 48 |22 < HCLK <= 44 |20 < HCLK <= 40 | + |---------------|----------------|----------------|-----------------|-----------------| + |2WS(3CPU cycle)|60 < HCLK <= 90 |48 < HCLK <= 72 |44 < HCLK <= 66 |40 < HCLK <= 60 | + |---------------|----------------|----------------|-----------------|-----------------| + |3WS(4CPU cycle)|90 < HCLK <= 120|72 < HCLK <= 96 |66 < HCLK <= 88 |60 < HCLK <= 80 | + |---------------|----------------|----------------|-----------------|-----------------| + |4WS(5CPU cycle)|120< HCLK <= 150|96 < HCLK <= 120|88 < HCLK <= 110 |80 < HCLK <= 100 | + |---------------|----------------|----------------|-----------------|-----------------| + |5WS(6CPU cycle)|120< HCLK <= 168|120< HCLK <= 144|110 < HCLK <= 132|100 < HCLK <= 120| + |---------------|----------------|----------------|-----------------|-----------------| + |6WS(7CPU cycle)| NA |144< HCLK <= 168|132 < HCLK <= 154|120 < HCLK <= 140| + |---------------|----------------|----------------|-----------------|-----------------| + |7WS(8CPU cycle)| NA | NA |154 < HCLK <= 168|140 < HCLK <= 160| + +-------------------------------------------------------------------------------------+ + + [..] + +-------------------------------------------------------------------------------------------------------------------+ + | | voltage range | voltage range | voltage range | voltage range | voltage range 2.7 V - 3.6 V | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | with External Vpp = 9V | + |---------------|----------------|----------------|-----------------|-----------------|-----------------------------| + |Max Parallelism| x32 | x16 | x8 | x64 | + |---------------|----------------|----------------|-----------------|-----------------|-----------------------------| + |PSIZE[1:0] | 10 | 01 | 00 | 11 | + +-------------------------------------------------------------------------------------------------------------------+ + -@- When VOS bit (in PWR_CR register) is reset to 0 , the maximum value of HCLK is 144 MHz. + You can use PWR_MainRegulatorModeConfig() function to set or reset this bit. + -@- On STM32F40xx/41xx devices: + (++) when VOS = '0', the maximum value of fHCLK = 144MHz. + (++) when VOS = '1', the maximum value of fHCLK = 168MHz. + [..] + On STM32F427x/437x devices: + (++) when VOS[1:0] = '0x01', the maximum value of fHCLK is 120MHz. + (++) when VOS[1:0] = '0x10', the maximum value of fHCLK is 144MHz. + (++) when VOS[1:0] = '0x11', the maximum value of f is 168MHz + You can use PWR_MainRegulatorModeConfig() function to control VOS bits. + + (+) void FLASH_PrefetchBufferCmd(FunctionalState NewState) + (+) void FLASH_InstructionCacheCmd(FunctionalState NewState) + (+) void FLASH_DataCacheCmd(FunctionalState NewState) + (+) void FLASH_InstructionCacheReset(void) + (+) void FLASH_DataCacheReset(void) + + [..] + The unlock sequence is not needed for these functions. + +@endverbatim + * @{ + */ + +/** + * @brief Sets the code latency value. + * @param FLASH_Latency: specifies the FLASH Latency value. + * This parameter can be one of the following values: + * @arg FLASH_Latency_0: FLASH Zero Latency cycle + * @arg FLASH_Latency_1: FLASH One Latency cycle + * @arg FLASH_Latency_2: FLASH Two Latency cycles + * @arg FLASH_Latency_3: FLASH Three Latency cycles + * @arg FLASH_Latency_4: FLASH Four Latency cycles + * @arg FLASH_Latency_5: FLASH Five Latency cycles + * @arg FLASH_Latency_6: FLASH Six Latency cycles + * @arg FLASH_Latency_7: FLASH Seven Latency cycles + * For STM32F40xx/41xx and STM32F427x/437x devices this parameter can be + * a value between FLASH_Latency_0 and FLASH_Latency_7. + * @retval None + */ +void FLASH_SetLatency(uint32_t FLASH_Latency) +{ + /* Check the parameters */ + assert_param(IS_FLASH_LATENCY(FLASH_Latency)); + + /* Perform Byte access to FLASH_ACR[8:0] to set the Latency value */ + *(__IO uint8_t *)ACR_BYTE0_ADDRESS = (uint8_t)FLASH_Latency; +} + +/** + * @brief Enables or disables the Prefetch Buffer. + * @param NewState: new state of the Prefetch Buffer. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_PrefetchBufferCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + /* Enable or disable the Prefetch Buffer */ + if(NewState != DISABLE) + { + FLASH->ACR |= FLASH_ACR_PRFTEN; + } + else + { + FLASH->ACR &= (~FLASH_ACR_PRFTEN); + } +} + +/** + * @brief Enables or disables the Instruction Cache feature. + * @param NewState: new state of the Instruction Cache. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_InstructionCacheCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if(NewState != DISABLE) + { + FLASH->ACR |= FLASH_ACR_ICEN; + } + else + { + FLASH->ACR &= (~FLASH_ACR_ICEN); + } +} + +/** + * @brief Enables or disables the Data Cache feature. + * @param NewState: new state of the Data Cache. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_DataCacheCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if(NewState != DISABLE) + { + FLASH->ACR |= FLASH_ACR_DCEN; + } + else + { + FLASH->ACR &= (~FLASH_ACR_DCEN); + } +} + +/** + * @brief Resets the Instruction Cache. + * @note This function must be used only when the Instruction Cache is disabled. + * @param None + * @retval None + */ +void FLASH_InstructionCacheReset(void) +{ + FLASH->ACR |= FLASH_ACR_ICRST; +} + +/** + * @brief Resets the Data Cache. + * @note This function must be used only when the Data Cache is disabled. + * @param None + * @retval None + */ +void FLASH_DataCacheReset(void) +{ + FLASH->ACR |= FLASH_ACR_DCRST; +} + +/** + * @} + */ + +/** @defgroup FLASH_Group2 FLASH Memory Programming functions + * @brief FLASH Memory Programming functions + * +@verbatim + =============================================================================== + ##### FLASH Memory Programming functions ##### + =============================================================================== + [..] + This group includes the following functions: + (+) void FLASH_Unlock(void) + (+) void FLASH_Lock(void) + (+) FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange) + (+) FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange) + (+) FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data) + (+) FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data) + (+) FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) + (+) FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data) + [..] + Any operation of erase or program should follow these steps: + (#) Call the FLASH_Unlock() function to enable the FLASH control register access + + (#) Call the desired function to erase sector(s) or program data + + (#) Call the FLASH_Lock() function to disable the FLASH control register access + (recommended to protect the FLASH memory against possible unwanted operation) + +@endverbatim + * @{ + */ + +/** + * @brief Unlocks the FLASH control register access + * @param None + * @retval None + */ +void FLASH_Unlock(void) +{ + if((FLASH->CR & FLASH_CR_LOCK) != RESET) + { + /* Authorize the FLASH Registers access */ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } +} + +/** + * @brief Locks the FLASH control register access + * @param None + * @retval None + */ +void FLASH_Lock(void) +{ + /* Set the LOCK Bit to lock the FLASH Registers access */ + FLASH->CR |= FLASH_CR_LOCK; +} + +/** + * @brief Erases a specified FLASH Sector. + * + * @note If an erase and a program operations are requested simustaneously, + * the erase operation is performed before the program one. + * + * @param FLASH_Sector: The Sector number to be erased. + * For STM32F40xx/41xx devices this parameter can be a value between + * FLASH_Sector_0 and FLASH_Sector_11. + * For STM32F427x/437x devices this parameter can be a value between + * FLASH_Sector_0 and FLASH_Sector_23. + * + * @param VoltageRange: The device voltage range which defines the erase parallelism. + * This parameter can be one of the following values: + * @arg VoltageRange_1: when the device voltage range is 1.8V to 2.1V, + * the operation will be done by byte (8-bit) + * @arg VoltageRange_2: when the device voltage range is 2.1V to 2.7V, + * the operation will be done by half word (16-bit) + * @arg VoltageRange_3: when the device voltage range is 2.7V to 3.6V, + * the operation will be done by word (32-bit) + * @arg VoltageRange_4: when the device voltage range is 2.7V to 3.6V + External Vpp, + * the operation will be done by double word (64-bit) + * + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange) +{ + uint32_t tmp_psize = 0x0; + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_FLASH_SECTOR(FLASH_Sector)); + assert_param(IS_VOLTAGERANGE(VoltageRange)); + + if(VoltageRange == VoltageRange_1) + { + tmp_psize = FLASH_PSIZE_BYTE; + } + else if(VoltageRange == VoltageRange_2) + { + tmp_psize = FLASH_PSIZE_HALF_WORD; + } + else if(VoltageRange == VoltageRange_3) + { + tmp_psize = FLASH_PSIZE_WORD; + } + else + { + tmp_psize = FLASH_PSIZE_DOUBLE_WORD; + } + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase the sector */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR &= SECTOR_MASK; + FLASH->CR |= FLASH_CR_SER | FLASH_Sector; + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + /* if the erase operation is completed, disable the SER Bit */ + FLASH->CR &= (~FLASH_CR_SER); + FLASH->CR &= SECTOR_MASK; + } + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases all FLASH Sectors. + * + * @note If an erase and a program operations are requested simustaneously, + * the erase operation is performed before the program one. + * + * @param VoltageRange: The device voltage range which defines the erase parallelism. + * This parameter can be one of the following values: + * @arg VoltageRange_1: when the device voltage range is 1.8V to 2.1V, + * the operation will be done by byte (8-bit) + * @arg VoltageRange_2: when the device voltage range is 2.1V to 2.7V, + * the operation will be done by half word (16-bit) + * @arg VoltageRange_3: when the device voltage range is 2.7V to 3.6V, + * the operation will be done by word (32-bit) + * @arg VoltageRange_4: when the device voltage range is 2.7V to 3.6V + External Vpp, + * the operation will be done by double word (64-bit) + * + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange) +{ + uint32_t tmp_psize = 0x0; + FLASH_Status status = FLASH_COMPLETE; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + assert_param(IS_VOLTAGERANGE(VoltageRange)); + + if(VoltageRange == VoltageRange_1) + { + tmp_psize = FLASH_PSIZE_BYTE; + } + else if(VoltageRange == VoltageRange_2) + { + tmp_psize = FLASH_PSIZE_HALF_WORD; + } + else if(VoltageRange == VoltageRange_3) + { + tmp_psize = FLASH_PSIZE_WORD; + } + else + { + tmp_psize = FLASH_PSIZE_DOUBLE_WORD; + } + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to erase all sectors */ +#if defined (STM32F427X) + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR |= (FLASH_CR_MER1 | FLASH_CR_MER2); + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + /* if the erase operation is completed, disable the MER Bit */ + FLASH->CR &= ~(FLASH_CR_MER1 | FLASH_CR_MER2); +#endif /* STM32F427X */ + +#ifdef STM32F40XX + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= tmp_psize; + FLASH->CR |= FLASH_CR_MER; + FLASH->CR |= FLASH_CR_STRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + /* if the erase operation is completed, disable the MER Bit */ + FLASH->CR &= (~FLASH_CR_MER); +#endif /* STM32F40XX */ + + } + /* Return the Erase Status */ + return status; +} + +/** + * @brief Programs a double word (64-bit) at a specified address. + * @note This function must be used when the device voltage range is from + * 2.7V to 3.6V and an External Vpp is present. + * + * @note If an erase and a program operations are requested simustaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_DOUBLE_WORD; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint64_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a word (32-bit) at a specified address. + * + * @note This function must be used when the device voltage range is from 2.7V to 3.6V. + * + * @note If an erase and a program operations are requested simustaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * This parameter can be any address in Program memory zone or in OTP zone. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_WORD; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint32_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a half word (16-bit) at a specified address. + * @note This function must be used when the device voltage range is from 2.1V to 3.6V. + * + * @note If an erase and a program operations are requested simustaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * This parameter can be any address in Program memory zone or in OTP zone. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_HALF_WORD; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint16_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a byte (8-bit) at a specified address. + * @note This function can be used within all the device supply voltage ranges. + * + * @note If an erase and a program operations are requested simustaneously, + * the erase operation is performed before the program one. + * + * @param Address: specifies the address to be programmed. + * This parameter can be any address in Program memory zone or in OTP zone. + * @param Data: specifies the data to be programmed. + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new data */ + FLASH->CR &= CR_PSIZE_MASK; + FLASH->CR |= FLASH_PSIZE_BYTE; + FLASH->CR |= FLASH_CR_PG; + + *(__IO uint8_t*)Address = Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + /* if the program operation is completed, disable the PG Bit */ + FLASH->CR &= (~FLASH_CR_PG); + } + + /* Return the Program Status */ + return status; +} + +/** + * @} + */ + +/** @defgroup FLASH_Group3 Option Bytes Programming functions + * @brief Option Bytes Programming functions + * +@verbatim + =============================================================================== + ##### Option Bytes Programming functions ##### + =============================================================================== + [..] + This group includes the following functions: + (+) void FLASH_OB_Unlock(void) + (+) void FLASH_OB_Lock(void) + (+) void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) + (+) void FLASH_OB_WRP1Config(uint32_t OB_WRP, FunctionalState NewState) + (+) void FLASH_OB_RDPConfig(uint8_t OB_RDP) + (+) void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY) + (+) void FLASH_OB_BORConfig(uint8_t OB_BOR) + (+) FLASH_Status FLASH_ProgramOTP(uint32_t Address, uint32_t Data) + (+) FLASH_Status FLASH_OB_Launch(void) + (+) uint32_t FLASH_OB_GetUser(void) + (+) uint8_t FLASH_OB_GetWRP(void) + (+) uint8_t FLASH_OB_GetWRP1(void) + (+) uint8_t FLASH_OB_GetRDP(void) + (+) uint8_t FLASH_OB_GetBOR(void) + [..] + Any operation of erase or program should follow these steps: + (#) Call the FLASH_OB_Unlock() function to enable the FLASH option control + register access + + (#) Call one or several functions to program the desired Option Bytes: + (++) void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) + => to Enable/Disable the desired sector write protection + (++) void FLASH_OB_RDPConfig(uint8_t OB_RDP) => to set the desired read + Protection Level + (++) void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY) + => to configure the user Option Bytes. + (++) void FLASH_OB_BORConfig(uint8_t OB_BOR) => to set the BOR Level + + (#) Once all needed Option Bytes to be programmed are correctly written, + call the FLASH_OB_Launch() function to launch the Option Bytes + programming process. + + -@- When changing the IWDG mode from HW to SW or from SW to HW, a system + reset is needed to make the change effective. + + (#) Call the FLASH_OB_Lock() function to disable the FLASH option control + register access (recommended to protect the Option Bytes against + possible unwanted operations) + +@endverbatim + * @{ + */ + +/** + * @brief Unlocks the FLASH Option Control Registers access. + * @param None + * @retval None + */ +void FLASH_OB_Unlock(void) +{ + if((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != RESET) + { + /* Authorizes the Option Byte register programming */ + FLASH->OPTKEYR = FLASH_OPT_KEY1; + FLASH->OPTKEYR = FLASH_OPT_KEY2; + } +} + +/** + * @brief Locks the FLASH Option Control Registers access. + * @param None + * @retval None + */ +void FLASH_OB_Lock(void) +{ + /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */ + FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; +} + +/** + * @brief Enables or disables the write protection of the desired sectors + * + * @note When the memory read protection level is selected (RDP level = 1), + * it is not possible to program or erase the flash sector i if CortexM4 + * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 + * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). + * + * @param OB_WRP: specifies the sector(s) to be write protected or unprotected. + * This parameter can be one of the following values: + * @arg OB_WRP: A value between OB_WRP_Sector0 and OB_WRP_Sector11 + * @arg OB_WRP_Sector_All + * @param Newstate: new state of the Write Protection. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_OB_WRP(OB_WRP)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + if(NewState != DISABLE) + { + *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS &= (~OB_WRP); + } + else + { + *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS |= (uint16_t)OB_WRP; + } + } +} + +/** + * @brief Enables or disables the write protection of the desired sectors + * @note This function can be used only for STM32F427x/437x devices. + * @note When the memory read out protection is selected (RDP level = 1), + * it is not possible to program or erase the flash sector i if CortexM4 + * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 + * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). + * + * @param OB_WRP: specifies the sector(s) to be write protected or unprotected. + * This parameter can be one of the following values: + * @arg OB_WRP: A value between OB_WRP_Sector12 and OB_WRP_Sector23 + * @arg OB_WRP_Sector_All + * @param Newstate: new state of the Write Protection. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void FLASH_OB_WRP1Config(uint32_t OB_WRP, FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_OB_WRP(OB_WRP)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + if(NewState != DISABLE) + { + *(__IO uint16_t*)OPTCR1_BYTE2_ADDRESS &= (~OB_WRP); + } + else + { + *(__IO uint16_t*)OPTCR1_BYTE2_ADDRESS |= (uint16_t)OB_WRP; + } + } +} + +/** + * @brief Sets the read protection level. + * @param OB_RDP: specifies the read protection level. + * This parameter can be one of the following values: + * @arg OB_RDP_Level_0: No protection + * @arg OB_RDP_Level_1: Read protection of the memory + * @arg OB_RDP_Level_2: Full chip protection + * + * !!!Warning!!! When enabling OB_RDP level 2 it's no more possible to go back to level 1 or 0 + * + * @retval None + */ +void FLASH_OB_RDPConfig(uint8_t OB_RDP) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_OB_RDP(OB_RDP)); + + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + *(__IO uint8_t*)OPTCR_BYTE1_ADDRESS = OB_RDP; + + } +} + +/** + * @brief Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. + * @param OB_IWDG: Selects the IWDG mode + * This parameter can be one of the following values: + * @arg OB_IWDG_SW: Software IWDG selected + * @arg OB_IWDG_HW: Hardware IWDG selected + * @param OB_STOP: Reset event when entering STOP mode. + * This parameter can be one of the following values: + * @arg OB_STOP_NoRST: No reset generated when entering in STOP + * @arg OB_STOP_RST: Reset generated when entering in STOP + * @param OB_STDBY: Reset event when entering Standby mode. + * This parameter can be one of the following values: + * @arg OB_STDBY_NoRST: No reset generated when entering in STANDBY + * @arg OB_STDBY_RST: Reset generated when entering in STANDBY + * @retval None + */ +void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY) +{ + uint8_t optiontmp = 0xFF; + FLASH_Status status = FLASH_COMPLETE; + + /* Check the parameters */ + assert_param(IS_OB_IWDG_SOURCE(OB_IWDG)); + assert_param(IS_OB_STOP_SOURCE(OB_STOP)); + assert_param(IS_OB_STDBY_SOURCE(OB_STDBY)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + if(status == FLASH_COMPLETE) + { + /* Mask OPTLOCK, OPTSTRT and BOR_LEV bits */ + optiontmp = (uint8_t)((*(__IO uint8_t *)OPTCR_BYTE0_ADDRESS) & (uint8_t)0x0F); + + /* Update User Option Byte */ + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS = OB_IWDG | (uint8_t)(OB_STDBY | (uint8_t)(OB_STOP | ((uint8_t)optiontmp))); + } +} + +/** + * @brief Sets the BOR Level. + * @param OB_BOR: specifies the Option Bytes BOR Reset Level. + * This parameter can be one of the following values: + * @arg OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V + * @arg OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V + * @arg OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V + * @arg OB_BOR_OFF: Supply voltage ranges from 1.62 to 2.1 V + * @retval None + */ +void FLASH_OB_BORConfig(uint8_t OB_BOR) +{ + /* Check the parameters */ + assert_param(IS_OB_BOR(OB_BOR)); + + /* Set the BOR Level */ + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS &= (~FLASH_OPTCR_BOR_LEV); + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= OB_BOR; + +} + +/** + * @brief Launch the option byte loading. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_OB_Launch(void) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Set the OPTSTRT bit in OPTCR register */ + *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= FLASH_OPTCR_OPTSTRT; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(); + + return status; +} + +/** + * @brief Returns the FLASH User Option Bytes values. + * @param None + * @retval The FLASH User Option Bytes values: IWDG_SW(Bit0), RST_STOP(Bit1) + * and RST_STDBY(Bit2). + */ +uint8_t FLASH_OB_GetUser(void) +{ + /* Return the User Option Byte */ + return (uint8_t)(FLASH->OPTCR >> 5); +} + +/** + * @brief Returns the FLASH Write Protection Option Bytes value. + * @param None + * @retval The FLASH Write Protection Option Bytes value + */ +uint16_t FLASH_OB_GetWRP(void) +{ + /* Return the FLASH write protection Register value */ + return (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS)); +} + +/** + * @brief Returns the FLASH Write Protection Option Bytes value. + * @note This function can be used only for STM32F427x/437x devices. + * @param None + * @retval The FLASH Write Protection Option Bytes value + */ +uint16_t FLASH_OB_GetWRP1(void) +{ + /* Return the FLASH write protection Register value */ + return (*(__IO uint16_t *)(OPTCR1_BYTE2_ADDRESS)); +} + +/** + * @brief Returns the FLASH Read Protection level. + * @param None + * @retval FLASH ReadOut Protection Status: + * - SET, when OB_RDP_Level_1 or OB_RDP_Level_2 is set + * - RESET, when OB_RDP_Level_0 is set + */ +FlagStatus FLASH_OB_GetRDP(void) +{ + FlagStatus readstatus = RESET; + + if ((*(__IO uint8_t*)(OPTCR_BYTE1_ADDRESS) != (uint8_t)OB_RDP_Level_0)) + { + readstatus = SET; + } + else + { + readstatus = RESET; + } + return readstatus; +} + +/** + * @brief Returns the FLASH BOR level. + * @param None + * @retval The FLASH BOR level: + * - OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V + * - OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V + * - OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V + * - OB_BOR_OFF : Supply voltage ranges from 1.62 to 2.1 V + */ +uint8_t FLASH_OB_GetBOR(void) +{ + /* Return the FLASH BOR level */ + return (uint8_t)(*(__IO uint8_t *)(OPTCR_BYTE0_ADDRESS) & (uint8_t)0x0C); +} + +/** + * @} + */ + +/** @defgroup FLASH_Group4 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified FLASH interrupts. + * @param FLASH_IT: specifies the FLASH interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg FLASH_IT_ERR: FLASH Error Interrupt + * @arg FLASH_IT_EOP: FLASH end of operation Interrupt + * @retval None + */ +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FLASH_IT(FLASH_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if(NewState != DISABLE) + { + /* Enable the interrupt sources */ + FLASH->CR |= FLASH_IT; + } + else + { + /* Disable the interrupt sources */ + FLASH->CR &= ~(uint32_t)FLASH_IT; + } +} + +/** + * @brief Checks whether the specified FLASH flag is set or not. + * @param FLASH_FLAG: specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH operation Error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming Alignment error flag + * @arg FLASH_FLAG_PGPERR: FLASH Programming Parallelism error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming Sequence error flag + * @arg FLASH_FLAG_BSY: FLASH Busy flag + * @retval The new state of FLASH_FLAG (SET or RESET). + */ +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)); + + if((FLASH->SR & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the new state of FLASH_FLAG (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Clears the FLASH's pending flags. + * @param FLASH_FLAG: specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH operation Error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming Alignment error flag + * @arg FLASH_FLAG_PGPERR: FLASH Programming Parallelism error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming Sequence error flag + * @retval None + */ +void FLASH_ClearFlag(uint32_t FLASH_FLAG) +{ + /* Check the parameters */ + assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)); + + /* Clear the flags */ + FLASH->SR = FLASH_FLAG; +} + +/** + * @brief Returns the FLASH Status. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_GetStatus(void) +{ + FLASH_Status flashstatus = FLASH_COMPLETE; + + if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY) + { + flashstatus = FLASH_BUSY; + } + else + { + if((FLASH->SR & FLASH_FLAG_WRPERR) != (uint32_t)0x00) + { + flashstatus = FLASH_ERROR_WRP; + } + else + { + if((FLASH->SR & (uint32_t)0xEF) != (uint32_t)0x00) + { + flashstatus = FLASH_ERROR_PROGRAM; + } + else + { + if((FLASH->SR & FLASH_FLAG_OPERR) != (uint32_t)0x00) + { + flashstatus = FLASH_ERROR_OPERATION; + } + else + { + flashstatus = FLASH_COMPLETE; + } + } + } + } + /* Return the FLASH Status */ + return flashstatus; +} + +/** + * @brief Waits for a FLASH operation to complete. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM, + * FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE. + */ +FLASH_Status FLASH_WaitForLastOperation(void) +{ + __IO FLASH_Status status = FLASH_COMPLETE; + + /* Check for the FLASH Status */ + status = FLASH_GetStatus(); + + /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + Even if the FLASH operation fails, the BUSY flag will be reset and an error + flag will be set */ + while(status == FLASH_BUSY) + { + status = FLASH_GetStatus(); + } + /* Return the operation status */ + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_flash.h b/stm/lib/stm32f4xx_flash.h new file mode 100644 index 000000000..55380b7ab --- /dev/null +++ b/stm/lib/stm32f4xx_flash.h @@ -0,0 +1,390 @@ +/** + ****************************************************************************** + * @file stm32f4xx_flash.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file contains all the functions prototypes for the FLASH + * firmware library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_FLASH_H +#define __STM32F4xx_FLASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** + * @brief FLASH Status + */ +typedef enum +{ + FLASH_BUSY = 1, + FLASH_ERROR_PGS, + FLASH_ERROR_PGP, + FLASH_ERROR_PGA, + FLASH_ERROR_WRP, + FLASH_ERROR_PROGRAM, + FLASH_ERROR_OPERATION, + FLASH_COMPLETE +}FLASH_Status; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup FLASH_Exported_Constants + * @{ + */ + +/** @defgroup Flash_Latency + * @{ + */ +#define FLASH_Latency_0 ((uint8_t)0x0000) /*!< FLASH Zero Latency cycle */ +#define FLASH_Latency_1 ((uint8_t)0x0001) /*!< FLASH One Latency cycle */ +#define FLASH_Latency_2 ((uint8_t)0x0002) /*!< FLASH Two Latency cycles */ +#define FLASH_Latency_3 ((uint8_t)0x0003) /*!< FLASH Three Latency cycles */ +#define FLASH_Latency_4 ((uint8_t)0x0004) /*!< FLASH Four Latency cycles */ +#define FLASH_Latency_5 ((uint8_t)0x0005) /*!< FLASH Five Latency cycles */ +#define FLASH_Latency_6 ((uint8_t)0x0006) /*!< FLASH Six Latency cycles */ +#define FLASH_Latency_7 ((uint8_t)0x0007) /*!< FLASH Seven Latency cycles */ + +#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_Latency_0) || \ + ((LATENCY) == FLASH_Latency_1) || \ + ((LATENCY) == FLASH_Latency_2) || \ + ((LATENCY) == FLASH_Latency_3) || \ + ((LATENCY) == FLASH_Latency_4) || \ + ((LATENCY) == FLASH_Latency_5) || \ + ((LATENCY) == FLASH_Latency_6) || \ + ((LATENCY) == FLASH_Latency_7)) + +/** + * @} + */ + +/** @defgroup FLASH_Voltage_Range + * @{ + */ +#define VoltageRange_1 ((uint8_t)0x00) /*!< Device operating range: 1.8V to 2.1V */ +#define VoltageRange_2 ((uint8_t)0x01) /*!= 0x08000000) && ((ADDRESS) < 0x081FFFFF)) ||\ + (((ADDRESS) >= 0x1FFF7800) && ((ADDRESS) < 0x1FFF7A0F))) +/** + * @} + */ + +/** @defgroup Option_Bytes_Write_Protection + * @{ + */ +#define OB_WRP_Sector_0 ((uint32_t)0x00000001) /*!< Write protection of Sector0 */ +#define OB_WRP_Sector_1 ((uint32_t)0x00000002) /*!< Write protection of Sector1 */ +#define OB_WRP_Sector_2 ((uint32_t)0x00000004) /*!< Write protection of Sector2 */ +#define OB_WRP_Sector_3 ((uint32_t)0x00000008) /*!< Write protection of Sector3 */ +#define OB_WRP_Sector_4 ((uint32_t)0x00000010) /*!< Write protection of Sector4 */ +#define OB_WRP_Sector_5 ((uint32_t)0x00000020) /*!< Write protection of Sector5 */ +#define OB_WRP_Sector_6 ((uint32_t)0x00000040) /*!< Write protection of Sector6 */ +#define OB_WRP_Sector_7 ((uint32_t)0x00000080) /*!< Write protection of Sector7 */ +#define OB_WRP_Sector_8 ((uint32_t)0x00000100) /*!< Write protection of Sector8 */ +#define OB_WRP_Sector_9 ((uint32_t)0x00000200) /*!< Write protection of Sector9 */ +#define OB_WRP_Sector_10 ((uint32_t)0x00000400) /*!< Write protection of Sector10 */ +#define OB_WRP_Sector_11 ((uint32_t)0x00000800) /*!< Write protection of Sector11 */ +#define OB_WRP_Sector_12 ((uint32_t)0x00000001) /*!< Write protection of Sector12 */ +#define OB_WRP_Sector_13 ((uint32_t)0x00000002) /*!< Write protection of Sector13 */ +#define OB_WRP_Sector_14 ((uint32_t)0x00000004) /*!< Write protection of Sector14 */ +#define OB_WRP_Sector_15 ((uint32_t)0x00000008) /*!< Write protection of Sector15 */ +#define OB_WRP_Sector_16 ((uint32_t)0x00000010) /*!< Write protection of Sector16 */ +#define OB_WRP_Sector_17 ((uint32_t)0x00000020) /*!< Write protection of Sector17 */ +#define OB_WRP_Sector_18 ((uint32_t)0x00000040) /*!< Write protection of Sector18 */ +#define OB_WRP_Sector_19 ((uint32_t)0x00000080) /*!< Write protection of Sector19 */ +#define OB_WRP_Sector_20 ((uint32_t)0x00000100) /*!< Write protection of Sector20 */ +#define OB_WRP_Sector_21 ((uint32_t)0x00000200) /*!< Write protection of Sector21 */ +#define OB_WRP_Sector_22 ((uint32_t)0x00000400) /*!< Write protection of Sector22 */ +#define OB_WRP_Sector_23 ((uint32_t)0x00000800) /*!< Write protection of Sector23 */ +#define OB_WRP_Sector_All ((uint32_t)0x00000FFF) /*!< Write protection of all Sectors */ + +#define IS_OB_WRP(SECTOR)((((SECTOR) & (uint32_t)0xFFFFF000) == 0x00000000) && ((SECTOR) != 0x00000000)) +/** + * @} + */ + +/** @defgroup FLASH_Option_Bytes_Read_Protection + * @{ + */ +#define OB_RDP_Level_0 ((uint8_t)0xAA) +#define OB_RDP_Level_1 ((uint8_t)0x55) +/*#define OB_RDP_Level_2 ((uint8_t)0xCC)*/ /*!< Warning: When enabling read protection level 2 + it's no more possible to go back to level 1 or 0 */ +#define IS_OB_RDP(LEVEL) (((LEVEL) == OB_RDP_Level_0)||\ + ((LEVEL) == OB_RDP_Level_1))/*||\ + ((LEVEL) == OB_RDP_Level_2))*/ +/** + * @} + */ + +/** @defgroup FLASH_Option_Bytes_IWatchdog + * @{ + */ +#define OB_IWDG_SW ((uint8_t)0x20) /*!< Software IWDG selected */ +#define OB_IWDG_HW ((uint8_t)0x00) /*!< Hardware IWDG selected */ +#define IS_OB_IWDG_SOURCE(SOURCE) (((SOURCE) == OB_IWDG_SW) || ((SOURCE) == OB_IWDG_HW)) +/** + * @} + */ + +/** @defgroup FLASH_Option_Bytes_nRST_STOP + * @{ + */ +#define OB_STOP_NoRST ((uint8_t)0x40) /*!< No reset generated when entering in STOP */ +#define OB_STOP_RST ((uint8_t)0x00) /*!< Reset generated when entering in STOP */ +#define IS_OB_STOP_SOURCE(SOURCE) (((SOURCE) == OB_STOP_NoRST) || ((SOURCE) == OB_STOP_RST)) +/** + * @} + */ + + +/** @defgroup FLASH_Option_Bytes_nRST_STDBY + * @{ + */ +#define OB_STDBY_NoRST ((uint8_t)0x80) /*!< No reset generated when entering in STANDBY */ +#define OB_STDBY_RST ((uint8_t)0x00) /*!< Reset generated when entering in STANDBY */ +#define IS_OB_STDBY_SOURCE(SOURCE) (((SOURCE) == OB_STDBY_NoRST) || ((SOURCE) == OB_STDBY_RST)) +/** + * @} + */ + +/** @defgroup FLASH_BOR_Reset_Level + * @{ + */ +#define OB_BOR_LEVEL3 ((uint8_t)0x00) /*!< Supply voltage ranges from 2.70 to 3.60 V */ +#define OB_BOR_LEVEL2 ((uint8_t)0x04) /*!< Supply voltage ranges from 2.40 to 2.70 V */ +#define OB_BOR_LEVEL1 ((uint8_t)0x08) /*!< Supply voltage ranges from 2.10 to 2.40 V */ +#define OB_BOR_OFF ((uint8_t)0x0C) /*!< Supply voltage ranges from 1.62 to 2.10 V */ +#define IS_OB_BOR(LEVEL) (((LEVEL) == OB_BOR_LEVEL1) || ((LEVEL) == OB_BOR_LEVEL2) ||\ + ((LEVEL) == OB_BOR_LEVEL3) || ((LEVEL) == OB_BOR_OFF)) +/** + * @} + */ + +/** @defgroup FLASH_Interrupts + * @{ + */ +#define FLASH_IT_EOP ((uint32_t)0x01000000) /*!< End of FLASH Operation Interrupt source */ +#define FLASH_IT_ERR ((uint32_t)0x02000000) /*!< Error Interrupt source */ +#define IS_FLASH_IT(IT) ((((IT) & (uint32_t)0xFCFFFFFF) == 0x00000000) && ((IT) != 0x00000000)) +/** + * @} + */ + +/** @defgroup FLASH_Flags + * @{ + */ +#define FLASH_FLAG_EOP ((uint32_t)0x00000001) /*!< FLASH End of Operation flag */ +#define FLASH_FLAG_OPERR ((uint32_t)0x00000002) /*!< FLASH operation Error flag */ +#define FLASH_FLAG_WRPERR ((uint32_t)0x00000010) /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_PGAERR ((uint32_t)0x00000020) /*!< FLASH Programming Alignment error flag */ +#define FLASH_FLAG_PGPERR ((uint32_t)0x00000040) /*!< FLASH Programming Parallelism error flag */ +#define FLASH_FLAG_PGSERR ((uint32_t)0x00000080) /*!< FLASH Programming Sequence error flag */ +#define FLASH_FLAG_BSY ((uint32_t)0x00010000) /*!< FLASH Busy flag */ +#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFE0C) == 0x00000000) && ((FLAG) != 0x00000000)) +#define IS_FLASH_GET_FLAG(FLAG) (((FLAG) == FLASH_FLAG_EOP) || ((FLAG) == FLASH_FLAG_OPERR) || \ + ((FLAG) == FLASH_FLAG_WRPERR) || ((FLAG) == FLASH_FLAG_PGAERR) || \ + ((FLAG) == FLASH_FLAG_PGPERR) || ((FLAG) == FLASH_FLAG_PGSERR) || \ + ((FLAG) == FLASH_FLAG_BSY)) +/** + * @} + */ + +/** @defgroup FLASH_Program_Parallelism + * @{ + */ +#define FLASH_PSIZE_BYTE ((uint32_t)0x00000000) +#define FLASH_PSIZE_HALF_WORD ((uint32_t)0x00000100) +#define FLASH_PSIZE_WORD ((uint32_t)0x00000200) +#define FLASH_PSIZE_DOUBLE_WORD ((uint32_t)0x00000300) +#define CR_PSIZE_MASK ((uint32_t)0xFFFFFCFF) +/** + * @} + */ + +/** @defgroup FLASH_Keys + * @{ + */ +#define RDP_KEY ((uint16_t)0x00A5) +#define FLASH_KEY1 ((uint32_t)0x45670123) +#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) +#define FLASH_OPT_KEY1 ((uint32_t)0x08192A3B) +#define FLASH_OPT_KEY2 ((uint32_t)0x4C5D6E7F) +/** + * @} + */ + +/** + * @brief ACR register byte 0 (Bits[7:0]) base address + */ +#define ACR_BYTE0_ADDRESS ((uint32_t)0x40023C00) +/** + * @brief OPTCR register byte 0 (Bits[7:0]) base address + */ +#define OPTCR_BYTE0_ADDRESS ((uint32_t)0x40023C14) +/** + * @brief OPTCR register byte 1 (Bits[15:8]) base address + */ +#define OPTCR_BYTE1_ADDRESS ((uint32_t)0x40023C15) +/** + * @brief OPTCR register byte 2 (Bits[23:16]) base address + */ +#define OPTCR_BYTE2_ADDRESS ((uint32_t)0x40023C16) +/** + * @brief OPTCR register byte 3 (Bits[31:24]) base address + */ +#define OPTCR_BYTE3_ADDRESS ((uint32_t)0x40023C17) + +/** + * @brief OPTCR1 register byte 0 (Bits[7:0]) base address + */ +#define OPTCR1_BYTE2_ADDRESS ((uint32_t)0x40023C1A) + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* FLASH Interface configuration functions ************************************/ +void FLASH_SetLatency(uint32_t FLASH_Latency); +void FLASH_PrefetchBufferCmd(FunctionalState NewState); +void FLASH_InstructionCacheCmd(FunctionalState NewState); +void FLASH_DataCacheCmd(FunctionalState NewState); +void FLASH_InstructionCacheReset(void); +void FLASH_DataCacheReset(void); + +/* FLASH Memory Programming functions *****************************************/ +void FLASH_Unlock(void); +void FLASH_Lock(void); +FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange); +FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange); +FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data); +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); +FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data); + +/* Option Bytes Programming functions *****************************************/ +void FLASH_OB_Unlock(void); +void FLASH_OB_Lock(void); +void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState); +void FLASH_OB_WRP1Config(uint32_t OB_WRP, FunctionalState NewState); +void FLASH_OB_RDPConfig(uint8_t OB_RDP); +void FLASH_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_STOP, uint8_t OB_STDBY); +void FLASH_OB_BORConfig(uint8_t OB_BOR); +FLASH_Status FLASH_OB_Launch(void); +uint8_t FLASH_OB_GetUser(void); +uint16_t FLASH_OB_GetWRP(void); +uint16_t FLASH_OB_GetWRP1(void); +FlagStatus FLASH_OB_GetRDP(void); +uint8_t FLASH_OB_GetBOR(void); + +/* Interrupts and flags management functions **********************************/ +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState); +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG); +void FLASH_ClearFlag(uint32_t FLASH_FLAG); +FLASH_Status FLASH_GetStatus(void); +FLASH_Status FLASH_WaitForLastOperation(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_FLASH_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_gpio.c b/stm/lib/stm32f4xx_gpio.c new file mode 100644 index 000000000..bdd91e665 --- /dev/null +++ b/stm/lib/stm32f4xx_gpio.c @@ -0,0 +1,585 @@ +/** + ****************************************************************************** + * @file stm32f4xx_gpio.c + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file provides firmware functions to manage the following + * functionalities of the GPIO peripheral: + * + Initialization and Configuration + * + GPIO Read and Write + * + GPIO Alternate functions configuration + * +@verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + (#) Enable the GPIO AHB clock using the following function + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE); + + (#) Configure the GPIO pin(s) using GPIO_Init() + Four possible configuration are available for each pin: + (++) Input: Floating, Pull-up, Pull-down. + (++) Output: Push-Pull (Pull-up, Pull-down or no Pull) + Open Drain (Pull-up, Pull-down or no Pull). In output mode, the speed + is configurable: 2 MHz, 25 MHz, 50 MHz or 100 MHz. + (++) Alternate Function: Push-Pull (Pull-up, Pull-down or no Pull) Open + Drain (Pull-up, Pull-down or no Pull). + (++) Analog: required mode when a pin is to be used as ADC channel or DAC + output. + + (#) Peripherals alternate function: + (++) For ADC and DAC, configure the desired pin in analog mode using + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AN; + (+++) For other peripherals (TIM, USART...): + (+++) Connect the pin to the desired peripherals' Alternate + Function (AF) using GPIO_PinAFConfig() function + (+++) Configure the desired pin in alternate function mode using + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF + (+++) Select the type, pull-up/pull-down and output speed via + GPIO_PuPd, GPIO_OType and GPIO_Speed members + (+++) Call GPIO_Init() function + + (#) To get the level of a pin configured in input mode use GPIO_ReadInputDataBit() + + (#) To set/reset the level of a pin configured in output mode use + GPIO_SetBits()/GPIO_ResetBits() + + (#) During and just after reset, the alternate functions are not + active and the GPIO pins are configured in input floating mode (except JTAG + pins). + + (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose + (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has + priority over the GPIO function. + + (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as + general purpose PH0 and PH1, respectively, when the HSE oscillator is off. + The HSE has priority over the GPIO function. + +@endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_conf.h" +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_rcc.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup GPIO + * @brief GPIO driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup GPIO_Private_Functions + * @{ + */ + +/** @defgroup GPIO_Group1 Initialization and Configuration + * @brief Initialization and Configuration + * +@verbatim + =============================================================================== + ##### Initialization and Configuration ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief De-initializes the GPIOx peripheral registers to their default reset values. + * @note By default, The GPIO pins are configured in input floating mode (except JTAG pins). + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @retval None + */ +void GPIO_DeInit(GPIO_TypeDef* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + if (GPIOx == GPIOA) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE); + } + else if (GPIOx == GPIOB) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, DISABLE); + } + else if (GPIOx == GPIOC) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, DISABLE); + } + else if (GPIOx == GPIOD) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, DISABLE); + } + else if (GPIOx == GPIOE) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, DISABLE); + } + else if (GPIOx == GPIOF) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, DISABLE); + } + else if (GPIOx == GPIOG) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, DISABLE); + } + else if (GPIOx == GPIOH) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, DISABLE); + } + else + { + if (GPIOx == GPIOI) + { + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, ENABLE); + RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, DISABLE); + } + } +} + +/** + * @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that contains + * the configuration information for the specified GPIO peripheral. + * @retval None + */ +void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) +{ + uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); + assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); + assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd)); + + /* ------------------------- Configure the port pins ---------------- */ + /*-- GPIO Mode Configuration --*/ + for (pinpos = 0x00; pinpos < 0x10; pinpos++) + { + pos = ((uint32_t)0x01) << pinpos; + /* Get the port pins position */ + currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; + + if (currentpin == pos) + { + GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (pinpos * 2)); + GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2)); + + if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF)) + { + /* Check Speed mode parameters */ + assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); + + /* Speed mode configuration */ + GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2)); + GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2)); + + /* Check Output mode parameters */ + assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType)); + + /* Output mode configuration*/ + GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ; + GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos)); + } + + /* Pull-up Pull down resistor configuration*/ + GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2)); + GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2)); + } + } +} + +/** + * @brief Fills each GPIO_InitStruct member with its default value. + * @param GPIO_InitStruct : pointer to a GPIO_InitTypeDef structure which will be initialized. + * @retval None + */ +void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct) +{ + /* Reset GPIO init structure parameters values */ + GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All; + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStruct->GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL; +} + +/** + * @brief Locks GPIO Pins configuration registers. + * @note The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR, + * GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH. + * @note The configuration of the locked GPIO pins can no longer be modified + * until the next reset. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_Pin: specifies the port bit to be locked. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + __IO uint32_t tmp = 0x00010000; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + tmp |= GPIO_Pin; + /* Set LCKK bit */ + GPIOx->LCKR = tmp; + /* Reset LCKK bit */ + GPIOx->LCKR = GPIO_Pin; + /* Set LCKK bit */ + GPIOx->LCKR = tmp; + /* Read LCKK bit*/ + tmp = GPIOx->LCKR; + /* Read LCKK bit*/ + tmp = GPIOx->LCKR; +} + +/** + * @} + */ + +/** @defgroup GPIO_Group2 GPIO Read and Write + * @brief GPIO Read and Write + * +@verbatim + =============================================================================== + ##### GPIO Read and Write ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Reads the specified input port pin. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_Pin: specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @retval The input port pin value. + */ +uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint8_t bitstatus = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); + + if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO input data port. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @retval GPIO input data port value. + */ +uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->IDR); +} + +/** + * @brief Reads the specified output data port bit. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_Pin: specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @retval The output port pin value. + */ +uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint8_t bitstatus = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); + + if (((GPIOx->ODR) & GPIO_Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO output data port. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @retval GPIO output data port value. + */ +uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->ODR); +} + +/** + * @brief Sets the selected data port bits. + * @note This functions uses GPIOx_BSRR register to allow atomic read/modify + * accesses. In this way, there is no risk of an IRQ occurring between + * the read and the modify access. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_Pin: specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + GPIOx->BSRRL = GPIO_Pin; +} + +/** + * @brief Clears the selected data port bits. + * @note This functions uses GPIOx_BSRR register to allow atomic read/modify + * accesses. In this way, there is no risk of an IRQ occurring between + * the read and the modify access. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_Pin: specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + GPIOx->BSRRH = GPIO_Pin; +} + +/** + * @brief Sets or clears the selected data port bit. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_Pin: specifies the port bit to be written. + * This parameter can be one of GPIO_Pin_x where x can be (0..15). + * @param BitVal: specifies the value to be written to the selected bit. + * This parameter can be one of the BitAction enum values: + * @arg Bit_RESET: to clear the port pin + * @arg Bit_SET: to set the port pin + * @retval None + */ +void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); + assert_param(IS_GPIO_BIT_ACTION(BitVal)); + + if (BitVal != Bit_RESET) + { + GPIOx->BSRRL = GPIO_Pin; + } + else + { + GPIOx->BSRRH = GPIO_Pin ; + } +} + +/** + * @brief Writes data to the specified GPIO data port. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param PortVal: specifies the value to be written to the port output data register. + * @retval None + */ +void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + GPIOx->ODR = PortVal; +} + +/** + * @brief Toggles the specified GPIO pins.. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_Pin: Specifies the pins to be toggled. + * @retval None + */ +void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + GPIOx->ODR ^= GPIO_Pin; +} + +/** + * @} + */ + +/** @defgroup GPIO_Group3 GPIO Alternate functions configuration function + * @brief GPIO Alternate functions configuration function + * +@verbatim + =============================================================================== + ##### GPIO Alternate functions configuration function ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Changes the mapping of the specified pin. + * @param GPIOx: where x can be (A..I) to select the GPIO peripheral for + * STM32F40xx/41xx and STM32F427x/437x devices. + * @param GPIO_PinSource: specifies the pin for the Alternate function. + * This parameter can be GPIO_PinSourcex where x can be (0..15). + * @param GPIO_AFSelection: selects the pin to used as Alternate function. + * This parameter can be one of the following values: + * @arg GPIO_AF_RTC_50Hz: Connect RTC_50Hz pin to AF0 (default after reset) + * @arg GPIO_AF_MCO: Connect MCO pin (MCO1 and MCO2) to AF0 (default after reset) + * @arg GPIO_AF_TAMPER: Connect TAMPER pins (TAMPER_1 and TAMPER_2) to AF0 (default after reset) + * @arg GPIO_AF_SWJ: Connect SWJ pins (SWD and JTAG)to AF0 (default after reset) + * @arg GPIO_AF_TRACE: Connect TRACE pins to AF0 (default after reset) + * @arg GPIO_AF_TIM1: Connect TIM1 pins to AF1 + * @arg GPIO_AF_TIM2: Connect TIM2 pins to AF1 + * @arg GPIO_AF_TIM3: Connect TIM3 pins to AF2 + * @arg GPIO_AF_TIM4: Connect TIM4 pins to AF2 + * @arg GPIO_AF_TIM5: Connect TIM5 pins to AF2 + * @arg GPIO_AF_TIM8: Connect TIM8 pins to AF3 + * @arg GPIO_AF_TIM9: Connect TIM9 pins to AF3 + * @arg GPIO_AF_TIM10: Connect TIM10 pins to AF3 + * @arg GPIO_AF_TIM11: Connect TIM11 pins to AF3 + * @arg GPIO_AF_I2C1: Connect I2C1 pins to AF4 + * @arg GPIO_AF_I2C2: Connect I2C2 pins to AF4 + * @arg GPIO_AF_I2C3: Connect I2C3 pins to AF4 + * @arg GPIO_AF_SPI1: Connect SPI1 pins to AF5 + * @arg GPIO_AF_SPI2: Connect SPI2/I2S2 pins to AF5 + * @arg GPIO_AF_SPI4: Connect SPI4 pins to AF5 + * @arg GPIO_AF_SPI5: Connect SPI5 pins to AF5 + * @arg GPIO_AF_SPI6: Connect SPI6 pins to AF5 + * @arg GPIO_AF_SPI3: Connect SPI3/I2S3 pins to AF6 + * @arg GPIO_AF_I2S3ext: Connect I2S3ext pins to AF7 + * @arg GPIO_AF_USART1: Connect USART1 pins to AF7 + * @arg GPIO_AF_USART2: Connect USART2 pins to AF7 + * @arg GPIO_AF_USART3: Connect USART3 pins to AF7 + * @arg GPIO_AF_UART4: Connect UART4 pins to AF8 + * @arg GPIO_AF_UART5: Connect UART5 pins to AF8 + * @arg GPIO_AF_USART6: Connect USART6 pins to AF8 + * @arg GPIO_AF_UART7: Connect UART7 pins to AF8 + * @arg GPIO_AF_UART8: Connect UART8 pins to AF8 + * @arg GPIO_AF_CAN1: Connect CAN1 pins to AF9 + * @arg GPIO_AF_CAN2: Connect CAN2 pins to AF9 + * @arg GPIO_AF_TIM12: Connect TIM12 pins to AF9 + * @arg GPIO_AF_TIM13: Connect TIM13 pins to AF9 + * @arg GPIO_AF_TIM14: Connect TIM14 pins to AF9 + * @arg GPIO_AF_OTG_FS: Connect OTG_FS pins to AF10 + * @arg GPIO_AF_OTG_HS: Connect OTG_HS pins to AF10 + * @arg GPIO_AF_ETH: Connect ETHERNET pins to AF11 + * @arg GPIO_AF_FSMC: Connect FSMC pins to AF12 + * @arg GPIO_AF_OTG_HS_FS: Connect OTG HS (configured in FS) pins to AF12 + * @arg GPIO_AF_SDIO: Connect SDIO pins to AF12 + * @arg GPIO_AF_DCMI: Connect DCMI pins to AF13 + * @arg GPIO_AF_EVENTOUT: Connect EVENTOUT pins to AF15 + * @retval None + */ +void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF) +{ + uint32_t temp = 0x00; + uint32_t temp_2 = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); + assert_param(IS_GPIO_AF(GPIO_AF)); + + temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ; + GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ; + temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp; + GPIOx->AFR[GPIO_PinSource >> 0x03] = temp_2; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_gpio.h b/stm/lib/stm32f4xx_gpio.h new file mode 100644 index 000000000..0cf96c5b1 --- /dev/null +++ b/stm/lib/stm32f4xx_gpio.h @@ -0,0 +1,423 @@ +/** + ****************************************************************************** + * @file stm32f4xx_gpio.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file contains all the functions prototypes for the GPIO firmware + * library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_GPIO_H +#define __STM32F4xx_GPIO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup GPIO + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \ + ((PERIPH) == GPIOB) || \ + ((PERIPH) == GPIOC) || \ + ((PERIPH) == GPIOD) || \ + ((PERIPH) == GPIOE) || \ + ((PERIPH) == GPIOF) || \ + ((PERIPH) == GPIOG) || \ + ((PERIPH) == GPIOH) || \ + ((PERIPH) == GPIOI)) + + +/** + * @brief GPIO Configuration Mode enumeration + */ +typedef enum +{ + GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */ + GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */ + GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */ + GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */ +}GPIOMode_TypeDef; +#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_IN) || ((MODE) == GPIO_Mode_OUT) || \ + ((MODE) == GPIO_Mode_AF)|| ((MODE) == GPIO_Mode_AN)) + +/** + * @brief GPIO Output type enumeration + */ +typedef enum +{ + GPIO_OType_PP = 0x00, + GPIO_OType_OD = 0x01 +}GPIOOType_TypeDef; +#define IS_GPIO_OTYPE(OTYPE) (((OTYPE) == GPIO_OType_PP) || ((OTYPE) == GPIO_OType_OD)) + + +/** + * @brief GPIO Output Maximum frequency enumeration + */ +typedef enum +{ + GPIO_Speed_2MHz = 0x00, /*!< Low speed */ + GPIO_Speed_25MHz = 0x01, /*!< Medium speed */ + GPIO_Speed_50MHz = 0x02, /*!< Fast speed */ + GPIO_Speed_100MHz = 0x03 /*!< High speed on 30 pF (80 MHz Output max speed on 15 pF) */ +}GPIOSpeed_TypeDef; +#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_2MHz) || ((SPEED) == GPIO_Speed_25MHz) || \ + ((SPEED) == GPIO_Speed_50MHz)|| ((SPEED) == GPIO_Speed_100MHz)) + +/** + * @brief GPIO Configuration PullUp PullDown enumeration + */ +typedef enum +{ + GPIO_PuPd_NOPULL = 0x00, + GPIO_PuPd_UP = 0x01, + GPIO_PuPd_DOWN = 0x02 +}GPIOPuPd_TypeDef; +#define IS_GPIO_PUPD(PUPD) (((PUPD) == GPIO_PuPd_NOPULL) || ((PUPD) == GPIO_PuPd_UP) || \ + ((PUPD) == GPIO_PuPd_DOWN)) + +/** + * @brief GPIO Bit SET and Bit RESET enumeration + */ +typedef enum +{ + Bit_RESET = 0, + Bit_SET +}BitAction; +#define IS_GPIO_BIT_ACTION(ACTION) (((ACTION) == Bit_RESET) || ((ACTION) == Bit_SET)) + + +/** + * @brief GPIO Init structure definition + */ +typedef struct +{ + uint32_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins_define */ + + GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIOMode_TypeDef */ + + GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIOSpeed_TypeDef */ + + GPIOOType_TypeDef GPIO_OType; /*!< Specifies the operating output type for the selected pins. + This parameter can be a value of @ref GPIOOType_TypeDef */ + + GPIOPuPd_TypeDef GPIO_PuPd; /*!< Specifies the operating Pull-up/Pull down for the selected pins. + This parameter can be a value of @ref GPIOPuPd_TypeDef */ +}GPIO_InitTypeDef; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup GPIO_Exported_Constants + * @{ + */ + +/** @defgroup GPIO_pins_define + * @{ + */ +#define GPIO_Pin_0 ((uint16_t)0x0001) /* Pin 0 selected */ +#define GPIO_Pin_1 ((uint16_t)0x0002) /* Pin 1 selected */ +#define GPIO_Pin_2 ((uint16_t)0x0004) /* Pin 2 selected */ +#define GPIO_Pin_3 ((uint16_t)0x0008) /* Pin 3 selected */ +#define GPIO_Pin_4 ((uint16_t)0x0010) /* Pin 4 selected */ +#define GPIO_Pin_5 ((uint16_t)0x0020) /* Pin 5 selected */ +#define GPIO_Pin_6 ((uint16_t)0x0040) /* Pin 6 selected */ +#define GPIO_Pin_7 ((uint16_t)0x0080) /* Pin 7 selected */ +#define GPIO_Pin_8 ((uint16_t)0x0100) /* Pin 8 selected */ +#define GPIO_Pin_9 ((uint16_t)0x0200) /* Pin 9 selected */ +#define GPIO_Pin_10 ((uint16_t)0x0400) /* Pin 10 selected */ +#define GPIO_Pin_11 ((uint16_t)0x0800) /* Pin 11 selected */ +#define GPIO_Pin_12 ((uint16_t)0x1000) /* Pin 12 selected */ +#define GPIO_Pin_13 ((uint16_t)0x2000) /* Pin 13 selected */ +#define GPIO_Pin_14 ((uint16_t)0x4000) /* Pin 14 selected */ +#define GPIO_Pin_15 ((uint16_t)0x8000) /* Pin 15 selected */ +#define GPIO_Pin_All ((uint16_t)0xFFFF) /* All pins selected */ + +#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00)) +#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \ + ((PIN) == GPIO_Pin_1) || \ + ((PIN) == GPIO_Pin_2) || \ + ((PIN) == GPIO_Pin_3) || \ + ((PIN) == GPIO_Pin_4) || \ + ((PIN) == GPIO_Pin_5) || \ + ((PIN) == GPIO_Pin_6) || \ + ((PIN) == GPIO_Pin_7) || \ + ((PIN) == GPIO_Pin_8) || \ + ((PIN) == GPIO_Pin_9) || \ + ((PIN) == GPIO_Pin_10) || \ + ((PIN) == GPIO_Pin_11) || \ + ((PIN) == GPIO_Pin_12) || \ + ((PIN) == GPIO_Pin_13) || \ + ((PIN) == GPIO_Pin_14) || \ + ((PIN) == GPIO_Pin_15)) +/** + * @} + */ + + +/** @defgroup GPIO_Pin_sources + * @{ + */ +#define GPIO_PinSource0 ((uint8_t)0x00) +#define GPIO_PinSource1 ((uint8_t)0x01) +#define GPIO_PinSource2 ((uint8_t)0x02) +#define GPIO_PinSource3 ((uint8_t)0x03) +#define GPIO_PinSource4 ((uint8_t)0x04) +#define GPIO_PinSource5 ((uint8_t)0x05) +#define GPIO_PinSource6 ((uint8_t)0x06) +#define GPIO_PinSource7 ((uint8_t)0x07) +#define GPIO_PinSource8 ((uint8_t)0x08) +#define GPIO_PinSource9 ((uint8_t)0x09) +#define GPIO_PinSource10 ((uint8_t)0x0A) +#define GPIO_PinSource11 ((uint8_t)0x0B) +#define GPIO_PinSource12 ((uint8_t)0x0C) +#define GPIO_PinSource13 ((uint8_t)0x0D) +#define GPIO_PinSource14 ((uint8_t)0x0E) +#define GPIO_PinSource15 ((uint8_t)0x0F) + +#define IS_GPIO_PIN_SOURCE(PINSOURCE) (((PINSOURCE) == GPIO_PinSource0) || \ + ((PINSOURCE) == GPIO_PinSource1) || \ + ((PINSOURCE) == GPIO_PinSource2) || \ + ((PINSOURCE) == GPIO_PinSource3) || \ + ((PINSOURCE) == GPIO_PinSource4) || \ + ((PINSOURCE) == GPIO_PinSource5) || \ + ((PINSOURCE) == GPIO_PinSource6) || \ + ((PINSOURCE) == GPIO_PinSource7) || \ + ((PINSOURCE) == GPIO_PinSource8) || \ + ((PINSOURCE) == GPIO_PinSource9) || \ + ((PINSOURCE) == GPIO_PinSource10) || \ + ((PINSOURCE) == GPIO_PinSource11) || \ + ((PINSOURCE) == GPIO_PinSource12) || \ + ((PINSOURCE) == GPIO_PinSource13) || \ + ((PINSOURCE) == GPIO_PinSource14) || \ + ((PINSOURCE) == GPIO_PinSource15)) +/** + * @} + */ + +/** @defgroup GPIO_Alternat_function_selection_define + * @{ + */ +/** + * @brief AF 0 selection + */ +#define GPIO_AF_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF_TAMPER ((uint8_t)0x00) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */ +#define GPIO_AF_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF_TIM9 ((uint8_t)0x03) /* TIM9 Alternate Function mapping */ +#define GPIO_AF_TIM10 ((uint8_t)0x03) /* TIM10 Alternate Function mapping */ +#define GPIO_AF_TIM11 ((uint8_t)0x03) /* TIM11 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF_SPI2 ((uint8_t)0x05) /* SPI2/I2S2 Alternate Function mapping */ +#define GPIO_AF_SPI4 ((uint8_t)0x05) /* SPI4 Alternate Function mapping */ +#define GPIO_AF_SPI5 ((uint8_t)0x05) /* SPI5 Alternate Function mapping */ +#define GPIO_AF_SPI6 ((uint8_t)0x05) /* SPI6 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF_SPI3 ((uint8_t)0x06) /* SPI3/I2S3 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ +#define GPIO_AF_I2S3ext ((uint8_t)0x07) /* I2S3ext Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ +#define GPIO_AF_USART6 ((uint8_t)0x08) /* USART6 Alternate Function mapping */ +#define GPIO_AF_UART7 ((uint8_t)0x08) /* UART7 Alternate Function mapping */ +#define GPIO_AF_UART8 ((uint8_t)0x08) /* UART8 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF_CAN2 ((uint8_t)0x09) /* CAN2 Alternate Function mapping */ +#define GPIO_AF_TIM12 ((uint8_t)0x09) /* TIM12 Alternate Function mapping */ +#define GPIO_AF_TIM13 ((uint8_t)0x09) /* TIM13 Alternate Function mapping */ +#define GPIO_AF_TIM14 ((uint8_t)0x09) /* TIM14 Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF_OTG_FS ((uint8_t)0xA) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF_OTG_HS ((uint8_t)0xA) /* OTG_HS Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF_ETH ((uint8_t)0x0B) /* ETHERNET Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF_FSMC ((uint8_t)0xC) /* FSMC Alternate Function mapping */ + +#define GPIO_AF_OTG_HS_FS ((uint8_t)0xC) /* OTG HS configured in FS, Alternate Function mapping */ +#define GPIO_AF_SDIO ((uint8_t)0xC) /* SDIO Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF_DCMI ((uint8_t)0x0D) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) (((AF) == GPIO_AF_RTC_50Hz) || ((AF) == GPIO_AF_TIM14) || \ + ((AF) == GPIO_AF_MCO) || ((AF) == GPIO_AF_TAMPER) || \ + ((AF) == GPIO_AF_SWJ) || ((AF) == GPIO_AF_TRACE) || \ + ((AF) == GPIO_AF_TIM1) || ((AF) == GPIO_AF_TIM2) || \ + ((AF) == GPIO_AF_TIM3) || ((AF) == GPIO_AF_TIM4) || \ + ((AF) == GPIO_AF_TIM5) || ((AF) == GPIO_AF_TIM8) || \ + ((AF) == GPIO_AF_I2C1) || ((AF) == GPIO_AF_I2C2) || \ + ((AF) == GPIO_AF_I2C3) || ((AF) == GPIO_AF_SPI1) || \ + ((AF) == GPIO_AF_SPI2) || ((AF) == GPIO_AF_TIM13) || \ + ((AF) == GPIO_AF_SPI3) || ((AF) == GPIO_AF_TIM14) || \ + ((AF) == GPIO_AF_USART1) || ((AF) == GPIO_AF_USART2) || \ + ((AF) == GPIO_AF_USART3) || ((AF) == GPIO_AF_UART4) || \ + ((AF) == GPIO_AF_UART5) || ((AF) == GPIO_AF_USART6) || \ + ((AF) == GPIO_AF_CAN1) || ((AF) == GPIO_AF_CAN2) || \ + ((AF) == GPIO_AF_OTG_FS) || ((AF) == GPIO_AF_OTG_HS) || \ + ((AF) == GPIO_AF_ETH) || ((AF) == GPIO_AF_OTG_HS_FS) || \ + ((AF) == GPIO_AF_SDIO) || ((AF) == GPIO_AF_DCMI) || \ + ((AF) == GPIO_AF_EVENTOUT) || ((AF) == GPIO_AF_SPI4) || \ + ((AF) == GPIO_AF_SPI5) || ((AF) == GPIO_AF_SPI6) || \ + ((AF) == GPIO_AF_UART7) || ((AF) == GPIO_AF_UART8) || \ + ((AF) == GPIO_AF_FSMC)) + +/** + * @} + */ + +/** @defgroup GPIO_Legacy + * @{ + */ + +#define GPIO_Mode_AIN GPIO_Mode_AN + +#define GPIO_AF_OTG1_FS GPIO_AF_OTG_FS +#define GPIO_AF_OTG2_HS GPIO_AF_OTG_HS +#define GPIO_AF_OTG2_FS GPIO_AF_OTG_HS_FS + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Function used to set the GPIO configuration to the default reset state ****/ +void GPIO_DeInit(GPIO_TypeDef* GPIOx); + +/* Initialization and Configuration functions *********************************/ +void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); +void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); +void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); + +/* GPIO Read and Write functions **********************************************/ +uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); +uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); +void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); +void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); +void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); + +/* GPIO Alternate functions configuration function ****************************/ +void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF); + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F4xx_GPIO_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_rcc.c b/stm/lib/stm32f4xx_rcc.c new file mode 100644 index 000000000..6e74bc6f0 --- /dev/null +++ b/stm/lib/stm32f4xx_rcc.c @@ -0,0 +1,1873 @@ +/** + ****************************************************************************** + * @file stm32f4xx_rcc.c + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file provides firmware functions to manage the following + * functionalities of the Reset and clock control (RCC) peripheral: + * + Internal/external clocks, PLL, CSS and MCO configuration + * + System, AHB and APB busses clocks configuration + * + Peripheral clocks configuration + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### RCC specific features ##### + =============================================================================== + [..] + After reset the device is running from Internal High Speed oscillator + (HSI 16MHz) with Flash 0 wait state, Flash prefetch buffer, D-Cache + and I-Cache are disabled, and all peripherals are off except internal + SRAM, Flash and JTAG. + (+) There is no prescaler on High speed (AHB) and Low speed (APB) busses; + all peripherals mapped on these busses are running at HSI speed. + (+) The clock for all peripherals is switched off, except the SRAM and FLASH. + (+) All GPIOs are in input floating state, except the JTAG pins which + are assigned to be used for debug purpose. + [..] + Once the device started from reset, the user application has to: + (+) Configure the clock source to be used to drive the System clock + (if the application needs higher frequency/performance) + (+) Configure the System clock frequency and Flash settings + (+) Configure the AHB and APB busses prescalers + (+) Enable the clock for the peripheral(s) to be used + (+) Configure the clock source(s) for peripherals which clocks are not + derived from the System clock (I2S, RTC, ADC, USB OTG FS/SDIO/RNG) + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_conf.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup RCC + * @brief RCC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* ------------ RCC registers bit address in the alias region ----------- */ +#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) +/* --- CR Register ---*/ +/* Alias word address of HSION bit */ +#define CR_OFFSET (RCC_OFFSET + 0x00) +#define HSION_BitNumber 0x00 +#define CR_HSION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BitNumber * 4)) +/* Alias word address of CSSON bit */ +#define CSSON_BitNumber 0x13 +#define CR_CSSON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (CSSON_BitNumber * 4)) +/* Alias word address of PLLON bit */ +#define PLLON_BitNumber 0x18 +#define CR_PLLON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLON_BitNumber * 4)) +/* Alias word address of PLLI2SON bit */ +#define PLLI2SON_BitNumber 0x1A +#define CR_PLLI2SON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLI2SON_BitNumber * 4)) + +/* --- CFGR Register ---*/ +/* Alias word address of I2SSRC bit */ +#define CFGR_OFFSET (RCC_OFFSET + 0x08) +#define I2SSRC_BitNumber 0x17 +#define CFGR_I2SSRC_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (I2SSRC_BitNumber * 4)) + +/* --- BDCR Register ---*/ +/* Alias word address of RTCEN bit */ +#define BDCR_OFFSET (RCC_OFFSET + 0x70) +#define RTCEN_BitNumber 0x0F +#define BDCR_RTCEN_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (RTCEN_BitNumber * 4)) +/* Alias word address of BDRST bit */ +#define BDRST_BitNumber 0x10 +#define BDCR_BDRST_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (BDRST_BitNumber * 4)) + +/* --- CSR Register ---*/ +/* Alias word address of LSION bit */ +#define CSR_OFFSET (RCC_OFFSET + 0x74) +#define LSION_BitNumber 0x00 +#define CSR_LSION_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSION_BitNumber * 4)) + +/* --- DCKCFGR Register ---*/ +/* Alias word address of TIMPRE bit */ +#define DCKCFGR_OFFSET (RCC_OFFSET + 0x8C) +#define TIMPRE_BitNumber 0x18 +#define DCKCFGR_TIMPRE_BB (PERIPH_BB_BASE + (DCKCFGR_OFFSET * 32) + (TIMPRE_BitNumber * 4)) +/* ---------------------- RCC registers bit mask ------------------------ */ +/* CFGR register bit mask */ +#define CFGR_MCO2_RESET_MASK ((uint32_t)0x07FFFFFF) +#define CFGR_MCO1_RESET_MASK ((uint32_t)0xF89FFFFF) + +/* RCC Flag Mask */ +#define FLAG_MASK ((uint8_t)0x1F) + +/* CR register byte 3 (Bits[23:16]) base address */ +#define CR_BYTE3_ADDRESS ((uint32_t)0x40023802) + +/* CIR register byte 2 (Bits[15:8]) base address */ +#define CIR_BYTE2_ADDRESS ((uint32_t)(RCC_BASE + 0x0C + 0x01)) + +/* CIR register byte 3 (Bits[23:16]) base address */ +#define CIR_BYTE3_ADDRESS ((uint32_t)(RCC_BASE + 0x0C + 0x02)) + +/* BDCR register base address */ +#define BDCR_ADDRESS (PERIPH_BASE + BDCR_OFFSET) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup RCC_Private_Functions + * @{ + */ + +/** @defgroup RCC_Group1 Internal and external clocks, PLL, CSS and MCO configuration functions + * @brief Internal and external clocks, PLL, CSS and MCO configuration functions + * +@verbatim + =================================================================================== + ##### Internal and external clocks, PLL, CSS and MCO configuration functions ##### + =================================================================================== + [..] + This section provide functions allowing to configure the internal/external clocks, + PLLs, CSS and MCO pins. + + (#) HSI (high-speed internal), 16 MHz factory-trimmed RC used directly or through + the PLL as System clock source. + + (#) LSI (low-speed internal), 32 KHz low consumption RC used as IWDG and/or RTC + clock source. + + (#) HSE (high-speed external), 4 to 26 MHz crystal oscillator used directly or + through the PLL as System clock source. Can be used also as RTC clock source. + + (#) LSE (low-speed external), 32 KHz oscillator used as RTC clock source. + + (#) PLL (clocked by HSI or HSE), featuring two different output clocks: + (++) The first output is used to generate the high speed system clock (up to 168 MHz) + (++) The second output is used to generate the clock for the USB OTG FS (48 MHz), + the random analog generator (<=48 MHz) and the SDIO (<= 48 MHz). + + (#) PLLI2S (clocked by HSI or HSE), used to generate an accurate clock to achieve + high-quality audio performance on the I2S interface. + + (#) CSS (Clock security system), once enable and if a HSE clock failure occurs + (HSE used directly or through PLL as System clock source), the System clock + is automatically switched to HSI and an interrupt is generated if enabled. + The interrupt is linked to the Cortex-M4 NMI (Non-Maskable Interrupt) + exception vector. + + (#) MCO1 (microcontroller clock output), used to output HSI, LSE, HSE or PLL + clock (through a configurable prescaler) on PA8 pin. + + (#) MCO2 (microcontroller clock output), used to output HSE, PLL, SYSCLK or PLLI2S + clock (through a configurable prescaler) on PC9 pin. + @endverbatim + * @{ + */ + +/** + * @brief Resets the RCC clock configuration to the default reset state. + * @note The default reset state of the clock configuration is given below: + * - HSI ON and used as system clock source + * - HSE, PLL and PLLI2S OFF + * - AHB, APB1 and APB2 prescaler set to 1. + * - CSS, MCO1 and MCO2 OFF + * - All interrupts disabled + * @note This function doesn't modify the configuration of the + * - Peripheral clocks + * - LSI, LSE and RTC clocks + * @param None + * @retval None + */ +void RCC_DeInit(void) +{ + /* Set HSION bit */ + RCC->CR |= (uint32_t)0x00000001; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000; + + /* Reset HSEON, CSSON, PLLON and PLLI2S bits */ + RCC->CR &= (uint32_t)0xFAF6FFFF; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x24003010; + + /* Reset PLLI2SCFGR register */ + RCC->PLLI2SCFGR = 0x20003000; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Disable all interrupts */ + RCC->CIR = 0x00000000; + +#ifdef STM32F427X + /* Disable Timers clock prescalers selection */ + RCC->DCKCFGR = 0x00000000; +#endif /* STM32F427X */ + +} + +/** + * @brief Configures the External High Speed oscillator (HSE). + * @note After enabling the HSE (RCC_HSE_ON or RCC_HSE_Bypass), the application + * software should wait on HSERDY flag to be set indicating that HSE clock + * is stable and can be used to clock the PLL and/or system clock. + * @note HSE state can not be changed if it is used directly or through the + * PLL as system clock. In this case, you have to select another source + * of the system clock then change the HSE state (ex. disable it). + * @note The HSE is stopped by hardware when entering STOP and STANDBY modes. + * @note This function reset the CSSON bit, so if the Clock security system(CSS) + * was previously enabled you have to enable it again after calling this + * function. + * @param RCC_HSE: specifies the new state of the HSE. + * This parameter can be one of the following values: + * @arg RCC_HSE_OFF: turn OFF the HSE oscillator, HSERDY flag goes low after + * 6 HSE oscillator clock cycles. + * @arg RCC_HSE_ON: turn ON the HSE oscillator + * @arg RCC_HSE_Bypass: HSE oscillator bypassed with external clock + * @retval None + */ +void RCC_HSEConfig(uint8_t RCC_HSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_HSE)); + + /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/ + *(__IO uint8_t *) CR_BYTE3_ADDRESS = RCC_HSE_OFF; + + /* Set the new HSE configuration -------------------------------------------*/ + *(__IO uint8_t *) CR_BYTE3_ADDRESS = RCC_HSE; +} + +/** + * @brief Waits for HSE start-up. + * @note This functions waits on HSERDY flag to be set and return SUCCESS if + * this flag is set, otherwise returns ERROR if the timeout is reached + * and this flag is not set. The timeout value is defined by the constant + * HSE_STARTUP_TIMEOUT in stm32f4xx.h file. You can tailor it depending + * on the HSE crystal used in your application. + * @param None + * @retval An ErrorStatus enumeration value: + * - SUCCESS: HSE oscillator is stable and ready to use + * - ERROR: HSE oscillator not yet ready + */ +ErrorStatus RCC_WaitForHSEStartUp(void) +{ + __IO uint32_t startupcounter = 0; + ErrorStatus status = ERROR; + FlagStatus hsestatus = RESET; + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + hsestatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY); + startupcounter++; + } while((startupcounter != HSE_STARTUP_TIMEOUT) && (hsestatus == RESET)); + + if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + return (status); +} + +/** + * @brief Adjusts the Internal High Speed oscillator (HSI) calibration value. + * @note The calibration is used to compensate for the variations in voltage + * and temperature that influence the frequency of the internal HSI RC. + * @param HSICalibrationValue: specifies the calibration trimming value. + * This parameter must be a number between 0 and 0x1F. + * @retval None + */ +void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue) +{ + uint32_t tmpreg = 0; + /* Check the parameters */ + assert_param(IS_RCC_CALIBRATION_VALUE(HSICalibrationValue)); + + tmpreg = RCC->CR; + + /* Clear HSITRIM[4:0] bits */ + tmpreg &= ~RCC_CR_HSITRIM; + + /* Set the HSITRIM[4:0] bits according to HSICalibrationValue value */ + tmpreg |= (uint32_t)HSICalibrationValue << 3; + + /* Store the new value */ + RCC->CR = tmpreg; +} + +/** + * @brief Enables or disables the Internal High Speed oscillator (HSI). + * @note The HSI is stopped by hardware when entering STOP and STANDBY modes. + * It is used (enabled by hardware) as system clock source after startup + * from Reset, wakeup from STOP and STANDBY mode, or in case of failure + * of the HSE used directly or indirectly as system clock (if the Clock + * Security System CSS is enabled). + * @note HSI can not be stopped if it is used as system clock source. In this case, + * you have to select another source of the system clock then stop the HSI. + * @note After enabling the HSI, the application software should wait on HSIRDY + * flag to be set indicating that HSI clock is stable and can be used as + * system clock source. + * @param NewState: new state of the HSI. + * This parameter can be: ENABLE or DISABLE. + * @note When the HSI is stopped, HSIRDY flag goes low after 6 HSI oscillator + * clock cycles. + * @retval None + */ +void RCC_HSICmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CR_HSION_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the External Low Speed oscillator (LSE). + * @note As the LSE is in the Backup domain and write access is denied to + * this domain after reset, you have to enable write access using + * PWR_BackupAccessCmd(ENABLE) function before to configure the LSE + * (to be done once after reset). + * @note After enabling the LSE (RCC_LSE_ON or RCC_LSE_Bypass), the application + * software should wait on LSERDY flag to be set indicating that LSE clock + * is stable and can be used to clock the RTC. + * @param RCC_LSE: specifies the new state of the LSE. + * This parameter can be one of the following values: + * @arg RCC_LSE_OFF: turn OFF the LSE oscillator, LSERDY flag goes low after + * 6 LSE oscillator clock cycles. + * @arg RCC_LSE_ON: turn ON the LSE oscillator + * @arg RCC_LSE_Bypass: LSE oscillator bypassed with external clock + * @retval None + */ +void RCC_LSEConfig(uint8_t RCC_LSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_LSE)); + + /* Reset LSEON and LSEBYP bits before configuring the LSE ------------------*/ + /* Reset LSEON bit */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_OFF; + + /* Reset LSEBYP bit */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_OFF; + + /* Configure LSE (RCC_LSE_OFF is already covered by the code section above) */ + switch (RCC_LSE) + { + case RCC_LSE_ON: + /* Set LSEON bit */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_ON; + break; + case RCC_LSE_Bypass: + /* Set LSEBYP and LSEON bits */ + *(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_Bypass | RCC_LSE_ON; + break; + default: + break; + } +} + +/** + * @brief Enables or disables the Internal Low Speed oscillator (LSI). + * @note After enabling the LSI, the application software should wait on + * LSIRDY flag to be set indicating that LSI clock is stable and can + * be used to clock the IWDG and/or the RTC. + * @note LSI can not be disabled if the IWDG is running. + * @param NewState: new state of the LSI. + * This parameter can be: ENABLE or DISABLE. + * @note When the LSI is stopped, LSIRDY flag goes low after 6 LSI oscillator + * clock cycles. + * @retval None + */ +void RCC_LSICmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CSR_LSION_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the main PLL clock source, multiplication and division factors. + * @note This function must be used only when the main PLL is disabled. + * + * @param RCC_PLLSource: specifies the PLL entry clock source. + * This parameter can be one of the following values: + * @arg RCC_PLLSource_HSI: HSI oscillator clock selected as PLL clock entry + * @arg RCC_PLLSource_HSE: HSE oscillator clock selected as PLL clock entry + * @note This clock source (RCC_PLLSource) is common for the main PLL and PLLI2S. + * + * @param PLLM: specifies the division factor for PLL VCO input clock + * This parameter must be a number between 0 and 63. + * @note You have to set the PLLM parameter correctly to ensure that the VCO input + * frequency ranges from 1 to 2 MHz. It is recommended to select a frequency + * of 2 MHz to limit PLL jitter. + * + * @param PLLN: specifies the multiplication factor for PLL VCO output clock + * This parameter must be a number between 192 and 432. + * @note You have to set the PLLN parameter correctly to ensure that the VCO + * output frequency is between 192 and 432 MHz. + * + * @param PLLP: specifies the division factor for main system clock (SYSCLK) + * This parameter must be a number in the range {2, 4, 6, or 8}. + * @note You have to set the PLLP parameter correctly to not exceed 168 MHz on + * the System clock frequency. + * + * @param PLLQ: specifies the division factor for OTG FS, SDIO and RNG clocks + * This parameter must be a number between 4 and 15. + * @note If the USB OTG FS is used in your application, you have to set the + * PLLQ parameter correctly to have 48 MHz clock for the USB. However, + * the SDIO and RNG need a frequency lower than or equal to 48 MHz to work + * correctly. + * + * @retval None + */ +void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ) +{ + /* Check the parameters */ + assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource)); + assert_param(IS_RCC_PLLM_VALUE(PLLM)); + assert_param(IS_RCC_PLLN_VALUE(PLLN)); + assert_param(IS_RCC_PLLP_VALUE(PLLP)); + assert_param(IS_RCC_PLLQ_VALUE(PLLQ)); + + RCC->PLLCFGR = PLLM | (PLLN << 6) | (((PLLP >> 1) -1) << 16) | (RCC_PLLSource) | + (PLLQ << 24); +} + +/** + * @brief Enables or disables the main PLL. + * @note After enabling the main PLL, the application software should wait on + * PLLRDY flag to be set indicating that PLL clock is stable and can + * be used as system clock source. + * @note The main PLL can not be disabled if it is used as system clock source + * @note The main PLL is disabled by hardware when entering STOP and STANDBY modes. + * @param NewState: new state of the main PLL. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_PLLCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_PLLON_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the PLLI2S clock multiplication and division factors. + * + * @note This function must be used only when the PLLI2S is disabled. + * @note PLLI2S clock source is common with the main PLL (configured in + * RCC_PLLConfig function ) + * + * @param PLLI2SN: specifies the multiplication factor for PLLI2S VCO output clock + * This parameter must be a number between 192 and 432. + * @note You have to set the PLLI2SN parameter correctly to ensure that the VCO + * output frequency is between 192 and 432 MHz. + * + * @param PLLI2SR: specifies the division factor for I2S clock + * This parameter must be a number between 2 and 7. + * @note You have to set the PLLI2SR parameter correctly to not exceed 192 MHz + * on the I2S clock frequency. + * + * @retval None + */ +void RCC_PLLI2SConfig(uint32_t PLLI2SN, uint32_t PLLI2SR) +{ + /* Check the parameters */ + assert_param(IS_RCC_PLLI2SN_VALUE(PLLI2SN)); + assert_param(IS_RCC_PLLI2SR_VALUE(PLLI2SR)); + + RCC->PLLI2SCFGR = (PLLI2SN << 6) | (PLLI2SR << 28); +} + +/** + * @brief Enables or disables the PLLI2S. + * @note The PLLI2S is disabled by hardware when entering STOP and STANDBY modes. + * @param NewState: new state of the PLLI2S. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_PLLI2SCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_PLLI2SON_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the Clock Security System. + * @note If a failure is detected on the HSE oscillator clock, this oscillator + * is automatically disabled and an interrupt is generated to inform the + * software about the failure (Clock Security System Interrupt, CSSI), + * allowing the MCU to perform rescue operations. The CSSI is linked to + * the Cortex-M4 NMI (Non-Maskable Interrupt) exception vector. + * @param NewState: new state of the Clock Security System. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_ClockSecuritySystemCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) CR_CSSON_BB = (uint32_t)NewState; +} + +/** + * @brief Selects the clock source to output on MCO1 pin(PA8). + * @note PA8 should be configured in alternate function mode. + * @param RCC_MCO1Source: specifies the clock source to output. + * This parameter can be one of the following values: + * @arg RCC_MCO1Source_HSI: HSI clock selected as MCO1 source + * @arg RCC_MCO1Source_LSE: LSE clock selected as MCO1 source + * @arg RCC_MCO1Source_HSE: HSE clock selected as MCO1 source + * @arg RCC_MCO1Source_PLLCLK: main PLL clock selected as MCO1 source + * @param RCC_MCO1Div: specifies the MCO1 prescaler. + * This parameter can be one of the following values: + * @arg RCC_MCO1Div_1: no division applied to MCO1 clock + * @arg RCC_MCO1Div_2: division by 2 applied to MCO1 clock + * @arg RCC_MCO1Div_3: division by 3 applied to MCO1 clock + * @arg RCC_MCO1Div_4: division by 4 applied to MCO1 clock + * @arg RCC_MCO1Div_5: division by 5 applied to MCO1 clock + * @retval None + */ +void RCC_MCO1Config(uint32_t RCC_MCO1Source, uint32_t RCC_MCO1Div) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_MCO1SOURCE(RCC_MCO1Source)); + assert_param(IS_RCC_MCO1DIV(RCC_MCO1Div)); + + tmpreg = RCC->CFGR; + + /* Clear MCO1[1:0] and MCO1PRE[2:0] bits */ + tmpreg &= CFGR_MCO1_RESET_MASK; + + /* Select MCO1 clock source and prescaler */ + tmpreg |= RCC_MCO1Source | RCC_MCO1Div; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Selects the clock source to output on MCO2 pin(PC9). + * @note PC9 should be configured in alternate function mode. + * @param RCC_MCO2Source: specifies the clock source to output. + * This parameter can be one of the following values: + * @arg RCC_MCO2Source_SYSCLK: System clock (SYSCLK) selected as MCO2 source + * @arg RCC_MCO2Source_PLLI2SCLK: PLLI2S clock selected as MCO2 source + * @arg RCC_MCO2Source_HSE: HSE clock selected as MCO2 source + * @arg RCC_MCO2Source_PLLCLK: main PLL clock selected as MCO2 source + * @param RCC_MCO2Div: specifies the MCO2 prescaler. + * This parameter can be one of the following values: + * @arg RCC_MCO2Div_1: no division applied to MCO2 clock + * @arg RCC_MCO2Div_2: division by 2 applied to MCO2 clock + * @arg RCC_MCO2Div_3: division by 3 applied to MCO2 clock + * @arg RCC_MCO2Div_4: division by 4 applied to MCO2 clock + * @arg RCC_MCO2Div_5: division by 5 applied to MCO2 clock + * @retval None + */ +void RCC_MCO2Config(uint32_t RCC_MCO2Source, uint32_t RCC_MCO2Div) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_MCO2SOURCE(RCC_MCO2Source)); + assert_param(IS_RCC_MCO2DIV(RCC_MCO2Div)); + + tmpreg = RCC->CFGR; + + /* Clear MCO2 and MCO2PRE[2:0] bits */ + tmpreg &= CFGR_MCO2_RESET_MASK; + + /* Select MCO2 clock source and prescaler */ + tmpreg |= RCC_MCO2Source | RCC_MCO2Div; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @} + */ + +/** @defgroup RCC_Group2 System AHB and APB busses clocks configuration functions + * @brief System, AHB and APB busses clocks configuration functions + * +@verbatim + =============================================================================== + ##### System, AHB and APB busses clocks configuration functions ##### + =============================================================================== + [..] + This section provide functions allowing to configure the System, AHB, APB1 and + APB2 busses clocks. + + (#) Several clock sources can be used to drive the System clock (SYSCLK): HSI, + HSE and PLL. + The AHB clock (HCLK) is derived from System clock through configurable + prescaler and used to clock the CPU, memory and peripherals mapped + on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived + from AHB clock through configurable prescalers and used to clock + the peripherals mapped on these busses. You can use + "RCC_GetClocksFreq()" function to retrieve the frequencies of these clocks. + + -@- All the peripheral clocks are derived from the System clock (SYSCLK) except: + (+@) I2S: the I2S clock can be derived either from a specific PLL (PLLI2S) or + from an external clock mapped on the I2S_CKIN pin. + You have to use RCC_I2SCLKConfig() function to configure this clock. + (+@) RTC: the RTC clock can be derived either from the LSI, LSE or HSE clock + divided by 2 to 31. You have to use RCC_RTCCLKConfig() and RCC_RTCCLKCmd() + functions to configure this clock. + (+@) USB OTG FS, SDIO and RTC: USB OTG FS require a frequency equal to 48 MHz + to work correctly, while the SDIO require a frequency equal or lower than + to 48. This clock is derived of the main PLL through PLLQ divider. + (+@) IWDG clock which is always the LSI clock. + + (#) The maximum frequency of the SYSCLK and HCLK is 168 MHz, PCLK2 84 MHz + and PCLK1 42 MHz. Depending on the device voltage range, the maximum + frequency should be adapted accordingly: + +-------------------------------------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |---------------------------------------------------------------------| + | | voltage range | voltage range | voltage range | voltage range | + | | 2.7 V - 3.6 V | 2.4 V - 2.7 V | 2.1 V - 2.4 V | 1.8 V - 2.1 V | + |---------------|----------------|----------------|-----------------|-----------------| + |0WS(1CPU cycle)|0 < HCLK <= 30 |0 < HCLK <= 24 |0 < HCLK <= 18 |0 < HCLK <= 16 | + |---------------|----------------|----------------|-----------------|-----------------| + |1WS(2CPU cycle)|30 < HCLK <= 60 |24 < HCLK <= 48 |18 < HCLK <= 36 |16 < HCLK <= 32 | + |---------------|----------------|----------------|-----------------|-----------------| + |2WS(3CPU cycle)|60 < HCLK <= 90 |48 < HCLK <= 72 |36 < HCLK <= 54 |32 < HCLK <= 48 | + |---------------|----------------|----------------|-----------------|-----------------| + |3WS(4CPU cycle)|90 < HCLK <= 120|72 < HCLK <= 96 |54 < HCLK <= 72 |48 < HCLK <= 64 | + |---------------|----------------|----------------|-----------------|-----------------| + |4WS(5CPU cycle)|120< HCLK <= 150|96 < HCLK <= 120|72 < HCLK <= 90 |64 < HCLK <= 80 | + |---------------|----------------|----------------|-----------------|-----------------| + |5WS(6CPU cycle)|120< HCLK <= 168|120< HCLK <= 144|90 < HCLK <= 108 |80 < HCLK <= 96 | + |---------------|----------------|----------------|-----------------|-----------------| + |6WS(7CPU cycle)| NA |144< HCLK <= 168|108 < HCLK <= 120|96 < HCLK <= 112 | + |---------------|----------------|----------------|-----------------|-----------------| + |7WS(8CPU cycle)| NA | NA |120 < HCLK <= 138|112 < HCLK <= 120| + +-------------------------------------------------------------------------------------+ + -@- When VOS bits (in PWR_CR register) is reset to 0 , the maximum value of HCLK is 144 MHz. + You can use PWR_MainRegulatorModeConfig() function to set or reset this bit. + +@endverbatim + * @{ + */ + +/** + * @brief Configures the system clock (SYSCLK). + * @note The HSI is used (enabled by hardware) as system clock source after + * startup from Reset, wake-up from STOP and STANDBY mode, or in case + * of failure of the HSE used directly or indirectly as system clock + * (if the Clock Security System CSS is enabled). + * @note A switch from one clock source to another occurs only if the target + * clock source is ready (clock stable after startup delay or PLL locked). + * If a clock source which is not yet ready is selected, the switch will + * occur when the clock source will be ready. + * You can use RCC_GetSYSCLKSource() function to know which clock is + * currently used as system clock source. + * @param RCC_SYSCLKSource: specifies the clock source used as system clock. + * This parameter can be one of the following values: + * @arg RCC_SYSCLKSource_HSI: HSI selected as system clock source + * @arg RCC_SYSCLKSource_HSE: HSE selected as system clock source + * @arg RCC_SYSCLKSource_PLLCLK: PLL selected as system clock source + * @retval None + */ +void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource)); + + tmpreg = RCC->CFGR; + + /* Clear SW[1:0] bits */ + tmpreg &= ~RCC_CFGR_SW; + + /* Set SW[1:0] bits according to RCC_SYSCLKSource value */ + tmpreg |= RCC_SYSCLKSource; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Returns the clock source used as system clock. + * @param None + * @retval The clock source used as system clock. The returned value can be one + * of the following: + * - 0x00: HSI used as system clock + * - 0x04: HSE used as system clock + * - 0x08: PLL used as system clock + */ +uint8_t RCC_GetSYSCLKSource(void) +{ + return ((uint8_t)(RCC->CFGR & RCC_CFGR_SWS)); +} + +/** + * @brief Configures the AHB clock (HCLK). + * @note Depending on the device voltage range, the software has to set correctly + * these bits to ensure that HCLK not exceed the maximum allowed frequency + * (for more details refer to section above + * "CPU, AHB and APB busses clocks configuration functions") + * @param RCC_SYSCLK: defines the AHB clock divider. This clock is derived from + * the system clock (SYSCLK). + * This parameter can be one of the following values: + * @arg RCC_SYSCLK_Div1: AHB clock = SYSCLK + * @arg RCC_SYSCLK_Div2: AHB clock = SYSCLK/2 + * @arg RCC_SYSCLK_Div4: AHB clock = SYSCLK/4 + * @arg RCC_SYSCLK_Div8: AHB clock = SYSCLK/8 + * @arg RCC_SYSCLK_Div16: AHB clock = SYSCLK/16 + * @arg RCC_SYSCLK_Div64: AHB clock = SYSCLK/64 + * @arg RCC_SYSCLK_Div128: AHB clock = SYSCLK/128 + * @arg RCC_SYSCLK_Div256: AHB clock = SYSCLK/256 + * @arg RCC_SYSCLK_Div512: AHB clock = SYSCLK/512 + * @retval None + */ +void RCC_HCLKConfig(uint32_t RCC_SYSCLK) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_HCLK(RCC_SYSCLK)); + + tmpreg = RCC->CFGR; + + /* Clear HPRE[3:0] bits */ + tmpreg &= ~RCC_CFGR_HPRE; + + /* Set HPRE[3:0] bits according to RCC_SYSCLK value */ + tmpreg |= RCC_SYSCLK; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + + +/** + * @brief Configures the Low Speed APB clock (PCLK1). + * @param RCC_HCLK: defines the APB1 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_Div1: APB1 clock = HCLK + * @arg RCC_HCLK_Div2: APB1 clock = HCLK/2 + * @arg RCC_HCLK_Div4: APB1 clock = HCLK/4 + * @arg RCC_HCLK_Div8: APB1 clock = HCLK/8 + * @arg RCC_HCLK_Div16: APB1 clock = HCLK/16 + * @retval None + */ +void RCC_PCLK1Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PCLK(RCC_HCLK)); + + tmpreg = RCC->CFGR; + + /* Clear PPRE1[2:0] bits */ + tmpreg &= ~RCC_CFGR_PPRE1; + + /* Set PPRE1[2:0] bits according to RCC_HCLK value */ + tmpreg |= RCC_HCLK; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Configures the High Speed APB clock (PCLK2). + * @param RCC_HCLK: defines the APB2 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_Div1: APB2 clock = HCLK + * @arg RCC_HCLK_Div2: APB2 clock = HCLK/2 + * @arg RCC_HCLK_Div4: APB2 clock = HCLK/4 + * @arg RCC_HCLK_Div8: APB2 clock = HCLK/8 + * @arg RCC_HCLK_Div16: APB2 clock = HCLK/16 + * @retval None + */ +void RCC_PCLK2Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PCLK(RCC_HCLK)); + + tmpreg = RCC->CFGR; + + /* Clear PPRE2[2:0] bits */ + tmpreg &= ~RCC_CFGR_PPRE2; + + /* Set PPRE2[2:0] bits according to RCC_HCLK value */ + tmpreg |= RCC_HCLK << 3; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Returns the frequencies of different on chip clocks; SYSCLK, HCLK, + * PCLK1 and PCLK2. + * + * @note The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*) + * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**) + * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * @note (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * @note (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * @note The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold + * the clocks frequencies. + * + * @note This function can be used by the user application to compute the + * baudrate for the communication peripherals or configure other parameters. + * @note Each time SYSCLK, HCLK, PCLK1 and/or PCLK2 clock changes, this function + * must be called to update the structure's field. Otherwise, any + * configuration based on this function will be incorrect. + * + * @retval None + */ +void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) +{ + uint32_t tmp = 0, presc = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + SYSCLK = PLL_VCO / PLLP + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + RCC_Clocks->SYSCLK_Frequency = pllvco/pllp; + break; + default: + RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; + break; + } + /* Compute HCLK, PCLK1 and PCLK2 clocks frequencies ------------------------*/ + + /* Get HCLK prescaler */ + tmp = RCC->CFGR & RCC_CFGR_HPRE; + tmp = tmp >> 4; + presc = APBAHBPrescTable[tmp]; + /* HCLK clock frequency */ + RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc; + + /* Get PCLK1 prescaler */ + tmp = RCC->CFGR & RCC_CFGR_PPRE1; + tmp = tmp >> 10; + presc = APBAHBPrescTable[tmp]; + /* PCLK1 clock frequency */ + RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc; + + /* Get PCLK2 prescaler */ + tmp = RCC->CFGR & RCC_CFGR_PPRE2; + tmp = tmp >> 13; + presc = APBAHBPrescTable[tmp]; + /* PCLK2 clock frequency */ + RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc; +} + +/** + * @} + */ + +/** @defgroup RCC_Group3 Peripheral clocks configuration functions + * @brief Peripheral clocks configuration functions + * +@verbatim + =============================================================================== + ##### Peripheral clocks configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to configure the Peripheral clocks. + + (#) The RTC clock which is derived from the LSI, LSE or HSE clock divided + by 2 to 31. + + (#) After restart from Reset or wakeup from STANDBY, all peripherals are off + except internal SRAM, Flash and JTAG. Before to start using a peripheral + you have to enable its interface clock. You can do this using + RCC_AHBPeriphClockCmd(), RCC_APB2PeriphClockCmd() and RCC_APB1PeriphClockCmd() functions. + + (#) To reset the peripherals configuration (to the default state after device reset) + you can use RCC_AHBPeriphResetCmd(), RCC_APB2PeriphResetCmd() and + RCC_APB1PeriphResetCmd() functions. + + (#) To further reduce power consumption in SLEEP mode the peripheral clocks + can be disabled prior to executing the WFI or WFE instructions. + You can do this using RCC_AHBPeriphClockLPModeCmd(), + RCC_APB2PeriphClockLPModeCmd() and RCC_APB1PeriphClockLPModeCmd() functions. + +@endverbatim + * @{ + */ + +/** + * @brief Configures the RTC clock (RTCCLK). + * @note As the RTC clock configuration bits are in the Backup domain and write + * access is denied to this domain after reset, you have to enable write + * access using PWR_BackupAccessCmd(ENABLE) function before to configure + * the RTC clock source (to be done once after reset). + * @note Once the RTC clock is configured it can't be changed unless the + * Backup domain is reset using RCC_BackupResetCmd() function, or by + * a Power On Reset (POR). + * + * @param RCC_RTCCLKSource: specifies the RTC clock source. + * This parameter can be one of the following values: + * @arg RCC_RTCCLKSource_LSE: LSE selected as RTC clock + * @arg RCC_RTCCLKSource_LSI: LSI selected as RTC clock + * @arg RCC_RTCCLKSource_HSE_Divx: HSE clock divided by x selected + * as RTC clock, where x:[2,31] + * + * @note If the LSE or LSI is used as RTC clock source, the RTC continues to + * work in STOP and STANDBY modes, and can be used as wakeup source. + * However, when the HSE clock is used as RTC clock source, the RTC + * cannot be used in STOP and STANDBY modes. + * @note The maximum input clock frequency for RTC is 1MHz (when using HSE as + * RTC clock source). + * + * @retval None + */ +void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_RTCCLK_SOURCE(RCC_RTCCLKSource)); + + if ((RCC_RTCCLKSource & 0x00000300) == 0x00000300) + { /* If HSE is selected as RTC clock source, configure HSE division factor for RTC clock */ + tmpreg = RCC->CFGR; + + /* Clear RTCPRE[4:0] bits */ + tmpreg &= ~RCC_CFGR_RTCPRE; + + /* Configure HSE division factor for RTC clock */ + tmpreg |= (RCC_RTCCLKSource & 0xFFFFCFF); + + /* Store the new value */ + RCC->CFGR = tmpreg; + } + + /* Select the RTC clock source */ + RCC->BDCR |= (RCC_RTCCLKSource & 0x00000FFF); +} + +/** + * @brief Enables or disables the RTC clock. + * @note This function must be used only after the RTC clock source was selected + * using the RCC_RTCCLKConfig function. + * @param NewState: new state of the RTC clock. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_RTCCLKCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) BDCR_RTCEN_BB = (uint32_t)NewState; +} + +/** + * @brief Forces or releases the Backup domain reset. + * @note This function resets the RTC peripheral (including the backup registers) + * and the RTC clock source selection in RCC_CSR register. + * @note The BKPSRAM is not affected by this reset. + * @param NewState: new state of the Backup domain reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_BackupResetCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + *(__IO uint32_t *) BDCR_BDRST_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the I2S clock source (I2SCLK). + * @note This function must be called before enabling the I2S APB clock. + * @param RCC_I2SCLKSource: specifies the I2S clock source. + * This parameter can be one of the following values: + * @arg RCC_I2S2CLKSource_PLLI2S: PLLI2S clock used as I2S clock source + * @arg RCC_I2S2CLKSource_Ext: External clock mapped on the I2S_CKIN pin + * used as I2S clock source + * @retval None + */ +void RCC_I2SCLKConfig(uint32_t RCC_I2SCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_I2SCLK_SOURCE(RCC_I2SCLKSource)); + + *(__IO uint32_t *) CFGR_I2SSRC_BB = RCC_I2SCLKSource; +} + +/** + * @brief Configures the Timers clocks prescalers selection. + * + * @note This feature is only available with STM32F427x/437x Devices. + * @param RCC_TIMCLKPrescaler : specifies the Timers clocks prescalers selection + * This parameter can be one of the following values: + * @arg RCC_TIMPrescDesactivated: The Timers kernels clocks prescaler is + * equal to HPRE if PPREx is corresponding to division by 1 or 2, + * else it is equal to [(HPRE * PPREx) / 2] if PPREx is corresponding to + * division by 4 or more. + * + * @arg RCC_TIMPrescActivated: The Timers kernels clocks prescaler is + * equal to HPRE if PPREx is corresponding to division by 1, 2 or 4, + * else it is equal to [(HPRE * PPREx) / 4] if PPREx is corresponding + * to division by 8 or more. + * @retval None + */ +void RCC_TIMCLKPresConfig(uint32_t RCC_TIMCLKPrescaler) +{ + /* Check the parameters */ + assert_param(IS_RCC_TIMCLK_PRESCALER(RCC_TIMCLKPrescaler)); + + *(__IO uint32_t *) DCKCFGR_TIMPRE_BB = RCC_TIMCLKPrescaler; + +} + +/** + * @brief Enables or disables the AHB1 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_AHBPeriph: specifies the AHB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_AHB1Periph_GPIOA: GPIOA clock + * @arg RCC_AHB1Periph_GPIOB: GPIOB clock + * @arg RCC_AHB1Periph_GPIOC: GPIOC clock + * @arg RCC_AHB1Periph_GPIOD: GPIOD clock + * @arg RCC_AHB1Periph_GPIOE: GPIOE clock + * @arg RCC_AHB1Periph_GPIOF: GPIOF clock + * @arg RCC_AHB1Periph_GPIOG: GPIOG clock + * @arg RCC_AHB1Periph_GPIOG: GPIOG clock + * @arg RCC_AHB1Periph_GPIOI: GPIOI clock + * @arg RCC_AHB1Periph_CRC: CRC clock + * @arg RCC_AHB1Periph_BKPSRAM: BKPSRAM interface clock + * @arg RCC_AHB1Periph_CCMDATARAMEN CCM data RAM interface clock + * @arg RCC_AHB1Periph_DMA1: DMA1 clock + * @arg RCC_AHB1Periph_DMA2: DMA2 clock + * @arg RCC_AHB1Periph_ETH_MAC: Ethernet MAC clock + * @arg RCC_AHB1Periph_ETH_MAC_Tx: Ethernet Transmission clock + * @arg RCC_AHB1Periph_ETH_MAC_Rx: Ethernet Reception clock + * @arg RCC_AHB1Periph_ETH_MAC_PTP: Ethernet PTP clock + * @arg RCC_AHB1Periph_OTG_HS: USB OTG HS clock + * @arg RCC_AHB1Periph_OTG_HS_ULPI: USB OTG HS ULPI clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB1_CLOCK_PERIPH(RCC_AHB1Periph)); + + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->AHB1ENR |= RCC_AHB1Periph; + } + else + { + RCC->AHB1ENR &= ~RCC_AHB1Periph; + } +} + +/** + * @brief Enables or disables the AHB2 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_AHBPeriph: specifies the AHB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_AHB2Periph_DCMI: DCMI clock + * @arg RCC_AHB2Periph_CRYP: CRYP clock + * @arg RCC_AHB2Periph_HASH: HASH clock + * @arg RCC_AHB2Periph_RNG: RNG clock + * @arg RCC_AHB2Periph_OTG_FS: USB OTG FS clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB2_PERIPH(RCC_AHB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHB2ENR |= RCC_AHB2Periph; + } + else + { + RCC->AHB2ENR &= ~RCC_AHB2Periph; + } +} + +/** + * @brief Enables or disables the AHB3 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_AHBPeriph: specifies the AHB3 peripheral to gates its clock. + * This parameter must be: RCC_AHB3Periph_FSMC + * + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB3_PERIPH(RCC_AHB3Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHB3ENR |= RCC_AHB3Periph; + } + else + { + RCC->AHB3ENR &= ~RCC_AHB3Periph; + } +} + +/** + * @brief Enables or disables the Low Speed APB (APB1) peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_APB1Periph: specifies the APB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2: TIM2 clock + * @arg RCC_APB1Periph_TIM3: TIM3 clock + * @arg RCC_APB1Periph_TIM4: TIM4 clock + * @arg RCC_APB1Periph_TIM5: TIM5 clock + * @arg RCC_APB1Periph_TIM6: TIM6 clock + * @arg RCC_APB1Periph_TIM7: TIM7 clock + * @arg RCC_APB1Periph_TIM12: TIM12 clock + * @arg RCC_APB1Periph_TIM13: TIM13 clock + * @arg RCC_APB1Periph_TIM14: TIM14 clock + * @arg RCC_APB1Periph_WWDG: WWDG clock + * @arg RCC_APB1Periph_SPI2: SPI2 clock + * @arg RCC_APB1Periph_SPI3: SPI3 clock + * @arg RCC_APB1Periph_USART2: USART2 clock + * @arg RCC_APB1Periph_USART3: USART3 clock + * @arg RCC_APB1Periph_UART4: UART4 clock + * @arg RCC_APB1Periph_UART5: UART5 clock + * @arg RCC_APB1Periph_I2C1: I2C1 clock + * @arg RCC_APB1Periph_I2C2: I2C2 clock + * @arg RCC_APB1Periph_I2C3: I2C3 clock + * @arg RCC_APB1Periph_CAN1: CAN1 clock + * @arg RCC_APB1Periph_CAN2: CAN2 clock + * @arg RCC_APB1Periph_PWR: PWR clock + * @arg RCC_APB1Periph_DAC: DAC clock + * @arg RCC_APB1Periph_UART7: UART7 clock + * @arg RCC_APB1Periph_UART8: UART8 clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB1ENR |= RCC_APB1Periph; + } + else + { + RCC->APB1ENR &= ~RCC_APB1Periph; + } +} + +/** + * @brief Enables or disables the High Speed APB (APB2) peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_TIM1: TIM1 clock + * @arg RCC_APB2Periph_TIM8: TIM8 clock + * @arg RCC_APB2Periph_USART1: USART1 clock + * @arg RCC_APB2Periph_USART6: USART6 clock + * @arg RCC_APB2Periph_ADC1: ADC1 clock + * @arg RCC_APB2Periph_ADC2: ADC2 clock + * @arg RCC_APB2Periph_ADC3: ADC3 clock + * @arg RCC_APB2Periph_SDIO: SDIO clock + * @arg RCC_APB2Periph_SPI1: SPI1 clock + * @arg RCC_APB2Periph_SPI4: SPI4 clock + * @arg RCC_APB2Periph_SYSCFG: SYSCFG clock + * @arg RCC_APB2Periph_TIM9: TIM9 clock + * @arg RCC_APB2Periph_TIM10: TIM10 clock + * @arg RCC_APB2Periph_TIM11: TIM11 clock + * @arg RCC_APB2Periph_SPI5: SPI5 clock + * @arg RCC_APB2Periph_SPI6: SPI6 clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB2ENR |= RCC_APB2Periph; + } + else + { + RCC->APB2ENR &= ~RCC_APB2Periph; + } +} + +/** + * @brief Forces or releases AHB1 peripheral reset. + * @param RCC_AHB1Periph: specifies the AHB1 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_AHB1Periph_GPIOA: GPIOA clock + * @arg RCC_AHB1Periph_GPIOB: GPIOB clock + * @arg RCC_AHB1Periph_GPIOC: GPIOC clock + * @arg RCC_AHB1Periph_GPIOD: GPIOD clock + * @arg RCC_AHB1Periph_GPIOE: GPIOE clock + * @arg RCC_AHB1Periph_GPIOF: GPIOF clock + * @arg RCC_AHB1Periph_GPIOG: GPIOG clock + * @arg RCC_AHB1Periph_GPIOG: GPIOG clock + * @arg RCC_AHB1Periph_GPIOI: GPIOI clock + * @arg RCC_AHB1Periph_CRC: CRC clock + * @arg RCC_AHB1Periph_DMA1: DMA1 clock + * @arg RCC_AHB1Periph_DMA2: DMA2 clock + * @arg RCC_AHB1Periph_ETH_MAC: Ethernet MAC clock + * @arg RCC_AHB1Periph_OTG_HS: USB OTG HS clock + * + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB1_RESET_PERIPH(RCC_AHB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHB1RSTR |= RCC_AHB1Periph; + } + else + { + RCC->AHB1RSTR &= ~RCC_AHB1Periph; + } +} + +/** + * @brief Forces or releases AHB2 peripheral reset. + * @param RCC_AHB2Periph: specifies the AHB2 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_AHB2Periph_DCMI: DCMI clock + * @arg RCC_AHB2Periph_CRYP: CRYP clock + * @arg RCC_AHB2Periph_HASH: HASH clock + * @arg RCC_AHB2Periph_RNG: RNG clock + * @arg RCC_AHB2Periph_OTG_FS: USB OTG FS clock + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB2_PERIPH(RCC_AHB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHB2RSTR |= RCC_AHB2Periph; + } + else + { + RCC->AHB2RSTR &= ~RCC_AHB2Periph; + } +} + +/** + * @brief Forces or releases AHB3 peripheral reset. + * @param RCC_AHB3Periph: specifies the AHB3 peripheral to reset. + * This parameter must be: RCC_AHB3Periph_FSMC + * + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB3_PERIPH(RCC_AHB3Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHB3RSTR |= RCC_AHB3Periph; + } + else + { + RCC->AHB3RSTR &= ~RCC_AHB3Periph; + } +} + +/** + * @brief Forces or releases Low Speed APB (APB1) peripheral reset. + * @param RCC_APB1Periph: specifies the APB1 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2: TIM2 clock + * @arg RCC_APB1Periph_TIM3: TIM3 clock + * @arg RCC_APB1Periph_TIM4: TIM4 clock + * @arg RCC_APB1Periph_TIM5: TIM5 clock + * @arg RCC_APB1Periph_TIM6: TIM6 clock + * @arg RCC_APB1Periph_TIM7: TIM7 clock + * @arg RCC_APB1Periph_TIM12: TIM12 clock + * @arg RCC_APB1Periph_TIM13: TIM13 clock + * @arg RCC_APB1Periph_TIM14: TIM14 clock + * @arg RCC_APB1Periph_WWDG: WWDG clock + * @arg RCC_APB1Periph_SPI2: SPI2 clock + * @arg RCC_APB1Periph_SPI3: SPI3 clock + * @arg RCC_APB1Periph_USART2: USART2 clock + * @arg RCC_APB1Periph_USART3: USART3 clock + * @arg RCC_APB1Periph_UART4: UART4 clock + * @arg RCC_APB1Periph_UART5: UART5 clock + * @arg RCC_APB1Periph_I2C1: I2C1 clock + * @arg RCC_APB1Periph_I2C2: I2C2 clock + * @arg RCC_APB1Periph_I2C3: I2C3 clock + * @arg RCC_APB1Periph_CAN1: CAN1 clock + * @arg RCC_APB1Periph_CAN2: CAN2 clock + * @arg RCC_APB1Periph_PWR: PWR clock + * @arg RCC_APB1Periph_DAC: DAC clock + * @arg RCC_APB1Periph_UART7: UART7 clock + * @arg RCC_APB1Periph_UART8: UART8 clock + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB1RSTR |= RCC_APB1Periph; + } + else + { + RCC->APB1RSTR &= ~RCC_APB1Periph; + } +} + +/** + * @brief Forces or releases High Speed APB (APB2) peripheral reset. + * @param RCC_APB2Periph: specifies the APB2 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_TIM1: TIM1 clock + * @arg RCC_APB2Periph_TIM8: TIM8 clock + * @arg RCC_APB2Periph_USART1: USART1 clock + * @arg RCC_APB2Periph_USART6: USART6 clock + * @arg RCC_APB2Periph_ADC1: ADC1 clock + * @arg RCC_APB2Periph_ADC2: ADC2 clock + * @arg RCC_APB2Periph_ADC3: ADC3 clock + * @arg RCC_APB2Periph_SDIO: SDIO clock + * @arg RCC_APB2Periph_SPI1: SPI1 clock + * @arg RCC_APB2Periph_SPI4: SPI4 clock + * @arg RCC_APB2Periph_SYSCFG: SYSCFG clock + * @arg RCC_APB2Periph_TIM9: TIM9 clock + * @arg RCC_APB2Periph_TIM10: TIM10 clock + * @arg RCC_APB2Periph_TIM11: TIM11 clock + * @arg RCC_APB2Periph_SPI5: SPI5 clock + * @arg RCC_APB2Periph_SPI6: SPI6 clock + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_RESET_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB2RSTR |= RCC_APB2Periph; + } + else + { + RCC->APB2RSTR &= ~RCC_APB2Periph; + } +} + +/** + * @brief Enables or disables the AHB1 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_AHBPeriph: specifies the AHB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_AHB1Periph_GPIOA: GPIOA clock + * @arg RCC_AHB1Periph_GPIOB: GPIOB clock + * @arg RCC_AHB1Periph_GPIOC: GPIOC clock + * @arg RCC_AHB1Periph_GPIOD: GPIOD clock + * @arg RCC_AHB1Periph_GPIOE: GPIOE clock + * @arg RCC_AHB1Periph_GPIOF: GPIOF clock + * @arg RCC_AHB1Periph_GPIOG: GPIOG clock + * @arg RCC_AHB1Periph_GPIOG: GPIOG clock + * @arg RCC_AHB1Periph_GPIOI: GPIOI clock + * @arg RCC_AHB1Periph_CRC: CRC clock + * @arg RCC_AHB1Periph_BKPSRAM: BKPSRAM interface clock + * @arg RCC_AHB1Periph_DMA1: DMA1 clock + * @arg RCC_AHB1Periph_DMA2: DMA2 clock + * @arg RCC_AHB1Periph_ETH_MAC: Ethernet MAC clock + * @arg RCC_AHB1Periph_ETH_MAC_Tx: Ethernet Transmission clock + * @arg RCC_AHB1Periph_ETH_MAC_Rx: Ethernet Reception clock + * @arg RCC_AHB1Periph_ETH_MAC_PTP: Ethernet PTP clock + * @arg RCC_AHB1Periph_OTG_HS: USB OTG HS clock + * @arg RCC_AHB1Periph_OTG_HS_ULPI: USB OTG HS ULPI clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB1PeriphClockLPModeCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB1_LPMODE_PERIPH(RCC_AHB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->AHB1LPENR |= RCC_AHB1Periph; + } + else + { + RCC->AHB1LPENR &= ~RCC_AHB1Periph; + } +} + +/** + * @brief Enables or disables the AHB2 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_AHBPeriph: specifies the AHB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_AHB2Periph_DCMI: DCMI clock + * @arg RCC_AHB2Periph_CRYP: CRYP clock + * @arg RCC_AHB2Periph_HASH: HASH clock + * @arg RCC_AHB2Periph_RNG: RNG clock + * @arg RCC_AHB2Periph_OTG_FS: USB OTG FS clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB2PeriphClockLPModeCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB2_PERIPH(RCC_AHB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->AHB2LPENR |= RCC_AHB2Periph; + } + else + { + RCC->AHB2LPENR &= ~RCC_AHB2Periph; + } +} + +/** + * @brief Enables or disables the AHB3 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_AHBPeriph: specifies the AHB3 peripheral to gates its clock. + * This parameter must be: RCC_AHB3Periph_FSMC + * + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHB3PeriphClockLPModeCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB3_PERIPH(RCC_AHB3Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->AHB3LPENR |= RCC_AHB3Periph; + } + else + { + RCC->AHB3LPENR &= ~RCC_AHB3Periph; + } +} + +/** + * @brief Enables or disables the APB1 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_APB1Periph: specifies the APB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2: TIM2 clock + * @arg RCC_APB1Periph_TIM3: TIM3 clock + * @arg RCC_APB1Periph_TIM4: TIM4 clock + * @arg RCC_APB1Periph_TIM5: TIM5 clock + * @arg RCC_APB1Periph_TIM6: TIM6 clock + * @arg RCC_APB1Periph_TIM7: TIM7 clock + * @arg RCC_APB1Periph_TIM12: TIM12 clock + * @arg RCC_APB1Periph_TIM13: TIM13 clock + * @arg RCC_APB1Periph_TIM14: TIM14 clock + * @arg RCC_APB1Periph_WWDG: WWDG clock + * @arg RCC_APB1Periph_SPI2: SPI2 clock + * @arg RCC_APB1Periph_SPI3: SPI3 clock + * @arg RCC_APB1Periph_USART2: USART2 clock + * @arg RCC_APB1Periph_USART3: USART3 clock + * @arg RCC_APB1Periph_UART4: UART4 clock + * @arg RCC_APB1Periph_UART5: UART5 clock + * @arg RCC_APB1Periph_I2C1: I2C1 clock + * @arg RCC_APB1Periph_I2C2: I2C2 clock + * @arg RCC_APB1Periph_I2C3: I2C3 clock + * @arg RCC_APB1Periph_CAN1: CAN1 clock + * @arg RCC_APB1Periph_CAN2: CAN2 clock + * @arg RCC_APB1Periph_PWR: PWR clock + * @arg RCC_APB1Periph_DAC: DAC clock + * @arg RCC_APB1Periph_UART7: UART7 clock + * @arg RCC_APB1Periph_UART8: UART8 clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphClockLPModeCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB1LPENR |= RCC_APB1Periph; + } + else + { + RCC->APB1LPENR &= ~RCC_APB1Periph; + } +} + +/** + * @brief Enables or disables the APB2 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_TIM1: TIM1 clock + * @arg RCC_APB2Periph_TIM8: TIM8 clock + * @arg RCC_APB2Periph_USART1: USART1 clock + * @arg RCC_APB2Periph_USART6: USART6 clock + * @arg RCC_APB2Periph_ADC1: ADC1 clock + * @arg RCC_APB2Periph_ADC2: ADC2 clock + * @arg RCC_APB2Periph_ADC3: ADC3 clock + * @arg RCC_APB2Periph_SDIO: SDIO clock + * @arg RCC_APB2Periph_SPI1: SPI1 clock + * @arg RCC_APB2Periph_SPI4: SPI4 clock + * @arg RCC_APB2Periph_SYSCFG: SYSCFG clock + * @arg RCC_APB2Periph_TIM9: TIM9 clock + * @arg RCC_APB2Periph_TIM10: TIM10 clock + * @arg RCC_APB2Periph_TIM11: TIM11 clock + * @arg RCC_APB2Periph_SPI5: SPI5 clock + * @arg RCC_APB2Periph_SPI6: SPI6 clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphClockLPModeCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + RCC->APB2LPENR |= RCC_APB2Periph; + } + else + { + RCC->APB2LPENR &= ~RCC_APB2Periph; + } +} + +/** + * @} + */ + +/** @defgroup RCC_Group4 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified RCC interrupts. + * @param RCC_IT: specifies the RCC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: main PLL ready interrupt + * @arg RCC_IT_PLLI2SRDY: PLLI2S ready interrupt + * + * @param NewState: new state of the specified RCC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_IT(RCC_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + if (NewState != DISABLE) + { + /* Perform Byte access to RCC_CIR[14:8] bits to enable the selected interrupts */ + *(__IO uint8_t *) CIR_BYTE2_ADDRESS |= RCC_IT; + } + else + { + /* Perform Byte access to RCC_CIR[14:8] bits to disable the selected interrupts */ + *(__IO uint8_t *) CIR_BYTE2_ADDRESS &= (uint8_t)~RCC_IT; + } +} + +/** + * @brief Checks whether the specified RCC flag is set or not. + * @param RCC_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready + * @arg RCC_FLAG_HSERDY: HSE oscillator clock ready + * @arg RCC_FLAG_PLLRDY: main PLL clock ready + * @arg RCC_FLAG_PLLI2SRDY: PLLI2S clock ready + * @arg RCC_FLAG_LSERDY: LSE oscillator clock ready + * @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready + * @arg RCC_FLAG_BORRST: POR/PDR or BOR reset + * @arg RCC_FLAG_PINRST: Pin reset + * @arg RCC_FLAG_PORRST: POR/PDR reset + * @arg RCC_FLAG_SFTRST: Software reset + * @arg RCC_FLAG_IWDGRST: Independent Watchdog reset + * @arg RCC_FLAG_WWDGRST: Window Watchdog reset + * @arg RCC_FLAG_LPWRRST: Low Power reset + * @retval The new state of RCC_FLAG (SET or RESET). + */ +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG) +{ + uint32_t tmp = 0; + uint32_t statusreg = 0; + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_RCC_FLAG(RCC_FLAG)); + + /* Get the RCC register index */ + tmp = RCC_FLAG >> 5; + if (tmp == 1) /* The flag to check is in CR register */ + { + statusreg = RCC->CR; + } + else if (tmp == 2) /* The flag to check is in BDCR register */ + { + statusreg = RCC->BDCR; + } + else /* The flag to check is in CSR register */ + { + statusreg = RCC->CSR; + } + + /* Get the flag position */ + tmp = RCC_FLAG & FLAG_MASK; + if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the RCC reset flags. + * The reset flags are: RCC_FLAG_PINRST, RCC_FLAG_PORRST, RCC_FLAG_SFTRST, + * RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST, RCC_FLAG_LPWRRST + * @param None + * @retval None + */ +void RCC_ClearFlag(void) +{ + /* Set RMVF bit to clear the reset flags */ + RCC->CSR |= RCC_CSR_RMVF; +} + +/** + * @brief Checks whether the specified RCC interrupt has occurred or not. + * @param RCC_IT: specifies the RCC interrupt source to check. + * This parameter can be one of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: main PLL ready interrupt + * @arg RCC_IT_PLLI2SRDY: PLLI2S ready interrupt + * @arg RCC_IT_CSS: Clock Security System interrupt + * @retval The new state of RCC_IT (SET or RESET). + */ +ITStatus RCC_GetITStatus(uint8_t RCC_IT) +{ + ITStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_RCC_GET_IT(RCC_IT)); + + /* Check the status of the specified RCC interrupt */ + if ((RCC->CIR & RCC_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the RCC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the RCC's interrupt pending bits. + * @param RCC_IT: specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: main PLL ready interrupt + * @arg RCC_IT_PLLI2SRDY: PLLI2S ready interrupt + * @arg RCC_IT_CSS: Clock Security System interrupt + * @retval None + */ +void RCC_ClearITPendingBit(uint8_t RCC_IT) +{ + /* Check the parameters */ + assert_param(IS_RCC_CLEAR_IT(RCC_IT)); + + /* Perform Byte access to RCC_CIR[23:16] bits to clear the selected interrupt + pending bits */ + *(__IO uint8_t *) CIR_BYTE3_ADDRESS = RCC_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm32f4xx_rcc.h b/stm/lib/stm32f4xx_rcc.h new file mode 100644 index 000000000..0cbeab2fc --- /dev/null +++ b/stm/lib/stm32f4xx_rcc.h @@ -0,0 +1,545 @@ +/** + ****************************************************************************** + * @file stm32f4xx_rcc.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file contains all the functions prototypes for the RCC firmware library. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_RCC_H +#define __STM32F4xx_RCC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RCC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +typedef struct +{ + uint32_t SYSCLK_Frequency; /*!< SYSCLK clock frequency expressed in Hz */ + uint32_t HCLK_Frequency; /*!< HCLK clock frequency expressed in Hz */ + uint32_t PCLK1_Frequency; /*!< PCLK1 clock frequency expressed in Hz */ + uint32_t PCLK2_Frequency; /*!< PCLK2 clock frequency expressed in Hz */ +}RCC_ClocksTypeDef; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup RCC_Exported_Constants + * @{ + */ + +/** @defgroup RCC_HSE_configuration + * @{ + */ +#define RCC_HSE_OFF ((uint8_t)0x00) +#define RCC_HSE_ON ((uint8_t)0x01) +#define RCC_HSE_Bypass ((uint8_t)0x05) +#define IS_RCC_HSE(HSE) (((HSE) == RCC_HSE_OFF) || ((HSE) == RCC_HSE_ON) || \ + ((HSE) == RCC_HSE_Bypass)) +/** + * @} + */ + +/** @defgroup RCC_PLL_Clock_Source + * @{ + */ +#define RCC_PLLSource_HSI ((uint32_t)0x00000000) +#define RCC_PLLSource_HSE ((uint32_t)0x00400000) +#define IS_RCC_PLL_SOURCE(SOURCE) (((SOURCE) == RCC_PLLSource_HSI) || \ + ((SOURCE) == RCC_PLLSource_HSE)) +#define IS_RCC_PLLM_VALUE(VALUE) ((VALUE) <= 63) +#define IS_RCC_PLLN_VALUE(VALUE) ((192 <= (VALUE)) && ((VALUE) <= 432)) +#define IS_RCC_PLLP_VALUE(VALUE) (((VALUE) == 2) || ((VALUE) == 4) || ((VALUE) == 6) || ((VALUE) == 8)) +#define IS_RCC_PLLQ_VALUE(VALUE) ((4 <= (VALUE)) && ((VALUE) <= 15)) + +#define IS_RCC_PLLI2SN_VALUE(VALUE) ((192 <= (VALUE)) && ((VALUE) <= 432)) +#define IS_RCC_PLLI2SR_VALUE(VALUE) ((2 <= (VALUE)) && ((VALUE) <= 7)) + +/** + * @} + */ + +/** @defgroup RCC_System_Clock_Source + * @{ + */ +#define RCC_SYSCLKSource_HSI ((uint32_t)0x00000000) +#define RCC_SYSCLKSource_HSE ((uint32_t)0x00000001) +#define RCC_SYSCLKSource_PLLCLK ((uint32_t)0x00000002) +#define IS_RCC_SYSCLK_SOURCE(SOURCE) (((SOURCE) == RCC_SYSCLKSource_HSI) || \ + ((SOURCE) == RCC_SYSCLKSource_HSE) || \ + ((SOURCE) == RCC_SYSCLKSource_PLLCLK)) +/** + * @} + */ + +/** @defgroup RCC_AHB_Clock_Source + * @{ + */ +#define RCC_SYSCLK_Div1 ((uint32_t)0x00000000) +#define RCC_SYSCLK_Div2 ((uint32_t)0x00000080) +#define RCC_SYSCLK_Div4 ((uint32_t)0x00000090) +#define RCC_SYSCLK_Div8 ((uint32_t)0x000000A0) +#define RCC_SYSCLK_Div16 ((uint32_t)0x000000B0) +#define RCC_SYSCLK_Div64 ((uint32_t)0x000000C0) +#define RCC_SYSCLK_Div128 ((uint32_t)0x000000D0) +#define RCC_SYSCLK_Div256 ((uint32_t)0x000000E0) +#define RCC_SYSCLK_Div512 ((uint32_t)0x000000F0) +#define IS_RCC_HCLK(HCLK) (((HCLK) == RCC_SYSCLK_Div1) || ((HCLK) == RCC_SYSCLK_Div2) || \ + ((HCLK) == RCC_SYSCLK_Div4) || ((HCLK) == RCC_SYSCLK_Div8) || \ + ((HCLK) == RCC_SYSCLK_Div16) || ((HCLK) == RCC_SYSCLK_Div64) || \ + ((HCLK) == RCC_SYSCLK_Div128) || ((HCLK) == RCC_SYSCLK_Div256) || \ + ((HCLK) == RCC_SYSCLK_Div512)) +/** + * @} + */ + +/** @defgroup RCC_APB1_APB2_Clock_Source + * @{ + */ +#define RCC_HCLK_Div1 ((uint32_t)0x00000000) +#define RCC_HCLK_Div2 ((uint32_t)0x00001000) +#define RCC_HCLK_Div4 ((uint32_t)0x00001400) +#define RCC_HCLK_Div8 ((uint32_t)0x00001800) +#define RCC_HCLK_Div16 ((uint32_t)0x00001C00) +#define IS_RCC_PCLK(PCLK) (((PCLK) == RCC_HCLK_Div1) || ((PCLK) == RCC_HCLK_Div2) || \ + ((PCLK) == RCC_HCLK_Div4) || ((PCLK) == RCC_HCLK_Div8) || \ + ((PCLK) == RCC_HCLK_Div16)) +/** + * @} + */ + +/** @defgroup RCC_Interrupt_Source + * @{ + */ +#define RCC_IT_LSIRDY ((uint8_t)0x01) +#define RCC_IT_LSERDY ((uint8_t)0x02) +#define RCC_IT_HSIRDY ((uint8_t)0x04) +#define RCC_IT_HSERDY ((uint8_t)0x08) +#define RCC_IT_PLLRDY ((uint8_t)0x10) +#define RCC_IT_PLLI2SRDY ((uint8_t)0x20) +#define RCC_IT_CSS ((uint8_t)0x80) + +#define IS_RCC_IT(IT) ((((IT) & (uint8_t)0xC0) == 0x00) && ((IT) != 0x00)) +#define IS_RCC_GET_IT(IT) (((IT) == RCC_IT_LSIRDY) || ((IT) == RCC_IT_LSERDY) || \ + ((IT) == RCC_IT_HSIRDY) || ((IT) == RCC_IT_HSERDY) || \ + ((IT) == RCC_IT_PLLRDY) || ((IT) == RCC_IT_CSS) || \ + ((IT) == RCC_IT_PLLI2SRDY)) +#define IS_RCC_CLEAR_IT(IT) ((((IT) & (uint8_t)0x40) == 0x00) && ((IT) != 0x00)) + +/** + * @} + */ + +/** @defgroup RCC_LSE_Configuration + * @{ + */ +#define RCC_LSE_OFF ((uint8_t)0x00) +#define RCC_LSE_ON ((uint8_t)0x01) +#define RCC_LSE_Bypass ((uint8_t)0x04) +#define IS_RCC_LSE(LSE) (((LSE) == RCC_LSE_OFF) || ((LSE) == RCC_LSE_ON) || \ + ((LSE) == RCC_LSE_Bypass)) +/** + * @} + */ + +/** @defgroup RCC_RTC_Clock_Source + * @{ + */ +#define RCC_RTCCLKSource_LSE ((uint32_t)0x00000100) +#define RCC_RTCCLKSource_LSI ((uint32_t)0x00000200) +#define RCC_RTCCLKSource_HSE_Div2 ((uint32_t)0x00020300) +#define RCC_RTCCLKSource_HSE_Div3 ((uint32_t)0x00030300) +#define RCC_RTCCLKSource_HSE_Div4 ((uint32_t)0x00040300) +#define RCC_RTCCLKSource_HSE_Div5 ((uint32_t)0x00050300) +#define RCC_RTCCLKSource_HSE_Div6 ((uint32_t)0x00060300) +#define RCC_RTCCLKSource_HSE_Div7 ((uint32_t)0x00070300) +#define RCC_RTCCLKSource_HSE_Div8 ((uint32_t)0x00080300) +#define RCC_RTCCLKSource_HSE_Div9 ((uint32_t)0x00090300) +#define RCC_RTCCLKSource_HSE_Div10 ((uint32_t)0x000A0300) +#define RCC_RTCCLKSource_HSE_Div11 ((uint32_t)0x000B0300) +#define RCC_RTCCLKSource_HSE_Div12 ((uint32_t)0x000C0300) +#define RCC_RTCCLKSource_HSE_Div13 ((uint32_t)0x000D0300) +#define RCC_RTCCLKSource_HSE_Div14 ((uint32_t)0x000E0300) +#define RCC_RTCCLKSource_HSE_Div15 ((uint32_t)0x000F0300) +#define RCC_RTCCLKSource_HSE_Div16 ((uint32_t)0x00100300) +#define RCC_RTCCLKSource_HSE_Div17 ((uint32_t)0x00110300) +#define RCC_RTCCLKSource_HSE_Div18 ((uint32_t)0x00120300) +#define RCC_RTCCLKSource_HSE_Div19 ((uint32_t)0x00130300) +#define RCC_RTCCLKSource_HSE_Div20 ((uint32_t)0x00140300) +#define RCC_RTCCLKSource_HSE_Div21 ((uint32_t)0x00150300) +#define RCC_RTCCLKSource_HSE_Div22 ((uint32_t)0x00160300) +#define RCC_RTCCLKSource_HSE_Div23 ((uint32_t)0x00170300) +#define RCC_RTCCLKSource_HSE_Div24 ((uint32_t)0x00180300) +#define RCC_RTCCLKSource_HSE_Div25 ((uint32_t)0x00190300) +#define RCC_RTCCLKSource_HSE_Div26 ((uint32_t)0x001A0300) +#define RCC_RTCCLKSource_HSE_Div27 ((uint32_t)0x001B0300) +#define RCC_RTCCLKSource_HSE_Div28 ((uint32_t)0x001C0300) +#define RCC_RTCCLKSource_HSE_Div29 ((uint32_t)0x001D0300) +#define RCC_RTCCLKSource_HSE_Div30 ((uint32_t)0x001E0300) +#define RCC_RTCCLKSource_HSE_Div31 ((uint32_t)0x001F0300) +#define IS_RCC_RTCCLK_SOURCE(SOURCE) (((SOURCE) == RCC_RTCCLKSource_LSE) || \ + ((SOURCE) == RCC_RTCCLKSource_LSI) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div2) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div3) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div4) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div5) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div6) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div7) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div8) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div9) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div10) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div11) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div12) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div13) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div14) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div15) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div16) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div17) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div18) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div19) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div20) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div21) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div22) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div23) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div24) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div25) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div26) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div27) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div28) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div29) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div30) || \ + ((SOURCE) == RCC_RTCCLKSource_HSE_Div31)) +/** + * @} + */ + +/** @defgroup RCC_I2S_Clock_Source + * @{ + */ +#define RCC_I2S2CLKSource_PLLI2S ((uint8_t)0x00) +#define RCC_I2S2CLKSource_Ext ((uint8_t)0x01) + +#define IS_RCC_I2SCLK_SOURCE(SOURCE) (((SOURCE) == RCC_I2S2CLKSource_PLLI2S) || ((SOURCE) == RCC_I2S2CLKSource_Ext)) +/** + * @} + */ + +/** @defgroup RCC_TIM_PRescaler_Selection + * @{ + */ +#define RCC_TIMPrescDesactivated ((uint8_t)0x00) +#define RCC_TIMPrescActivated ((uint8_t)0x01) + +#define IS_RCC_TIMCLK_PRESCALER(VALUE) (((VALUE) == RCC_TIMPrescDesactivated) || ((VALUE) == RCC_TIMPrescActivated)) +/** + * @} + */ + +/** @defgroup RCC_AHB1_Peripherals + * @{ + */ +#define RCC_AHB1Periph_GPIOA ((uint32_t)0x00000001) +#define RCC_AHB1Periph_GPIOB ((uint32_t)0x00000002) +#define RCC_AHB1Periph_GPIOC ((uint32_t)0x00000004) +#define RCC_AHB1Periph_GPIOD ((uint32_t)0x00000008) +#define RCC_AHB1Periph_GPIOE ((uint32_t)0x00000010) +#define RCC_AHB1Periph_GPIOF ((uint32_t)0x00000020) +#define RCC_AHB1Periph_GPIOG ((uint32_t)0x00000040) +#define RCC_AHB1Periph_GPIOH ((uint32_t)0x00000080) +#define RCC_AHB1Periph_GPIOI ((uint32_t)0x00000100) +#define RCC_AHB1Periph_CRC ((uint32_t)0x00001000) +#define RCC_AHB1Periph_FLITF ((uint32_t)0x00008000) +#define RCC_AHB1Periph_SRAM1 ((uint32_t)0x00010000) +#define RCC_AHB1Periph_SRAM2 ((uint32_t)0x00020000) +#define RCC_AHB1Periph_BKPSRAM ((uint32_t)0x00040000) +#define RCC_AHB1Periph_SRAM3 ((uint32_t)0x00080000) +#define RCC_AHB1Periph_CCMDATARAMEN ((uint32_t)0x00100000) +#define RCC_AHB1Periph_DMA1 ((uint32_t)0x00200000) +#define RCC_AHB1Periph_DMA2 ((uint32_t)0x00400000) +#define RCC_AHB1Periph_ETH_MAC ((uint32_t)0x02000000) +#define RCC_AHB1Periph_ETH_MAC_Tx ((uint32_t)0x04000000) +#define RCC_AHB1Periph_ETH_MAC_Rx ((uint32_t)0x08000000) +#define RCC_AHB1Periph_ETH_MAC_PTP ((uint32_t)0x10000000) +#define RCC_AHB1Periph_OTG_HS ((uint32_t)0x20000000) +#define RCC_AHB1Periph_OTG_HS_ULPI ((uint32_t)0x40000000) + +#define IS_RCC_AHB1_CLOCK_PERIPH(PERIPH) ((((PERIPH) & 0x818BEE00) == 0x00) && ((PERIPH) != 0x00)) +#define IS_RCC_AHB1_RESET_PERIPH(PERIPH) ((((PERIPH) & 0xDD9FEE00) == 0x00) && ((PERIPH) != 0x00)) +#define IS_RCC_AHB1_LPMODE_PERIPH(PERIPH) ((((PERIPH) & 0x81906E00) == 0x00) && ((PERIPH) != 0x00)) + + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Peripherals + * @{ + */ +#define RCC_AHB2Periph_DCMI ((uint32_t)0x00000001) +#define RCC_AHB2Periph_CRYP ((uint32_t)0x00000010) +#define RCC_AHB2Periph_HASH ((uint32_t)0x00000020) +#define RCC_AHB2Periph_RNG ((uint32_t)0x00000040) +#define RCC_AHB2Periph_OTG_FS ((uint32_t)0x00000080) +#define IS_RCC_AHB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFFFFF0E) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @defgroup RCC_AHB3_Peripherals + * @{ + */ +#define RCC_AHB3Periph_FSMC ((uint32_t)0x00000001) + +#define IS_RCC_AHB3_PERIPH(PERIPH) ((((PERIPH) & 0xFFFFFFFE) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @defgroup RCC_APB1_Peripherals + * @{ + */ +#define RCC_APB1Periph_TIM2 ((uint32_t)0x00000001) +#define RCC_APB1Periph_TIM3 ((uint32_t)0x00000002) +#define RCC_APB1Periph_TIM4 ((uint32_t)0x00000004) +#define RCC_APB1Periph_TIM5 ((uint32_t)0x00000008) +#define RCC_APB1Periph_TIM6 ((uint32_t)0x00000010) +#define RCC_APB1Periph_TIM7 ((uint32_t)0x00000020) +#define RCC_APB1Periph_TIM12 ((uint32_t)0x00000040) +#define RCC_APB1Periph_TIM13 ((uint32_t)0x00000080) +#define RCC_APB1Periph_TIM14 ((uint32_t)0x00000100) +#define RCC_APB1Periph_WWDG ((uint32_t)0x00000800) +#define RCC_APB1Periph_SPI2 ((uint32_t)0x00004000) +#define RCC_APB1Periph_SPI3 ((uint32_t)0x00008000) +#define RCC_APB1Periph_USART2 ((uint32_t)0x00020000) +#define RCC_APB1Periph_USART3 ((uint32_t)0x00040000) +#define RCC_APB1Periph_UART4 ((uint32_t)0x00080000) +#define RCC_APB1Periph_UART5 ((uint32_t)0x00100000) +#define RCC_APB1Periph_I2C1 ((uint32_t)0x00200000) +#define RCC_APB1Periph_I2C2 ((uint32_t)0x00400000) +#define RCC_APB1Periph_I2C3 ((uint32_t)0x00800000) +#define RCC_APB1Periph_CAN1 ((uint32_t)0x02000000) +#define RCC_APB1Periph_CAN2 ((uint32_t)0x04000000) +#define RCC_APB1Periph_PWR ((uint32_t)0x10000000) +#define RCC_APB1Periph_DAC ((uint32_t)0x20000000) +#define RCC_APB1Periph_UART7 ((uint32_t)0x40000000) +#define RCC_APB1Periph_UART8 ((uint32_t)0x80000000) +#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH) & 0x09013600) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @defgroup RCC_APB2_Peripherals + * @{ + */ +#define RCC_APB2Periph_TIM1 ((uint32_t)0x00000001) +#define RCC_APB2Periph_TIM8 ((uint32_t)0x00000002) +#define RCC_APB2Periph_USART1 ((uint32_t)0x00000010) +#define RCC_APB2Periph_USART6 ((uint32_t)0x00000020) +#define RCC_APB2Periph_ADC ((uint32_t)0x00000100) +#define RCC_APB2Periph_ADC1 ((uint32_t)0x00000100) +#define RCC_APB2Periph_ADC2 ((uint32_t)0x00000200) +#define RCC_APB2Periph_ADC3 ((uint32_t)0x00000400) +#define RCC_APB2Periph_SDIO ((uint32_t)0x00000800) +#define RCC_APB2Periph_SPI1 ((uint32_t)0x00001000) +#define RCC_APB2Periph_SPI4 ((uint32_t)0x00002000) +#define RCC_APB2Periph_SYSCFG ((uint32_t)0x00004000) +#define RCC_APB2Periph_TIM9 ((uint32_t)0x00010000) +#define RCC_APB2Periph_TIM10 ((uint32_t)0x00020000) +#define RCC_APB2Periph_TIM11 ((uint32_t)0x00040000) +#define RCC_APB2Periph_SPI5 ((uint32_t)0x00100000) +#define RCC_APB2Periph_SPI6 ((uint32_t)0x00200000) + +#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC880CC) == 0x00) && ((PERIPH) != 0x00)) +#define IS_RCC_APB2_RESET_PERIPH(PERIPH) ((((PERIPH) & 0xFFC886CC) == 0x00) && ((PERIPH) != 0x00)) + + +/** + * @} + */ + +/** @defgroup RCC_MCO1_Clock_Source_Prescaler + * @{ + */ +#define RCC_MCO1Source_HSI ((uint32_t)0x00000000) +#define RCC_MCO1Source_LSE ((uint32_t)0x00200000) +#define RCC_MCO1Source_HSE ((uint32_t)0x00400000) +#define RCC_MCO1Source_PLLCLK ((uint32_t)0x00600000) +#define RCC_MCO1Div_1 ((uint32_t)0x00000000) +#define RCC_MCO1Div_2 ((uint32_t)0x04000000) +#define RCC_MCO1Div_3 ((uint32_t)0x05000000) +#define RCC_MCO1Div_4 ((uint32_t)0x06000000) +#define RCC_MCO1Div_5 ((uint32_t)0x07000000) +#define IS_RCC_MCO1SOURCE(SOURCE) (((SOURCE) == RCC_MCO1Source_HSI) || ((SOURCE) == RCC_MCO1Source_LSE) || \ + ((SOURCE) == RCC_MCO1Source_HSE) || ((SOURCE) == RCC_MCO1Source_PLLCLK)) + +#define IS_RCC_MCO1DIV(DIV) (((DIV) == RCC_MCO1Div_1) || ((DIV) == RCC_MCO1Div_2) || \ + ((DIV) == RCC_MCO1Div_3) || ((DIV) == RCC_MCO1Div_4) || \ + ((DIV) == RCC_MCO1Div_5)) +/** + * @} + */ + +/** @defgroup RCC_MCO2_Clock_Source_Prescaler + * @{ + */ +#define RCC_MCO2Source_SYSCLK ((uint32_t)0x00000000) +#define RCC_MCO2Source_PLLI2SCLK ((uint32_t)0x40000000) +#define RCC_MCO2Source_HSE ((uint32_t)0x80000000) +#define RCC_MCO2Source_PLLCLK ((uint32_t)0xC0000000) +#define RCC_MCO2Div_1 ((uint32_t)0x00000000) +#define RCC_MCO2Div_2 ((uint32_t)0x20000000) +#define RCC_MCO2Div_3 ((uint32_t)0x28000000) +#define RCC_MCO2Div_4 ((uint32_t)0x30000000) +#define RCC_MCO2Div_5 ((uint32_t)0x38000000) +#define IS_RCC_MCO2SOURCE(SOURCE) (((SOURCE) == RCC_MCO2Source_SYSCLK) || ((SOURCE) == RCC_MCO2Source_PLLI2SCLK)|| \ + ((SOURCE) == RCC_MCO2Source_HSE) || ((SOURCE) == RCC_MCO2Source_PLLCLK)) + +#define IS_RCC_MCO2DIV(DIV) (((DIV) == RCC_MCO2Div_1) || ((DIV) == RCC_MCO2Div_2) || \ + ((DIV) == RCC_MCO2Div_3) || ((DIV) == RCC_MCO2Div_4) || \ + ((DIV) == RCC_MCO2Div_5)) +/** + * @} + */ + +/** @defgroup RCC_Flag + * @{ + */ +#define RCC_FLAG_HSIRDY ((uint8_t)0x21) +#define RCC_FLAG_HSERDY ((uint8_t)0x31) +#define RCC_FLAG_PLLRDY ((uint8_t)0x39) +#define RCC_FLAG_PLLI2SRDY ((uint8_t)0x3B) +#define RCC_FLAG_LSERDY ((uint8_t)0x41) +#define RCC_FLAG_LSIRDY ((uint8_t)0x61) +#define RCC_FLAG_BORRST ((uint8_t)0x79) +#define RCC_FLAG_PINRST ((uint8_t)0x7A) +#define RCC_FLAG_PORRST ((uint8_t)0x7B) +#define RCC_FLAG_SFTRST ((uint8_t)0x7C) +#define RCC_FLAG_IWDGRST ((uint8_t)0x7D) +#define RCC_FLAG_WWDGRST ((uint8_t)0x7E) +#define RCC_FLAG_LPWRRST ((uint8_t)0x7F) + +#define IS_RCC_FLAG(FLAG) (((FLAG) == RCC_FLAG_HSIRDY) || ((FLAG) == RCC_FLAG_HSERDY) || \ + ((FLAG) == RCC_FLAG_PLLRDY) || ((FLAG) == RCC_FLAG_LSERDY) || \ + ((FLAG) == RCC_FLAG_LSIRDY) || ((FLAG) == RCC_FLAG_BORRST) || \ + ((FLAG) == RCC_FLAG_PINRST) || ((FLAG) == RCC_FLAG_PORRST) || \ + ((FLAG) == RCC_FLAG_SFTRST) || ((FLAG) == RCC_FLAG_IWDGRST)|| \ + ((FLAG) == RCC_FLAG_WWDGRST)|| ((FLAG) == RCC_FLAG_LPWRRST)|| \ + ((FLAG) == RCC_FLAG_PLLI2SRDY)) + +#define IS_RCC_CALIBRATION_VALUE(VALUE) ((VALUE) <= 0x1F) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Function used to set the RCC clock configuration to the default reset state */ +void RCC_DeInit(void); + +/* Internal/external clocks, PLL, CSS and MCO configuration functions *********/ +void RCC_HSEConfig(uint8_t RCC_HSE); +ErrorStatus RCC_WaitForHSEStartUp(void); +void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue); +void RCC_HSICmd(FunctionalState NewState); +void RCC_LSEConfig(uint8_t RCC_LSE); +void RCC_LSICmd(FunctionalState NewState); + +void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ); +void RCC_PLLCmd(FunctionalState NewState); +void RCC_PLLI2SConfig(uint32_t PLLI2SN, uint32_t PLLI2SR); +void RCC_PLLI2SCmd(FunctionalState NewState); +void RCC_ClockSecuritySystemCmd(FunctionalState NewState); +void RCC_MCO1Config(uint32_t RCC_MCO1Source, uint32_t RCC_MCO1Div); +void RCC_MCO2Config(uint32_t RCC_MCO2Source, uint32_t RCC_MCO2Div); + +/* System, AHB and APB busses clocks configuration functions ******************/ +void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource); +uint8_t RCC_GetSYSCLKSource(void); +void RCC_HCLKConfig(uint32_t RCC_SYSCLK); +void RCC_PCLK1Config(uint32_t RCC_HCLK); +void RCC_PCLK2Config(uint32_t RCC_HCLK); +void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks); + +/* Peripheral clocks configuration functions **********************************/ +void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource); +void RCC_RTCCLKCmd(FunctionalState NewState); +void RCC_BackupResetCmd(FunctionalState NewState); +void RCC_I2SCLKConfig(uint32_t RCC_I2SCLKSource); +void RCC_TIMCLKPresConfig(uint32_t RCC_TIMCLKPrescaler); + +void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); +void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState); +void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState); +void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); +void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); + +void RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); +void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState); +void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState); +void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); +void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); + +void RCC_AHB1PeriphClockLPModeCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); +void RCC_AHB2PeriphClockLPModeCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState); +void RCC_AHB3PeriphClockLPModeCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState); +void RCC_APB1PeriphClockLPModeCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); +void RCC_APB2PeriphClockLPModeCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); + +/* Interrupts and flags management functions **********************************/ +void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState); +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG); +void RCC_ClearFlag(void); +ITStatus RCC_GetITStatus(uint8_t RCC_IT); +void RCC_ClearITPendingBit(uint8_t RCC_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_RCC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm_misc.c b/stm/lib/stm_misc.c new file mode 100644 index 000000000..7f12a3724 --- /dev/null +++ b/stm/lib/stm_misc.c @@ -0,0 +1,250 @@ +/** + ****************************************************************************** + * @file misc.c + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file provides all the miscellaneous firmware functions (add-on + * to CMSIS functions). + * + * @verbatim + * + * =================================================================== + * How to configure Interrupts using driver + * =================================================================== + * + * This section provide functions allowing to configure the NVIC interrupts (IRQ). + * The Cortex-M4 exceptions are managed by CMSIS functions. + * + * 1. Configure the NVIC Priority Grouping using NVIC_PriorityGroupConfig() + * function according to the following table. + + * The table below gives the allowed values of the pre-emption priority and subpriority according + * to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function + * ========================================================================================================================== + * NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description + * ========================================================================================================================== + * NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority + * | | | 4 bits for subpriority + * -------------------------------------------------------------------------------------------------------------------------- + * NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority + * | | | 3 bits for subpriority + * -------------------------------------------------------------------------------------------------------------------------- + * NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority + * | | | 2 bits for subpriority + * -------------------------------------------------------------------------------------------------------------------------- + * NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority + * | | | 1 bits for subpriority + * -------------------------------------------------------------------------------------------------------------------------- + * NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority + * | | | 0 bits for subpriority + * ========================================================================================================================== + * + * 2. Enable and Configure the priority of the selected IRQ Channels using NVIC_Init() + * + * @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. + * The pending IRQ priority will be managed only by the subpriority. + * + * @note IRQ priority order (sorted by highest to lowest priority): + * - Lowest pre-emption priority + * - Lowest subpriority + * - Lowest hardware priority (IRQ number) + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_conf.h" +#include "stm_misc.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup MISC + * @brief MISC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup MISC_Private_Functions + * @{ + */ + +/** + * @brief Configures the priority grouping: pre-emption priority and subpriority. + * @param NVIC_PriorityGroup: specifies the priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority + * 4 bits for subpriority + * @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority + * 3 bits for subpriority + * @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority + * 2 bits for subpriority + * @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority + * 1 bits for subpriority + * @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority + * 0 bits for subpriority + * @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. + * The pending IRQ priority will be managed only by the subpriority. + * @retval None + */ +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) +{ + /* Check the parameters */ + assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); + + /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */ + SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; +} + +/** + * @brief Initializes the NVIC peripheral according to the specified + * parameters in the NVIC_InitStruct. + * @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig() + * function should be called before. + * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains + * the configuration information for the specified NVIC peripheral. + * @retval None + */ +void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) +{ + uint8_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); + assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); + assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); + + if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) + { + /* Compute the Corresponding IRQ Priority --------------------------------*/ + tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; + tmppre = (0x4 - tmppriority); + tmpsub = tmpsub >> tmppriority; + + tmppriority = NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; + tmppriority |= (uint8_t)(NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub); + + tmppriority = tmppriority << 0x04; + + NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; + + /* Enable the Selected IRQ Channels --------------------------------------*/ + NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = + (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } + else + { + /* Disable the Selected IRQ Channels -------------------------------------*/ + NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = + (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } +} + +/** + * @brief Sets the vector table location and Offset. + * @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory. + * This parameter can be one of the following values: + * @arg NVIC_VectTab_RAM: Vector Table in internal SRAM. + * @arg NVIC_VectTab_FLASH: Vector Table in internal FLASH. + * @param Offset: Vector Table base offset field. This value must be a multiple of 0x200. + * @retval None + */ +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset) +{ + /* Check the parameters */ + assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); + assert_param(IS_NVIC_OFFSET(Offset)); + + SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); +} + +/** + * @brief Selects the condition for the system to enter low power mode. + * @param LowPowerMode: Specifies the new mode for the system to enter low power mode. + * This parameter can be one of the following values: + * @arg NVIC_LP_SEVONPEND: Low Power SEV on Pend. + * @arg NVIC_LP_SLEEPDEEP: Low Power DEEPSLEEP request. + * @arg NVIC_LP_SLEEPONEXIT: Low Power Sleep on Exit. + * @param NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_NVIC_LP(LowPowerMode)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + SCB->SCR |= LowPowerMode; + } + else + { + SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode); + } +} + +/** + * @brief Configures the SysTick clock source. + * @param SysTick_CLKSource: specifies the SysTick clock source. + * This parameter can be one of the following values: + * @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source. + * @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source. + * @retval None + */ +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) +{ + /* Check the parameters */ + assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); + if (SysTick_CLKSource == SysTick_CLKSource_HCLK) + { + SysTick->CTRL |= SysTick_CLKSource_HCLK; + } + else + { + SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/stm_misc.h b/stm/lib/stm_misc.h new file mode 100644 index 000000000..dec96ec2a --- /dev/null +++ b/stm/lib/stm_misc.h @@ -0,0 +1,178 @@ +/** + ****************************************************************************** + * @file misc.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief This file contains all the functions prototypes for the miscellaneous + * firmware library functions (add-on to CMSIS functions). + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MISC_H +#define __MISC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_StdPeriph_Driver + * @{ + */ + +/** @addtogroup MISC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief NVIC Init Structure definition + */ + +typedef struct +{ + uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. + This parameter can be an enumerator of @ref IRQn_Type + enumeration (For the complete STM32 Devices IRQ Channels + list, please refer to stm32f4xx.h file) */ + + uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel + specified in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table + A lower priority value indicates a higher priority */ + + uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified + in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table + A lower priority value indicates a higher priority */ + + FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel + will be enabled or disabled. + This parameter can be set either to ENABLE or DISABLE */ +} NVIC_InitTypeDef; + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup MISC_Exported_Constants + * @{ + */ + +/** @defgroup MISC_Vector_Table_Base + * @{ + */ + +#define NVIC_VectTab_RAM ((uint32_t)0x20000000) +#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) +#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \ + ((VECTTAB) == NVIC_VectTab_FLASH)) +/** + * @} + */ + +/** @defgroup MISC_System_Low_Power + * @{ + */ + +#define NVIC_LP_SEVONPEND ((uint8_t)0x10) +#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) +#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) +#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \ + ((LP) == NVIC_LP_SLEEPDEEP) || \ + ((LP) == NVIC_LP_SLEEPONEXIT)) +/** + * @} + */ + +/** @defgroup MISC_Preemption_Priority_Group + * @{ + */ + +#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority + 4 bits for subpriority */ +#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority + 3 bits for subpriority */ +#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority + 2 bits for subpriority */ +#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority + 1 bits for subpriority */ +#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority + 0 bits for subpriority */ + +#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \ + ((GROUP) == NVIC_PriorityGroup_1) || \ + ((GROUP) == NVIC_PriorityGroup_2) || \ + ((GROUP) == NVIC_PriorityGroup_3) || \ + ((GROUP) == NVIC_PriorityGroup_4)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) + +/** + * @} + */ + +/** @defgroup MISC_SysTick_clock_source + * @{ + */ + +#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) +#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) +#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ + ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); +void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState); +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); + +#ifdef __cplusplus +} +#endif + +#endif /* __MISC_H */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/system_stm32f4xx.h b/stm/lib/system_stm32f4xx.h new file mode 100644 index 000000000..98da16c1e --- /dev/null +++ b/stm/lib/system_stm32f4xx.h @@ -0,0 +1,105 @@ +/** + ****************************************************************************** + * @file system_stm32f4xx.h + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef __SYSTEM_STM32F4XX_H +#define __SYSTEM_STM32F4XX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32F4xx_System_Includes + * @{ + */ + +/** + * @} + */ + + +/** @addtogroup STM32F4xx_System_Exported_types + * @{ + */ + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_STM32F4XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usb_bsp.c b/stm/lib/usb_bsp.c new file mode 100644 index 000000000..293ee95e2 --- /dev/null +++ b/stm/lib/usb_bsp.c @@ -0,0 +1,183 @@ +/** + ****************************************************************************** + * @file usb_bsp.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file is responsible to offer board support package and is + * configurable by user. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_rcc.h" +#include "stm_misc.h" +#include "usb_bsp.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY +* @{ +*/ + +/** @defgroup USB_BSP +* @brief This file is responsible to offer board support package +* @{ +*/ + +/** @defgroup USB_BSP_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_BSP_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + + + +/** @defgroup USB_BSP_Private_Macros +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_BSP_Private_Variables +* @{ +*/ + +/** +* @} +*/ + +/** @defgroup USBH_BSP_Private_FunctionPrototypes +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USB_BSP_Private_Functions +* @{ +*/ + + +/** +* @brief USB_OTG_BSP_Init +* Initilizes BSP configurations +* @param None +* @retval None +*/ + +void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) { + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + + /* Configure DM DP Pins */ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_OTG1_FS); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_OTG1_FS); + + /* Configure VBUS Pin (or disable VBUS_SENSING_ENABLED) */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE); +} + +/** +* @brief USB_OTG_BSP_EnableInterrupt +* Enabele USB Global interrupt +* @param None +* @retval None +*/ +void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev) { + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); + NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +} + +/** +* @brief USB_OTG_BSP_uDelay +* This function provides delay time in micro sec +* @param usec : Value of delay required in micro sec +* @retval None +*/ +void USB_OTG_BSP_uDelay (const uint32_t usec) +{ + uint32_t count = 0; + const uint32_t utime = (160 * usec / 5); + do + { + if ( ++count > utime ) + { + return ; + } + } + while (1); +} + + +/** +* @brief USB_OTG_BSP_mDelay +* This function provides delay time in milli sec +* @param msec : Value of delay required in milli sec +* @retval None +*/ +void USB_OTG_BSP_mDelay (const uint32_t msec) +{ + USB_OTG_BSP_uDelay(msec * 1000); +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usb_bsp.h b/stm/lib/usb_bsp.h new file mode 100644 index 000000000..29763a906 --- /dev/null +++ b/stm/lib/usb_bsp.h @@ -0,0 +1,103 @@ +/** + ****************************************************************************** + * @file usb_bsp.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Specific api's relative to the used hardware platform + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_BSP__H__ +#define __USB_BSP__H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_core.h" +#include "usb_conf.h" + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_BSP + * @brief This file is the + * @{ + */ + + +/** @defgroup USB_BSP_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_BSP_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_BSP_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_BSP_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_BSP_Exported_FunctionsPrototype + * @{ + */ +void BSP_Init(void); + +void USB_OTG_BSP_Init (USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_BSP_uDelay (const uint32_t usec); +void USB_OTG_BSP_mDelay (const uint32_t msec); +void USB_OTG_BSP_EnableInterrupt (USB_OTG_CORE_HANDLE *pdev); +#ifdef USE_HOST_MODE +void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev,uint8_t state); +#endif +/** + * @} + */ + +#endif //__USB_BSP__H__ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_conf.h b/stm/lib/usb_conf.h new file mode 100644 index 000000000..9fd0d739c --- /dev/null +++ b/stm/lib/usb_conf.h @@ -0,0 +1,293 @@ +/** + ****************************************************************************** + * @file usb_conf.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief General low level driver configuration + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CONF__H__ +#define __USB_CONF__H__ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" +//#include "stm324xg_eval.h" +//#include "stm324xg_eval_lcd.h" +//#include "stm324xg_eval_ioe.h" +//#include "stm324xg_eval_sdio_sd.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_CONF + * @brief USB low level driver configuration file + * @{ + */ + +/** @defgroup USB_CONF_Exported_Defines + * @{ + */ + +/* USB Core and PHY interface configuration. + Tip: To avoid modifying these defines each time you need to change the USB + configuration, you can declare the needed define in your toolchain + compiler preprocessor. + */ +/****************** USB OTG FS PHY CONFIGURATION ******************************* +* The USB OTG FS Core supports one on-chip Full Speed PHY. +* +* The USE_EMBEDDED_PHY symbol is defined in the project compiler preprocessor +* when FS core is used. +*******************************************************************************/ +#ifndef USE_USB_OTG_FS + #define USE_USB_OTG_FS +#endif /* USE_USB_OTG_FS */ + +#ifdef USE_USB_OTG_FS + #define USB_OTG_FS_CORE +#endif + +/****************** USB OTG HS PHY CONFIGURATION ******************************* +* The USB OTG HS Core supports two PHY interfaces: +* (i) An ULPI interface for the external High Speed PHY: the USB HS Core will +* operate in High speed mode +* (ii) An on-chip Full Speed PHY: the USB HS Core will operate in Full speed mode +* +* You can select the PHY to be used using one of these two defines: +* (i) USE_ULPI_PHY: if the USB OTG HS Core is to be used in High speed mode +* (ii) USE_EMBEDDED_PHY: if the USB OTG HS Core is to be used in Full speed mode +* +* Notes: +* - The USE_ULPI_PHY symbol is defined in the project compiler preprocessor as +* default PHY when HS core is used. +* - On STM322xG-EVAL and STM324xG-EVAL boards, only configuration(i) is available. +* Configuration (ii) need a different hardware, for more details refer to your +* STM32 device datasheet. +*******************************************************************************/ +#ifndef USE_USB_OTG_HS + //#define USE_USB_OTG_HS +#endif /* USE_USB_OTG_HS */ + +#ifndef USE_ULPI_PHY + //#define USE_ULPI_PHY +#endif /* USE_ULPI_PHY */ + +#ifndef USE_EMBEDDED_PHY + //#define USE_EMBEDDED_PHY +#endif /* USE_EMBEDDED_PHY */ + +#ifdef USE_USB_OTG_HS + #define USB_OTG_HS_CORE +#endif + +/******************************************************************************* +* FIFO Size Configuration in Device mode +* +* (i) Receive data FIFO size = RAM for setup packets + +* OUT endpoint control information + +* data OUT packets + miscellaneous +* Space = ONE 32-bits words +* --> RAM for setup packets = 10 spaces +* (n is the nbr of CTRL EPs the device core supports) +* --> OUT EP CTRL info = 1 space +* (one space for status information written to the FIFO along with each +* received packet) +* --> data OUT packets = (Largest Packet Size / 4) + 1 spaces +* (MINIMUM to receive packets) +* --> OR data OUT packets = at least 2*(Largest Packet Size / 4) + 1 spaces +* (if high-bandwidth EP is enabled or multiple isochronous EPs) +* --> miscellaneous = 1 space per OUT EP +* (one space for transfer complete status information also pushed to the +* FIFO with each endpoint's last packet) +* +* (ii)MINIMUM RAM space required for each IN EP Tx FIFO = MAX packet size for +* that particular IN EP. More space allocated in the IN EP Tx FIFO results +* in a better performance on the USB and can hide latencies on the AHB. +* +* (iii) TXn min size = 16 words. (n : Transmit FIFO index) +* (iv) When a TxFIFO is not used, the Configuration should be as follows: +* case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) +* --> Txm can use the space allocated for Txn. +* case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) +* --> Txn should be configured with the minimum space of 16 words +* (v) The FIFO is used optimally when used TxFIFOs are allocated in the top +* of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. +* (vi) In HS case 12 FIFO locations should be reserved for internal DMA registers +* so total FIFO size should be 1012 Only instead of 1024 +*******************************************************************************/ + +/****************** USB OTG HS CONFIGURATION **********************************/ +#ifdef USB_OTG_HS_CORE + #define RX_FIFO_HS_SIZE 512 + #define TX0_FIFO_HS_SIZE 128 + #define TX1_FIFO_HS_SIZE 372 + #define TX2_FIFO_HS_SIZE 64 + #define TX3_FIFO_HS_SIZE 0 + #define TX4_FIFO_HS_SIZE 0 + #define TX5_FIFO_HS_SIZE 0 + +// #define USB_OTG_HS_SOF_OUTPUT_ENABLED + + #ifdef USE_ULPI_PHY + #define USB_OTG_ULPI_PHY_ENABLED + #endif + #ifdef USE_EMBEDDED_PHY + #define USB_OTG_EMBEDDED_PHY_ENABLED + /* wakeup is working only when HS core is configured in FS mode */ + #define USB_OTG_HS_LOW_PWR_MGMT_SUPPORT + #endif + /* #define USB_OTG_HS_INTERNAL_DMA_ENABLED */ /* Be aware that enabling DMA mode will result in data being sent only by + multiple of 4 packet sizes. This is due to the fact that USB DMA does + not allow sending data from non word-aligned addresses. + For this specific application, it is advised to not enable this option + unless required. */ + #define USB_OTG_HS_DEDICATED_EP1_ENABLED +#endif + +/****************** USB OTG FS CONFIGURATION **********************************/ +#ifdef USB_OTG_FS_CORE + #define RX_FIFO_FS_SIZE 128 + #define TX0_FIFO_FS_SIZE 32 + #define TX1_FIFO_FS_SIZE 128 + #define TX2_FIFO_FS_SIZE 32 + #define TX3_FIFO_FS_SIZE 0 + +// #define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT +// #define USB_OTG_FS_SOF_OUTPUT_ENABLED +#endif + +/****************** USB OTG MISC CONFIGURATION ********************************/ +#define VBUS_SENSING_ENABLED + +/****************** USB OTG MODE CONFIGURATION ********************************/ +//#define USE_HOST_MODE +#define USE_DEVICE_MODE +//#define USE_OTG_MODE + +#ifndef USB_OTG_FS_CORE + #ifndef USB_OTG_HS_CORE + #error "USB_OTG_HS_CORE or USB_OTG_FS_CORE should be defined" + #endif +#endif + +#ifndef USE_DEVICE_MODE + #ifndef USE_HOST_MODE + #error "USE_DEVICE_MODE or USE_HOST_MODE should be defined" + #endif +#endif + +#ifndef USE_USB_OTG_HS + #ifndef USE_USB_OTG_FS + #error "USE_USB_OTG_HS or USE_USB_OTG_FS should be defined" + #endif +#else //USE_USB_OTG_HS + #ifndef USE_ULPI_PHY + #ifndef USE_EMBEDDED_PHY + #error "USE_ULPI_PHY or USE_EMBEDDED_PHY should be defined" + #endif + #endif +#endif + +/****************** C Compilers dependant keywords ****************************/ +/* In HS mode and when the DMA is used, all variables and data structures dealing + with the DMA during the transaction process should be 4-bytes aligned */ +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined (__GNUC__) /* GNU Compiler */ + #define __ALIGN_END __attribute__ ((aligned (4))) + #define __ALIGN_BEGIN + #else + #define __ALIGN_END + #if defined (__CC_ARM) /* ARM Compiler */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #elif defined (__TASKING__) /* TASKING Compiler */ + #define __ALIGN_BEGIN __align(4) + #endif /* __CC_ARM */ + #endif /* __GNUC__ */ +#else + #define __ALIGN_BEGIN + #define __ALIGN_END +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ + +/* __packed keyword used to decrease the data type alignment to 1-byte */ +#if defined (__CC_ARM) /* ARM Compiler */ + #define __packed __packed +#elif defined (__ICCARM__) /* IAR Compiler */ + #define __packed __packed +#elif defined ( __GNUC__ ) /* GNU Compiler */ + #define __packed __attribute__ ((__packed__)) +#elif defined (__TASKING__) /* TASKING Compiler */ + #define __packed __unaligned +#endif /* __CC_ARM */ + +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +#endif //__USB_CONF__H__ + + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_core.c b/stm/lib/usb_core.c new file mode 100644 index 000000000..e257e73dc --- /dev/null +++ b/stm/lib/usb_core.c @@ -0,0 +1,2162 @@ +/** + ****************************************************************************** + * @file usb_core.c + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief USB-OTG Core Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_core.h" +#include "usb_bsp.h" + + +/** @addtogroup USB_OTG_DRIVER +* @{ +*/ + +/** @defgroup USB_CORE +* @brief This file includes the USB-OTG Core Layer +* @{ +*/ + + +/** @defgroup USB_CORE_Private_Defines +* @{ +*/ + +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USB_CORE_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_FunctionPrototypes +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_Functions +* @{ +*/ + +/** +* @brief USB_OTG_EnableCommonInt +* Initializes the commmon interrupts, used in both device and modes +* @param pdev : Selected device +* @retval None +*/ +static void USB_OTG_EnableCommonInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTMSK_TypeDef int_mask; + + int_mask.d32 = 0; + /* Clear any pending USB_OTG Interrupts */ +#ifndef USE_OTG_MODE + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GOTGINT, 0xFFFFFFFF); +#endif + /* Clear any pending interrupts */ + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTSTS, 0xBFFFFFFF); + /* Enable the interrupts in the INTMSK */ + int_mask.b.wkupintr = 1; + int_mask.b.usbsuspend = 1; + +#ifdef USE_OTG_MODE + int_mask.b.otgintr = 1; + int_mask.b.sessreqintr = 1; + int_mask.b.conidstschng = 1; +#endif + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTMSK, int_mask.d32); +} + +/** +* @brief USB_OTG_CoreReset : Soft reset of the core +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +static USB_OTG_STS USB_OTG_CoreReset(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + __IO USB_OTG_GRSTCTL_TypeDef greset; + uint32_t count = 0; + + greset.d32 = 0; + /* Wait for AHB master IDLE state. */ + do + { + USB_OTG_BSP_uDelay(3); + greset.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + return USB_OTG_OK; + } + } + while (greset.b.ahbidle == 0); + /* Core Soft Reset */ + count = 0; + greset.b.csftrst = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRSTCTL, greset.d32 ); + do + { + greset.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + break; + } + } + while (greset.b.csftrst == 1); + /* Wait for 3 PHY Clocks*/ + USB_OTG_BSP_uDelay(3); + return status; +} + +/** +* @brief USB_OTG_WritePacket : Writes a packet into the Tx FIFO associated +* with the EP +* @param pdev : Selected device +* @param src : source pointer +* @param ch_ep_num : end point number +* @param bytes : No. of bytes +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_WritePacket(USB_OTG_CORE_HANDLE *pdev, + uint8_t *src, + uint8_t ch_ep_num, + uint16_t len) +{ + USB_OTG_STS status = USB_OTG_OK; + if (pdev->cfg.dma_enable == 0) + { + uint32_t count32b= 0 , i= 0; + __IO uint32_t *fifo; + + count32b = (len + 3) / 4; + fifo = pdev->regs.DFIFO[ch_ep_num]; + for (i = 0; i < count32b; i++, src+=4) + { + USB_OTG_WRITE_REG32( fifo, *((__packed uint32_t *)src) ); + } + } + return status; +} + + +/** +* @brief USB_OTG_ReadPacket : Reads a packet from the Rx FIFO +* @param pdev : Selected device +* @param dest : Destination Pointer +* @param bytes : No. of bytes +* @retval None +*/ +void *USB_OTG_ReadPacket(USB_OTG_CORE_HANDLE *pdev, + uint8_t *dest, + uint16_t len) +{ + uint32_t i=0; + uint32_t count32b = (len + 3) / 4; + + __IO uint32_t *fifo = pdev->regs.DFIFO[0]; + + for ( i = 0; i < count32b; i++, dest += 4 ) + { + *(__packed uint32_t *)dest = USB_OTG_READ_REG32(fifo); + + } + return ((void *)dest); +} + +/** +* @brief USB_OTG_SelectCore +* Initialize core registers address. +* @param pdev : Selected device +* @param coreID : USB OTG Core ID +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_SelectCore(USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID) +{ + uint32_t i , baseAddress = 0; + USB_OTG_STS status = USB_OTG_OK; + + pdev->cfg.dma_enable = 0; + + /* at startup the core is in FS mode */ + pdev->cfg.speed = USB_OTG_SPEED_FULL; + pdev->cfg.mps = USB_OTG_FS_MAX_PACKET_SIZE ; + + /* initialize device cfg following its address */ + if (coreID == USB_OTG_FS_CORE_ID) + { + baseAddress = USB_OTG_FS_BASE_ADDR; + pdev->cfg.coreID = USB_OTG_FS_CORE_ID; + pdev->cfg.host_channels = 8 ; + pdev->cfg.dev_endpoints = 4 ; + pdev->cfg.TotalFifoSize = 320; /* in 32-bits */ + pdev->cfg.phy_itface = USB_OTG_EMBEDDED_PHY; + +#ifdef USB_OTG_FS_SOF_OUTPUT_ENABLED + pdev->cfg.Sof_output = 1; +#endif + +#ifdef USB_OTG_FS_LOW_PWR_MGMT_SUPPORT + pdev->cfg.low_power = 1; +#endif + } + else if (coreID == USB_OTG_HS_CORE_ID) + { + baseAddress = USB_OTG_HS_BASE_ADDR; + pdev->cfg.coreID = USB_OTG_HS_CORE_ID; + pdev->cfg.host_channels = 12 ; + pdev->cfg.dev_endpoints = 6 ; + pdev->cfg.TotalFifoSize = 1280;/* in 32-bits */ + +#ifdef USB_OTG_ULPI_PHY_ENABLED + pdev->cfg.phy_itface = USB_OTG_ULPI_PHY; +#else +#ifdef USB_OTG_EMBEDDED_PHY_ENABLED + pdev->cfg.phy_itface = USB_OTG_EMBEDDED_PHY; +#endif +#endif + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + pdev->cfg.dma_enable = 1; +#endif + +#ifdef USB_OTG_HS_SOF_OUTPUT_ENABLED + pdev->cfg.Sof_output = 1; +#endif + +#ifdef USB_OTG_HS_LOW_PWR_MGMT_SUPPORT + pdev->cfg.low_power = 1; +#endif + + } + + pdev->regs.GREGS = (USB_OTG_GREGS *)(baseAddress + \ + USB_OTG_CORE_GLOBAL_REGS_OFFSET); + pdev->regs.DREGS = (USB_OTG_DREGS *) (baseAddress + \ + USB_OTG_DEV_GLOBAL_REG_OFFSET); + + for (i = 0; i < pdev->cfg.dev_endpoints; i++) + { + pdev->regs.INEP_REGS[i] = (USB_OTG_INEPREGS *) \ + (baseAddress + USB_OTG_DEV_IN_EP_REG_OFFSET + \ + (i * USB_OTG_EP_REG_OFFSET)); + pdev->regs.OUTEP_REGS[i] = (USB_OTG_OUTEPREGS *) \ + (baseAddress + USB_OTG_DEV_OUT_EP_REG_OFFSET + \ + (i * USB_OTG_EP_REG_OFFSET)); + } + pdev->regs.HREGS = (USB_OTG_HREGS *)(baseAddress + \ + USB_OTG_HOST_GLOBAL_REG_OFFSET); + pdev->regs.HPRT0 = (uint32_t *)(baseAddress + USB_OTG_HOST_PORT_REGS_OFFSET); + + for (i = 0; i < pdev->cfg.host_channels; i++) + { + pdev->regs.HC_REGS[i] = (USB_OTG_HC_REGS *)(baseAddress + \ + USB_OTG_HOST_CHAN_REGS_OFFSET + \ + (i * USB_OTG_CHAN_REGS_OFFSET)); + } + for (i = 0; i < pdev->cfg.host_channels; i++) + { + pdev->regs.DFIFO[i] = (uint32_t *)(baseAddress + USB_OTG_DATA_FIFO_OFFSET +\ + (i * USB_OTG_DATA_FIFO_SIZE)); + } + pdev->regs.PCGCCTL = (uint32_t *)(baseAddress + USB_OTG_PCGCCTL_OFFSET); + + return status; +} + + +/** +* @brief USB_OTG_CoreInit +* Initializes the USB_OTG controller registers and prepares the core +* device mode or host mode operation. +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_CoreInit(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GUSBCFG_TypeDef usbcfg; + USB_OTG_GCCFG_TypeDef gccfg; + USB_OTG_GAHBCFG_TypeDef ahbcfg; + + usbcfg.d32 = 0; + gccfg.d32 = 0; + ahbcfg.d32 = 0; + + + + if (pdev->cfg.phy_itface == USB_OTG_ULPI_PHY) + { + gccfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GCCFG); + gccfg.b.pwdn = 0; + + if (pdev->cfg.Sof_output) + { + gccfg.b.sofouten = 1; + } + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GCCFG, gccfg.d32); + + /* Init The ULPI Interface */ + usbcfg.d32 = 0; + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + + usbcfg.b.physel = 0; /* HS Interface */ +#ifdef USB_OTG_INTERNAL_VBUS_ENABLED + usbcfg.b.ulpi_ext_vbus_drv = 0; /* Use internal VBUS */ +#else +#ifdef USB_OTG_EXTERNAL_VBUS_ENABLED + usbcfg.b.ulpi_ext_vbus_drv = 1; /* Use external VBUS */ +#endif +#endif + usbcfg.b.term_sel_dl_pulse = 0; /* Data line pulsing using utmi_txvalid */ + + usbcfg.b.ulpi_fsls = 0; + usbcfg.b.ulpi_clk_sus_m = 0; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + + /* Reset after a PHY select */ + USB_OTG_CoreReset(pdev); + + if(pdev->cfg.dma_enable == 1) + { + + ahbcfg.b.hburstlen = 5; /* 64 x 32-bits*/ + ahbcfg.b.dmaenable = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GAHBCFG, ahbcfg.d32); + + } + } + else /* FS interface (embedded Phy) */ + { + + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG);; + usbcfg.b.physel = 1; /* FS Interface */ + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + /* Reset after a PHY select and set Host mode */ + USB_OTG_CoreReset(pdev); + /* Deactivate the power down*/ + gccfg.d32 = 0; + gccfg.b.pwdn = 1; + + gccfg.b.vbussensingA = 1 ; + gccfg.b.vbussensingB = 1 ; +#ifndef VBUS_SENSING_ENABLED + gccfg.b.disablevbussensing = 1; +#endif + + if(pdev->cfg.Sof_output) + { + gccfg.b.sofouten = 1; + } + + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GCCFG, gccfg.d32); + USB_OTG_BSP_mDelay(20); + } + /* case the HS core is working in FS mode */ + if(pdev->cfg.dma_enable == 1) + { + + ahbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GAHBCFG); + ahbcfg.b.hburstlen = 5; /* 64 x 32-bits*/ + ahbcfg.b.dmaenable = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GAHBCFG, ahbcfg.d32); + + } + /* initialize OTG features */ +#ifdef USE_OTG_MODE + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + usbcfg.b.hnpcap = 1; + usbcfg.b.srpcap = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + USB_OTG_EnableCommonInt(pdev); +#endif + return status; +} +/** +* @brief USB_OTG_EnableGlobalInt +* Enables the controller's Global Int in the AHB Config reg +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EnableGlobalInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GAHBCFG_TypeDef ahbcfg; + + ahbcfg.d32 = 0; + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GAHBCFG, 0, ahbcfg.d32); + return status; +} + + +/** +* @brief USB_OTG_DisableGlobalInt +* Enables the controller's Global Int in the AHB Config reg +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_DisableGlobalInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GAHBCFG_TypeDef ahbcfg; + ahbcfg.d32 = 0; + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GAHBCFG, ahbcfg.d32, 0); + return status; +} + + +/** +* @brief USB_OTG_FlushTxFifo : Flush a Tx FIFO +* @param pdev : Selected device +* @param num : FO num +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_FlushTxFifo (USB_OTG_CORE_HANDLE *pdev , uint32_t num ) +{ + USB_OTG_STS status = USB_OTG_OK; + __IO USB_OTG_GRSTCTL_TypeDef greset; + + uint32_t count = 0; + greset.d32 = 0; + greset.b.txfflsh = 1; + greset.b.txfnum = num; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GRSTCTL, greset.d32 ); + do + { + greset.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + break; + } + } + while (greset.b.txfflsh == 1); + /* Wait for 3 PHY Clocks*/ + USB_OTG_BSP_uDelay(3); + return status; +} + + +/** +* @brief USB_OTG_FlushRxFifo : Flush a Rx FIFO +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_FlushRxFifo( USB_OTG_CORE_HANDLE *pdev ) +{ + USB_OTG_STS status = USB_OTG_OK; + __IO USB_OTG_GRSTCTL_TypeDef greset; + uint32_t count = 0; + + greset.d32 = 0; + greset.b.rxfflsh = 1; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GRSTCTL, greset.d32 ); + do + { + greset.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + break; + } + } + while (greset.b.rxfflsh == 1); + /* Wait for 3 PHY Clocks*/ + USB_OTG_BSP_uDelay(3); + return status; +} + + +/** +* @brief USB_OTG_SetCurrentMode : Set ID line +* @param pdev : Selected device +* @param mode : (Host/device) +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_SetCurrentMode(USB_OTG_CORE_HANDLE *pdev , uint8_t mode) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GUSBCFG_TypeDef usbcfg; + + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + + usbcfg.b.force_host = 0; + usbcfg.b.force_dev = 0; + + if ( mode == HOST_MODE) + { + usbcfg.b.force_host = 1; + } + else if ( mode == DEVICE_MODE) + { + usbcfg.b.force_dev = 1; + } + + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + USB_OTG_BSP_mDelay(50); + return status; +} + + +/** +* @brief USB_OTG_GetMode : Get current mode +* @param pdev : Selected device +* @retval current mode +*/ +uint32_t USB_OTG_GetMode(USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTSTS ) & 0x1); +} + + +/** +* @brief USB_OTG_IsDeviceMode : Check if it is device mode +* @param pdev : Selected device +* @retval num_in_ep +*/ +uint8_t USB_OTG_IsDeviceMode(USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_GetMode(pdev) != HOST_MODE); +} + + +/** +* @brief USB_OTG_IsHostMode : Check if it is host mode +* @param pdev : Selected device +* @retval num_in_ep +*/ +uint8_t USB_OTG_IsHostMode(USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_GetMode(pdev) == HOST_MODE); +} + + +/** +* @brief USB_OTG_ReadCoreItr : returns the Core Interrupt register +* @param pdev : Selected device +* @retval Status +*/ +uint32_t USB_OTG_ReadCoreItr(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t v = 0; + v = USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTSTS); + v &= USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTMSK); + return v; +} + + +/** +* @brief USB_OTG_ReadOtgItr : returns the USB_OTG Interrupt register +* @param pdev : Selected device +* @retval Status +*/ +uint32_t USB_OTG_ReadOtgItr (USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_READ_REG32 (&pdev->regs.GREGS->GOTGINT)); +} + +#ifdef USE_HOST_MODE +/** +* @brief USB_OTG_CoreInitHost : Initializes USB_OTG controller for host mode +* @param pdev : Selected device +* @retval status +*/ +USB_OTG_STS USB_OTG_CoreInitHost(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_FSIZ_TypeDef nptxfifosize; + USB_OTG_FSIZ_TypeDef ptxfifosize; + USB_OTG_HCFG_TypeDef hcfg; + +#ifdef USE_OTG_MODE + USB_OTG_OTGCTL_TypeDef gotgctl; +#endif + + uint32_t i = 0; + + nptxfifosize.d32 = 0; + ptxfifosize.d32 = 0; +#ifdef USE_OTG_MODE + gotgctl.d32 = 0; +#endif + hcfg.d32 = 0; + + + /* configure charge pump IO */ + USB_OTG_BSP_ConfigVBUS(pdev); + + /* Restart the Phy Clock */ + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, 0); + + /* Initialize Host Configuration Register */ + if (pdev->cfg.phy_itface == USB_OTG_ULPI_PHY) + { + USB_OTG_InitFSLSPClkSel(pdev , HCFG_30_60_MHZ); + } + else + { + USB_OTG_InitFSLSPClkSel(pdev , HCFG_48_MHZ); + } + USB_OTG_ResetPort(pdev); + + hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); + hcfg.b.fslssupp = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HCFG, hcfg.d32); + + /* Configure data FIFO sizes */ + /* Rx FIFO */ +#ifdef USB_OTG_FS_CORE + if(pdev->cfg.coreID == USB_OTG_FS_CORE_ID) + { + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_FS_SIZE); + nptxfifosize.b.startaddr = RX_FIFO_FS_SIZE; + nptxfifosize.b.depth = TXH_NP_FS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32); + + ptxfifosize.b.startaddr = RX_FIFO_FS_SIZE + TXH_NP_FS_FIFOSIZ; + ptxfifosize.b.depth = TXH_P_FS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->HPTXFSIZ, ptxfifosize.d32); + } +#endif +#ifdef USB_OTG_HS_CORE + if (pdev->cfg.coreID == USB_OTG_HS_CORE_ID) + { + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_HS_SIZE); + nptxfifosize.b.startaddr = RX_FIFO_HS_SIZE; + nptxfifosize.b.depth = TXH_NP_HS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32); + + ptxfifosize.b.startaddr = RX_FIFO_HS_SIZE + TXH_NP_HS_FIFOSIZ; + ptxfifosize.b.depth = TXH_P_HS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->HPTXFSIZ, ptxfifosize.d32); + } +#endif + +#ifdef USE_OTG_MODE + /* Clear Host Set HNP Enable in the USB_OTG Control Register */ + gotgctl.b.hstsethnpen = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GOTGCTL, gotgctl.d32, 0); +#endif + + /* Make sure the FIFOs are flushed. */ + USB_OTG_FlushTxFifo(pdev, 0x10 ); /* all Tx FIFOs */ + USB_OTG_FlushRxFifo(pdev); + + + /* Clear all pending HC Interrupts */ + for (i = 0; i < pdev->cfg.host_channels; i++) + { + USB_OTG_WRITE_REG32( &pdev->regs.HC_REGS[i]->HCINT, 0xFFFFFFFF ); + USB_OTG_WRITE_REG32( &pdev->regs.HC_REGS[i]->HCINTMSK, 0 ); + } +#ifndef USE_OTG_MODE + USB_OTG_DriveVbus(pdev, 1); +#endif + + USB_OTG_EnableHostInt(pdev); + return status; +} + +/** +* @brief USB_OTG_IsEvenFrame +* This function returns the frame number for sof packet +* @param pdev : Selected device +* @retval Frame number +*/ +uint8_t USB_OTG_IsEvenFrame (USB_OTG_CORE_HANDLE *pdev) +{ + return !(USB_OTG_READ_REG32(&pdev->regs.HREGS->HFNUM) & 0x1); +} + +/** +* @brief USB_OTG_DriveVbus : set/reset vbus +* @param pdev : Selected device +* @param state : VBUS state +* @retval None +*/ +void USB_OTG_DriveVbus (USB_OTG_CORE_HANDLE *pdev, uint8_t state) +{ + USB_OTG_HPRT0_TypeDef hprt0; + + hprt0.d32 = 0; + + /* enable disable the external charge pump */ + USB_OTG_BSP_DriveVBUS(pdev, state); + + /* Turn on the Host port power. */ + hprt0.d32 = USB_OTG_ReadHPRT0(pdev); + if ((hprt0.b.prtpwr == 0 ) && (state == 1 )) + { + hprt0.b.prtpwr = 1; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + } + if ((hprt0.b.prtpwr == 1 ) && (state == 0 )) + { + hprt0.b.prtpwr = 0; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + } + + USB_OTG_BSP_mDelay(200); +} +/** +* @brief USB_OTG_EnableHostInt: Enables the Host mode interrupts +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EnableHostInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GINTMSK_TypeDef intmsk; + intmsk.d32 = 0; + /* Disable all interrupts. */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTMSK, 0); + + /* Clear any pending interrupts. */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, 0xFFFFFFFF); + + /* Enable the common interrupts */ + USB_OTG_EnableCommonInt(pdev); + + if (pdev->cfg.dma_enable == 0) + { + intmsk.b.rxstsqlvl = 1; + } + intmsk.b.portintr = 1; + intmsk.b.hcintr = 1; + intmsk.b.disconnect = 1; + intmsk.b.sofintr = 1; + intmsk.b.incomplisoout = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, intmsk.d32, intmsk.d32); + return status; +} + +/** +* @brief USB_OTG_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the +* HCFG register on the PHY type +* @param pdev : Selected device +* @param freq : clock frequency +* @retval None +*/ +void USB_OTG_InitFSLSPClkSel(USB_OTG_CORE_HANDLE *pdev , uint8_t freq) +{ + USB_OTG_HCFG_TypeDef hcfg; + + hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); + hcfg.b.fslspclksel = freq; + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HCFG, hcfg.d32); +} + + +/** +* @brief USB_OTG_ReadHPRT0 : Reads HPRT0 to modify later +* @param pdev : Selected device +* @retval HPRT0 value +*/ +uint32_t USB_OTG_ReadHPRT0(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HPRT0_TypeDef hprt0; + + hprt0.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); + hprt0.b.prtena = 0; + hprt0.b.prtconndet = 0; + hprt0.b.prtenchng = 0; + hprt0.b.prtovrcurrchng = 0; + return hprt0.d32; +} + + +/** +* @brief USB_OTG_ReadHostAllChannels_intr : Register PCD Callbacks +* @param pdev : Selected device +* @retval Status +*/ +uint32_t USB_OTG_ReadHostAllChannels_intr (USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_READ_REG32 (&pdev->regs.HREGS->HAINT)); +} + + +/** +* @brief USB_OTG_ResetPort : Reset Host Port +* @param pdev : Selected device +* @retval status +* @note : (1)The application must wait at least 10 ms (+ 10 ms security) +* before clearing the reset bit. +*/ +uint32_t USB_OTG_ResetPort(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HPRT0_TypeDef hprt0; + + hprt0.d32 = USB_OTG_ReadHPRT0(pdev); + hprt0.b.prtrst = 1; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + USB_OTG_BSP_mDelay (10); /* See Note #1 */ + hprt0.b.prtrst = 0; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + USB_OTG_BSP_mDelay (20); + return 1; +} + + +/** +* @brief USB_OTG_HC_Init : Prepares a host channel for transferring packets +* @param pdev : Selected device +* @param hc_num : channel number +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_HC_Init(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + uint32_t intr_enable = 0; + USB_OTG_HCINTMSK_TypeDef hcintmsk; + USB_OTG_GINTMSK_TypeDef gintmsk; + USB_OTG_HCCHAR_TypeDef hcchar; + USB_OTG_HCINTn_TypeDef hcint; + + + gintmsk.d32 = 0; + hcintmsk.d32 = 0; + hcchar.d32 = 0; + + /* Clear old interrupt conditions for this host channel. */ + hcint.d32 = 0xFFFFFFFF; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCINT, hcint.d32); + + /* Enable channel interrupts required for this transfer. */ + hcintmsk.d32 = 0; + + if (pdev->cfg.dma_enable == 1) + { + hcintmsk.b.ahberr = 1; + } + + switch (pdev->host.hc[hc_num].ep_type) + { + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + hcintmsk.b.xfercompl = 1; + hcintmsk.b.stall = 1; + hcintmsk.b.xacterr = 1; + hcintmsk.b.datatglerr = 1; + hcintmsk.b.nak = 1; + if (pdev->host.hc[hc_num].ep_is_in) + { + hcintmsk.b.bblerr = 1; + } + else + { + hcintmsk.b.nyet = 1; + if (pdev->host.hc[hc_num].do_ping) + { + hcintmsk.b.ack = 1; + } + } + break; + case EP_TYPE_INTR: + hcintmsk.b.xfercompl = 1; + hcintmsk.b.nak = 1; + hcintmsk.b.stall = 1; + hcintmsk.b.xacterr = 1; + hcintmsk.b.datatglerr = 1; + hcintmsk.b.frmovrun = 1; + + if (pdev->host.hc[hc_num].ep_is_in) + { + hcintmsk.b.bblerr = 1; + } + + break; + case EP_TYPE_ISOC: + hcintmsk.b.xfercompl = 1; + hcintmsk.b.frmovrun = 1; + hcintmsk.b.ack = 1; + + if (pdev->host.hc[hc_num].ep_is_in) + { + hcintmsk.b.xacterr = 1; + hcintmsk.b.bblerr = 1; + } + break; + } + + + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK, hcintmsk.d32); + + + /* Enable the top level host channel interrupt. */ + intr_enable = (1 << hc_num); + USB_OTG_MODIFY_REG32(&pdev->regs.HREGS->HAINTMSK, 0, intr_enable); + + /* Make sure host channel interrupts are enabled. */ + gintmsk.b.hcintr = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, 0, gintmsk.d32); + + /* Program the HCCHAR register */ + hcchar.d32 = 0; + hcchar.b.devaddr = pdev->host.hc[hc_num].dev_addr; + hcchar.b.epnum = pdev->host.hc[hc_num].ep_num; + hcchar.b.epdir = pdev->host.hc[hc_num].ep_is_in; + hcchar.b.lspddev = (pdev->host.hc[hc_num].speed == HPRT0_PRTSPD_LOW_SPEED); + hcchar.b.eptype = pdev->host.hc[hc_num].ep_type; + hcchar.b.mps = pdev->host.hc[hc_num].max_packet; + if (pdev->host.hc[hc_num].ep_type == HCCHAR_INTR) + { + hcchar.b.oddfrm = 1; + } + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + return status; +} + + +/** +* @brief USB_OTG_HC_StartXfer : Start transfer +* @param pdev : Selected device +* @param hc_num : channel number +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_HC_StartXfer(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_HCCHAR_TypeDef hcchar; + USB_OTG_HCTSIZn_TypeDef hctsiz; + USB_OTG_HNPTXSTS_TypeDef hnptxsts; + USB_OTG_HPTXSTS_TypeDef hptxsts; + USB_OTG_GINTMSK_TypeDef intmsk; + uint16_t len_words = 0; + + uint16_t num_packets; + uint16_t max_hc_pkt_count; + + max_hc_pkt_count = 256; + hctsiz.d32 = 0; + hcchar.d32 = 0; + intmsk.d32 = 0; + + /* Compute the expected number of packets associated to the transfer */ + if (pdev->host.hc[hc_num].xfer_len > 0) + { + num_packets = (pdev->host.hc[hc_num].xfer_len + \ + pdev->host.hc[hc_num].max_packet - 1) / pdev->host.hc[hc_num].max_packet; + + if (num_packets > max_hc_pkt_count) + { + num_packets = max_hc_pkt_count; + pdev->host.hc[hc_num].xfer_len = num_packets * \ + pdev->host.hc[hc_num].max_packet; + } + } + else + { + num_packets = 1; + } + if (pdev->host.hc[hc_num].ep_is_in) + { + pdev->host.hc[hc_num].xfer_len = num_packets * \ + pdev->host.hc[hc_num].max_packet; + } + /* Initialize the HCTSIZn register */ + hctsiz.b.xfersize = pdev->host.hc[hc_num].xfer_len; + hctsiz.b.pktcnt = num_packets; + hctsiz.b.pid = pdev->host.hc[hc_num].data_pid; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCTSIZ, hctsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCDMA, (unsigned int)pdev->host.hc[hc_num].xfer_buff); + } + + + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR); + hcchar.b.oddfrm = USB_OTG_IsEvenFrame(pdev); + + /* Set host channel enable */ + hcchar.b.chen = 1; + hcchar.b.chdis = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + + if (pdev->cfg.dma_enable == 0) /* Slave mode */ + { + if((pdev->host.hc[hc_num].ep_is_in == 0) && + (pdev->host.hc[hc_num].xfer_len > 0)) + { + switch(pdev->host.hc[hc_num].ep_type) + { + /* Non periodic transfer */ + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + + hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS); + len_words = (pdev->host.hc[hc_num].xfer_len + 3) / 4; + + /* check if there is enough space in FIFO space */ + if(len_words > hnptxsts.b.nptxfspcavail) + { + /* need to process data in nptxfempty interrupt */ + intmsk.b.nptxfempty = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, intmsk.d32); + } + + break; + /* Periodic transfer */ + case EP_TYPE_INTR: + case EP_TYPE_ISOC: + hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS); + len_words = (pdev->host.hc[hc_num].xfer_len + 3) / 4; + /* check if there is enough space in FIFO space */ + if(len_words > hptxsts.b.ptxfspcavail) /* split the transfer */ + { + /* need to process data in ptxfempty interrupt */ + intmsk.b.ptxfempty = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, intmsk.d32); + } + break; + + default: + break; + } + + /* Write packet into the Tx FIFO. */ + USB_OTG_WritePacket(pdev, + pdev->host.hc[hc_num].xfer_buff , + hc_num, pdev->host.hc[hc_num].xfer_len); + } + } + return status; +} + + +/** +* @brief USB_OTG_HC_Halt : Halt channel +* @param pdev : Selected device +* @param hc_num : channel number +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_HC_Halt(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_HNPTXSTS_TypeDef nptxsts; + USB_OTG_HPTXSTS_TypeDef hptxsts; + USB_OTG_HCCHAR_TypeDef hcchar; + + nptxsts.d32 = 0; + hptxsts.d32 = 0; + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR); + hcchar.b.chen = 1; + hcchar.b.chdis = 1; + + /* Check for space in the request queue to issue the halt. */ + if (hcchar.b.eptype == HCCHAR_CTRL || hcchar.b.eptype == HCCHAR_BULK) + { + nptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS); + if (nptxsts.b.nptxqspcavail == 0) + { + hcchar.b.chen = 0; + } + } + else + { + hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS); + if (hptxsts.b.ptxqspcavail == 0) + { + hcchar.b.chen = 0; + } + } + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + return status; +} + +/** +* @brief Issue a ping token +* @param None +* @retval : None +*/ +USB_OTG_STS USB_OTG_HC_DoPing(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_HCCHAR_TypeDef hcchar; + USB_OTG_HCTSIZn_TypeDef hctsiz; + + hctsiz.d32 = 0; + hctsiz.b.dopng = 1; + hctsiz.b.pktcnt = 1; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCTSIZ, hctsiz.d32); + + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR); + hcchar.b.chen = 1; + hcchar.b.chdis = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + return status; +} + +/** +* @brief Stop the device and clean up fifo's +* @param None +* @retval : None +*/ +void USB_OTG_StopHost(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HCCHAR_TypeDef hcchar; + uint32_t i; + + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HAINTMSK , 0); + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HAINT, 0xFFFFFFFF); + /* Flush out any leftover queued requests. */ + + for (i = 0; i < pdev->cfg.host_channels; i++) + { + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[i]->HCCHAR); + hcchar.b.chen = 0; + hcchar.b.chdis = 1; + hcchar.b.epdir = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[i]->HCCHAR, hcchar.d32); + } + + /* Flush the FIFO */ + USB_OTG_FlushRxFifo(pdev); + USB_OTG_FlushTxFifo(pdev , 0x10 ); +} +#endif +#ifdef USE_DEVICE_MODE +/* PCD Core Layer */ + +/** +* @brief USB_OTG_InitDevSpeed :Initializes the DevSpd field of DCFG register +* depending the PHY type and the enumeration speed of the device. +* @param pdev : Selected device +* @retval : None +*/ +void USB_OTG_InitDevSpeed(USB_OTG_CORE_HANDLE *pdev , uint8_t speed) +{ + USB_OTG_DCFG_TypeDef dcfg; + + dcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCFG); + dcfg.b.devspd = speed; + USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCFG, dcfg.d32); +} + + +/** +* @brief USB_OTG_CoreInitDev : Initializes the USB_OTG controller registers +* for device mode +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_CoreInitDev (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + uint32_t i; + USB_OTG_DCFG_TypeDef dcfg; + USB_OTG_FSIZ_TypeDef nptxfifosize; + USB_OTG_FSIZ_TypeDef txfifosize; + USB_OTG_DIEPMSK_TypeDef msk; + USB_OTG_DTHRCTL_TypeDef dthrctl; + + depctl.d32 = 0; + dcfg.d32 = 0; + nptxfifosize.d32 = 0; + txfifosize.d32 = 0; + msk.d32 = 0; + + /* Restart the Phy Clock */ + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, 0); + /* Device configuration register */ + dcfg.d32 = USB_OTG_READ_REG32( &pdev->regs.DREGS->DCFG); + dcfg.b.perfrint = DCFG_FRAME_INTERVAL_80; + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DCFG, dcfg.d32 ); + +#ifdef USB_OTG_FS_CORE + if(pdev->cfg.coreID == USB_OTG_FS_CORE_ID ) + { + + /* Set Full speed phy */ + USB_OTG_InitDevSpeed (pdev , USB_OTG_SPEED_PARAM_FULL); + + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_FS_SIZE); + + /* EP0 TX*/ + nptxfifosize.b.depth = TX0_FIFO_FS_SIZE; + nptxfifosize.b.startaddr = RX_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32 ); + + + /* EP1 TX*/ + txfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth; + txfifosize.b.depth = TX1_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[0], txfifosize.d32 ); + + + /* EP2 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX2_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[1], txfifosize.d32 ); + + + /* EP3 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX3_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[2], txfifosize.d32 ); + } +#endif +#ifdef USB_OTG_HS_CORE + if(pdev->cfg.coreID == USB_OTG_HS_CORE_ID ) + { + + /* Set High speed phy */ + + if(pdev->cfg.phy_itface == USB_OTG_ULPI_PHY) + { + USB_OTG_InitDevSpeed (pdev , USB_OTG_SPEED_PARAM_HIGH); + } + else /* set High speed phy in Full speed mode */ + { + USB_OTG_InitDevSpeed (pdev , USB_OTG_SPEED_PARAM_HIGH_IN_FULL); + } + + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_HS_SIZE); + + /* EP0 TX*/ + nptxfifosize.b.depth = TX0_FIFO_HS_SIZE; + nptxfifosize.b.startaddr = RX_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32 ); + + + /* EP1 TX*/ + txfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth; + txfifosize.b.depth = TX1_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[0], txfifosize.d32 ); + + + /* EP2 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX2_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[1], txfifosize.d32 ); + + + /* EP3 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX3_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[2], txfifosize.d32 ); + + /* EP4 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX4_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[3], txfifosize.d32 ); + + + /* EP5 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX5_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[4], txfifosize.d32 ); + } +#endif + /* Flush the FIFOs */ + USB_OTG_FlushTxFifo(pdev , 0x10); /* all Tx FIFOs */ + USB_OTG_FlushRxFifo(pdev); + /* Clear all pending Device Interrupts */ + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DIEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DOEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINT, 0xFFFFFFFF ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINTMSK, 0 ); + + for (i = 0; i < pdev->cfg.dev_endpoints; i++) + { + depctl.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[i]->DIEPCTL); + if (depctl.b.epena) + { + depctl.d32 = 0; + depctl.b.epdis = 1; + depctl.b.snak = 1; + } + else + { + depctl.d32 = 0; + } + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPCTL, depctl.d32); + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPTSIZ, 0); + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPINT, 0xFF); + } + for (i = 0; i < pdev->cfg.dev_endpoints; i++) + { + USB_OTG_DEPCTL_TypeDef depctl; + depctl.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[i]->DOEPCTL); + if (depctl.b.epena) + { + depctl.d32 = 0; + depctl.b.epdis = 1; + depctl.b.snak = 1; + } + else + { + depctl.d32 = 0; + } + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPCTL, depctl.d32); + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPTSIZ, 0); + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPINT, 0xFF); + } + msk.d32 = 0; + msk.b.txfifoundrn = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPMSK, msk.d32, msk.d32); + + if (pdev->cfg.dma_enable == 1) + { + dthrctl.d32 = 0; + dthrctl.b.non_iso_thr_en = 1; + dthrctl.b.iso_thr_en = 1; + dthrctl.b.tx_thr_len = 64; + dthrctl.b.rx_thr_en = 1; + dthrctl.b.rx_thr_len = 64; + USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DTHRCTL, dthrctl.d32); + } + USB_OTG_EnableDevInt(pdev); + return status; +} + + +/** +* @brief USB_OTG_EnableDevInt : Enables the Device mode interrupts +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EnableDevInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GINTMSK_TypeDef intmsk; + + intmsk.d32 = 0; + + /* Disable all interrupts. */ + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTMSK, 0); + /* Clear any pending interrupts */ + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTSTS, 0xBFFFFFFF); + /* Enable the common interrupts */ + USB_OTG_EnableCommonInt(pdev); + + if (pdev->cfg.dma_enable == 0) + { + intmsk.b.rxstsqlvl = 1; + } + + /* Enable interrupts matching to the Device mode ONLY */ + intmsk.b.usbsuspend = 1; + intmsk.b.usbreset = 1; + intmsk.b.enumdone = 1; + intmsk.b.inepintr = 1; + intmsk.b.outepintr = 1; + intmsk.b.sofintr = 1; + + intmsk.b.incomplisoin = 1; + intmsk.b.incomplisoout = 1; +#ifdef VBUS_SENSING_ENABLED + intmsk.b.sessreqintr = 1; + intmsk.b.otgintr = 1; +#endif + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, intmsk.d32, intmsk.d32); + return status; +} + + +/** +* @brief USB_OTG_GetDeviceSpeed +* Get the device speed from the device status register +* @param None +* @retval status +*/ +enum USB_OTG_SPEED USB_OTG_GetDeviceSpeed (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_DSTS_TypeDef dsts; + enum USB_OTG_SPEED speed = USB_SPEED_UNKNOWN; + + + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + + switch (dsts.b.enumspd) + { + case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: + speed = USB_SPEED_HIGH; + break; + case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: + case DSTS_ENUMSPD_FS_PHY_48MHZ: + speed = USB_SPEED_FULL; + break; + + case DSTS_ENUMSPD_LS_PHY_6MHZ: + speed = USB_SPEED_LOW; + break; + } + + return speed; +} +/** +* @brief enables EP0 OUT to receive SETUP packets and configures EP0 +* for transmitting packets +* @param None +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EP0Activate(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DSTS_TypeDef dsts; + USB_OTG_DEPCTL_TypeDef diepctl; + USB_OTG_DCTL_TypeDef dctl; + + dctl.d32 = 0; + /* Read the Device Status and Endpoint 0 Control registers */ + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + diepctl.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[0]->DIEPCTL); + /* Set the MPS of the IN EP based on the enumeration speed */ + switch (dsts.b.enumspd) + { + case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: + case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: + case DSTS_ENUMSPD_FS_PHY_48MHZ: + diepctl.b.mps = DEP0CTL_MPS_64; + break; + case DSTS_ENUMSPD_LS_PHY_6MHZ: + diepctl.b.mps = DEP0CTL_MPS_8; + break; + } + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[0]->DIEPCTL, diepctl.d32); + dctl.b.cgnpinnak = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, dctl.d32); + return status; +} + + +/** +* @brief USB_OTG_EPActivate : Activates an EP +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPActivate(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DAINT_TypeDef daintmsk; + __IO uint32_t *addr; + + + depctl.d32 = 0; + daintmsk.d32 = 0; + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + addr = &pdev->regs.INEP_REGS[ep->num]->DIEPCTL; + daintmsk.ep.in = 1 << ep->num; + } + else + { + addr = &pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL; + daintmsk.ep.out = 1 << ep->num; + } + /* If the EP is already active don't change the EP Control + * register. */ + depctl.d32 = USB_OTG_READ_REG32(addr); + if (!depctl.b.usbactep) + { + depctl.b.mps = ep->maxpacket; + depctl.b.eptype = ep->type; + depctl.b.txfnum = ep->tx_fifo_num; + depctl.b.setd0pid = 1; + depctl.b.usbactep = 1; + USB_OTG_WRITE_REG32(addr, depctl.d32); + } + /* Enable the Interrupt for this EP */ +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED + if((ep->num == 1)&&(pdev->cfg.coreID == USB_OTG_HS_CORE_ID)) + { + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DEACHMSK, 0, daintmsk.d32); + } + else +#endif + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DAINTMSK, 0, daintmsk.d32); + return status; +} + + +/** +* @brief USB_OTG_EPDeactivate : Deactivates an EP +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPDeactivate(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DAINT_TypeDef daintmsk; + __IO uint32_t *addr; + + depctl.d32 = 0; + daintmsk.d32 = 0; + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + addr = &pdev->regs.INEP_REGS[ep->num]->DIEPCTL; + daintmsk.ep.in = 1 << ep->num; + } + else + { + addr = &pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL; + daintmsk.ep.out = 1 << ep->num; + } + depctl.b.usbactep = 0; + USB_OTG_WRITE_REG32(addr, depctl.d32); + /* Disable the Interrupt for this EP */ + +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED + if((ep->num == 1)&&(pdev->cfg.coreID == USB_OTG_HS_CORE_ID)) + { + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DEACHMSK, daintmsk.d32, 0); + } + else +#endif + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DAINTMSK, daintmsk.d32, 0); + return status; +} + + +/** +* @brief USB_OTG_EPStartXfer : Handle the setup for data xfer for an EP and +* starts the xfer +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPStartXfer(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DEPXFRSIZ_TypeDef deptsiz; + USB_OTG_DSTS_TypeDef dsts; + uint32_t fifoemptymsk = 0; + + depctl.d32 = 0; + deptsiz.d32 = 0; + /* IN endpoint */ + if (ep->is_in == 1) + { + depctl.d32 = USB_OTG_READ_REG32(&(pdev->regs.INEP_REGS[ep->num]->DIEPCTL)); + deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.INEP_REGS[ep->num]->DIEPTSIZ)); + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = 0; + deptsiz.b.pktcnt = 1; + } + else + { + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + deptsiz.b.xfersize = ep->xfer_len; + deptsiz.b.pktcnt = (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; + + if (ep->type == EP_TYPE_ISOC) + { + deptsiz.b.mc = 1; + } + } + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPTSIZ, deptsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPDMA, ep->dma_addr); + } + else + { + if (ep->type != EP_TYPE_ISOC) + { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + fifoemptymsk = 1 << ep->num; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, 0, fifoemptymsk); + } + } + } + + + if (ep->type == EP_TYPE_ISOC) + { + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + + if (((dsts.b.soffn)&0x1) == 0) + { + depctl.b.setd1pid = 1; + } + else + { + depctl.b.setd0pid = 1; + } + } + + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPCTL, depctl.d32); + + if (ep->type == EP_TYPE_ISOC) + { + USB_OTG_WritePacket(pdev, ep->xfer_buff, ep->num, ep->xfer_len); + } + } + else + { + /* OUT endpoint */ + depctl.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL)); + deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ)); + /* Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; + } + else + { + deptsiz.b.pktcnt = (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; + } + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ, deptsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPDMA, ep->dma_addr); + } + + if (ep->type == EP_TYPE_ISOC) + { + if (ep->even_odd_frame) + { + depctl.b.setd1pid = 1; + } + else + { + depctl.b.setd0pid = 1; + } + } + /* EP enable */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL, depctl.d32); + } + return status; +} + + +/** +* @brief USB_OTG_EP0StartXfer : Handle the setup for a data xfer for EP0 and +* starts the xfer +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EP0StartXfer(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DEP0XFRSIZ_TypeDef deptsiz; + USB_OTG_INEPREGS *in_regs; + uint32_t fifoemptymsk = 0; + + depctl.d32 = 0; + deptsiz.d32 = 0; + /* IN endpoint */ + if (ep->is_in == 1) + { + in_regs = pdev->regs.INEP_REGS[0]; + depctl.d32 = USB_OTG_READ_REG32(&in_regs->DIEPCTL); + deptsiz.d32 = USB_OTG_READ_REG32(&in_regs->DIEPTSIZ); + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = 0; + deptsiz.b.pktcnt = 1; + + } + else + { + if (ep->xfer_len > ep->maxpacket) + { + ep->xfer_len = ep->maxpacket; + deptsiz.b.xfersize = ep->maxpacket; + } + else + { + deptsiz.b.xfersize = ep->xfer_len; + } + deptsiz.b.pktcnt = 1; + } + USB_OTG_WRITE_REG32(&in_regs->DIEPTSIZ, deptsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPDMA, ep->dma_addr); + } + + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32(&in_regs->DIEPCTL, depctl.d32); + + + + if (pdev->cfg.dma_enable == 0) + { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + { + fifoemptymsk |= 1 << ep->num; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, 0, fifoemptymsk); + } + } + } + } + else + { + /* OUT endpoint */ + depctl.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + deptsiz.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ); + /* Program the transfer size and packet count as follows: + * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) + * pktcnt = N */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; + } + else + { + ep->xfer_len = ep->maxpacket; + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; + } + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ, deptsiz.d32); + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPDMA, ep->dma_addr); + } + /* EP enable */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32 (&(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL), depctl.d32); + + } + return status; +} + + +/** +* @brief USB_OTG_EPSetStall : Set the EP STALL +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPSetStall(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + + depctl.d32 = 0; + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + /* set the disable and stall bits */ + if (depctl.b.epena) + { + depctl.b.epdis = 1; + } + depctl.b.stall = 1; + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); + } + else + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + /* set the stall bit */ + depctl.b.stall = 1; + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); + } + return status; +} + + +/** +* @brief Clear the EP STALL +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPClearStall(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + + depctl.d32 = 0; + + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + } + else + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + } + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + /* clear the stall bits */ + depctl.b.stall = 0; + if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) + { + depctl.b.setd0pid = 1; /* DATA0 */ + } + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); + return status; +} + + +/** +* @brief USB_OTG_ReadDevAllOutEp_itr : returns OUT endpoint interrupt bits +* @param pdev : Selected device +* @retval OUT endpoint interrupt bits +*/ +uint32_t USB_OTG_ReadDevAllOutEp_itr(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t v; + v = USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINT); + v &= USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINTMSK); + return ((v & 0xffff0000) >> 16); +} + + +/** +* @brief USB_OTG_ReadDevOutEP_itr : returns Device OUT EP Interrupt register +* @param pdev : Selected device +* @param ep : end point number +* @retval Device OUT EP Interrupt register +*/ +uint32_t USB_OTG_ReadDevOutEP_itr(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum) +{ + uint32_t v; + v = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[epnum]->DOEPINT); + v &= USB_OTG_READ_REG32(&pdev->regs.DREGS->DOEPMSK); + return v; +} + + +/** +* @brief USB_OTG_ReadDevAllInEPItr : Get int status register +* @param pdev : Selected device +* @retval int status register +*/ +uint32_t USB_OTG_ReadDevAllInEPItr(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t v; + v = USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINT); + v &= USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINTMSK); + return (v & 0xffff); +} + +/** +* @brief configures EPO to receive SETUP packets +* @param None +* @retval : None +*/ +void USB_OTG_EP0_OutStart(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_DEP0XFRSIZ_TypeDef doeptsize0; + doeptsize0.d32 = 0; + doeptsize0.b.supcnt = 3; + doeptsize0.b.pktcnt = 1; + doeptsize0.b.xfersize = 8 * 3; + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[0]->DOEPTSIZ, doeptsize0.d32 ); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_DEPCTL_TypeDef doepctl; + doepctl.d32 = 0; + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[0]->DOEPDMA, + (uint32_t)&pdev->dev.setup_packet); + + /* EP enable */ + doepctl.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[0]->DOEPCTL); + doepctl.b.epena = 1; + doepctl.d32 = 0x80008000; + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[0]->DOEPCTL, doepctl.d32); + } +} + +/** +* @brief USB_OTG_RemoteWakeup : active remote wakeup signalling +* @param None +* @retval : None +*/ +void USB_OTG_ActiveRemoteWakeup(USB_OTG_CORE_HANDLE *pdev) +{ + + USB_OTG_DCTL_TypeDef dctl; + USB_OTG_DSTS_TypeDef dsts; + USB_OTG_PCGCCTL_TypeDef power; + + if (pdev->dev.DevRemoteWakeup) + { + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + if(dsts.b.suspsts == 1) + { + if(pdev->cfg.low_power) + { + /* un-gate USB Core clock */ + power.d32 = USB_OTG_READ_REG32(&pdev->regs.PCGCCTL); + power.b.gatehclk = 0; + power.b.stoppclk = 0; + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, power.d32); + } + /* active Remote wakeup signaling */ + dctl.d32 = 0; + dctl.b.rmtwkupsig = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, 0, dctl.d32); + USB_OTG_BSP_mDelay(5); + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, 0 ); + } + } +} + + +/** +* @brief USB_OTG_UngateClock : active USB Core clock +* @param None +* @retval : None +*/ +void USB_OTG_UngateClock(USB_OTG_CORE_HANDLE *pdev) +{ + if(pdev->cfg.low_power) + { + + USB_OTG_DSTS_TypeDef dsts; + USB_OTG_PCGCCTL_TypeDef power; + + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + + if(dsts.b.suspsts == 1) + { + /* un-gate USB Core clock */ + power.d32 = USB_OTG_READ_REG32(&pdev->regs.PCGCCTL); + power.b.gatehclk = 0; + power.b.stoppclk = 0; + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, power.d32); + + } + } +} + +/** +* @brief Stop the device and clean up fifo's +* @param None +* @retval : None +*/ +void USB_OTG_StopDevice(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t i; + + pdev->dev.device_status = 1; + + for (i = 0; i < pdev->cfg.dev_endpoints ; i++) + { + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPINT, 0xFF); + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPINT, 0xFF); + } + + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DIEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DOEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINTMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINT, 0xFFFFFFFF ); + + /* Flush the FIFO */ + USB_OTG_FlushRxFifo(pdev); + USB_OTG_FlushTxFifo(pdev , 0x10 ); +} + +/** +* @brief returns the EP Status +* @param pdev : Selected device +* ep : endpoint structure +* @retval : EP status +*/ + +uint32_t USB_OTG_GetEPStatus(USB_OTG_CORE_HANDLE *pdev ,USB_OTG_EP *ep) +{ + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + uint32_t Status = 0; + + depctl.d32 = 0; + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + + if (depctl.b.stall == 1) + Status = USB_OTG_EP_TX_STALL; + else if (depctl.b.naksts == 1) + Status = USB_OTG_EP_TX_NAK; + else + Status = USB_OTG_EP_TX_VALID; + + } + else + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + if (depctl.b.stall == 1) + Status = USB_OTG_EP_RX_STALL; + else if (depctl.b.naksts == 1) + Status = USB_OTG_EP_RX_NAK; + else + Status = USB_OTG_EP_RX_VALID; + } + + /* Return the current status */ + return Status; +} + +/** +* @brief Set the EP Status +* @param pdev : Selected device +* Status : new Status +* ep : EP structure +* @retval : None +*/ +void USB_OTG_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep , uint32_t Status) +{ + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + + depctl.d32 = 0; + + /* Process for IN endpoint */ + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + + if (Status == USB_OTG_EP_TX_STALL) + { + USB_OTG_EPSetStall(pdev, ep); return; + } + else if (Status == USB_OTG_EP_TX_NAK) + depctl.b.snak = 1; + else if (Status == USB_OTG_EP_TX_VALID) + { + if (depctl.b.stall == 1) + { + ep->even_odd_frame = 0; + USB_OTG_EPClearStall(pdev, ep); + return; + } + depctl.b.cnak = 1; + depctl.b.usbactep = 1; + depctl.b.epena = 1; + } + else if (Status == USB_OTG_EP_TX_DIS) + depctl.b.usbactep = 0; + } + else /* Process for OUT endpoint */ + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + + if (Status == USB_OTG_EP_RX_STALL) { + depctl.b.stall = 1; + } + else if (Status == USB_OTG_EP_RX_NAK) + depctl.b.snak = 1; + else if (Status == USB_OTG_EP_RX_VALID) + { + if (depctl.b.stall == 1) + { + ep->even_odd_frame = 0; + USB_OTG_EPClearStall(pdev, ep); + return; + } + depctl.b.cnak = 1; + depctl.b.usbactep = 1; + depctl.b.epena = 1; + } + else if (Status == USB_OTG_EP_RX_DIS) + { + depctl.b.usbactep = 0; + } + } + + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); +} + +#endif +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usb_core.h b/stm/lib/usb_core.h new file mode 100644 index 000000000..c574665c5 --- /dev/null +++ b/stm/lib/usb_core.h @@ -0,0 +1,417 @@ +/** + ****************************************************************************** + * @file usb_core.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Header of the Core Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CORE_H__ +#define __USB_CORE_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" +#include "usb_regs.h" +#include "usb_defines.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_CORE + * @brief usb otg driver core layer + * @{ + */ + + +/** @defgroup USB_CORE_Exported_Defines + * @{ + */ + +#define USB_OTG_EP0_IDLE 0 +#define USB_OTG_EP0_SETUP 1 +#define USB_OTG_EP0_DATA_IN 2 +#define USB_OTG_EP0_DATA_OUT 3 +#define USB_OTG_EP0_STATUS_IN 4 +#define USB_OTG_EP0_STATUS_OUT 5 +#define USB_OTG_EP0_STALL 6 + +#define USB_OTG_EP_TX_DIS 0x0000 +#define USB_OTG_EP_TX_STALL 0x0010 +#define USB_OTG_EP_TX_NAK 0x0020 +#define USB_OTG_EP_TX_VALID 0x0030 + +#define USB_OTG_EP_RX_DIS 0x0000 +#define USB_OTG_EP_RX_STALL 0x1000 +#define USB_OTG_EP_RX_NAK 0x2000 +#define USB_OTG_EP_RX_VALID 0x3000 +/** + * @} + */ +#define MAX_DATA_LENGTH 0x200 + +/** @defgroup USB_CORE_Exported_Types + * @{ + */ + + +typedef enum { + USB_OTG_OK = 0, + USB_OTG_FAIL +}USB_OTG_STS; + +typedef enum { + HC_IDLE = 0, + HC_XFRC, + HC_HALTED, + HC_NAK, + HC_NYET, + HC_STALL, + HC_XACTERR, + HC_BBLERR, + HC_DATATGLERR, +}HC_STATUS; + +typedef enum { + URB_IDLE = 0, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL +}URB_STATE; + +typedef enum { + CTRL_START = 0, + CTRL_XFRC, + CTRL_HALTED, + CTRL_NAK, + CTRL_STALL, + CTRL_XACTERR, + CTRL_BBLERR, + CTRL_DATATGLERR, + CTRL_FAIL +}CTRL_STATUS; + + +typedef struct USB_OTG_hc +{ + uint8_t dev_addr ; + uint8_t ep_num; + uint8_t ep_is_in; + uint8_t speed; + uint8_t do_ping; + uint8_t ep_type; + uint16_t max_packet; + uint8_t data_pid; + uint8_t *xfer_buff; + uint32_t xfer_len; + uint32_t xfer_count; + uint8_t toggle_in; + uint8_t toggle_out; + uint32_t dma_addr; +} +USB_OTG_HC , *PUSB_OTG_HC; + +typedef struct USB_OTG_ep +{ + uint8_t num; + uint8_t is_in; + uint8_t is_stall; + uint8_t type; + uint8_t data_pid_start; + uint8_t even_odd_frame; + uint16_t tx_fifo_num; + uint32_t maxpacket; + /* transaction level variables*/ + uint8_t *xfer_buff; + uint32_t dma_addr; + uint32_t xfer_len; + uint32_t xfer_count; + /* Transfer level variables*/ + uint32_t rem_data_len; + uint32_t total_data_len; + uint32_t ctl_data_len; + +} + +USB_OTG_EP , *PUSB_OTG_EP; + + + +typedef struct USB_OTG_core_cfg +{ + uint8_t host_channels; + uint8_t dev_endpoints; + uint8_t speed; + uint8_t dma_enable; + uint16_t mps; + uint16_t TotalFifoSize; + uint8_t phy_itface; + uint8_t Sof_output; + uint8_t low_power; + uint8_t coreID; + +} +USB_OTG_CORE_CFGS, *PUSB_OTG_CORE_CFGS; + + + +typedef struct usb_setup_req { + + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} USB_SETUP_REQ; + +typedef struct _Device_TypeDef +{ + uint8_t *(*GetDeviceDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetLangIDStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetManufacturerStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetProductStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetSerialStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetConfigurationStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetInterfaceStrDescriptor)( uint8_t speed , uint16_t *length); +} USBD_DEVICE, *pUSBD_DEVICE; + +//typedef struct USB_OTG_hPort +//{ +// void (*Disconnect) (void *phost); +// void (*Connect) (void *phost); +// uint8_t ConnStatus; +// uint8_t DisconnStatus; +// uint8_t ConnHandled; +// uint8_t DisconnHandled; +//} USB_OTG_hPort_TypeDef; + +typedef struct _Device_cb +{ + uint8_t (*Init) (void *pdev , uint8_t cfgidx); + uint8_t (*DeInit) (void *pdev , uint8_t cfgidx); + /* Control Endpoints*/ + uint8_t (*Setup) (void *pdev , USB_SETUP_REQ *req); + uint8_t (*EP0_TxSent) (void *pdev ); + uint8_t (*EP0_RxReady) (void *pdev ); + /* Class Specific Endpoints*/ + uint8_t (*DataIn) (void *pdev , uint8_t epnum); + uint8_t (*DataOut) (void *pdev , uint8_t epnum); + uint8_t (*SOF) (void *pdev); + uint8_t (*IsoINIncomplete) (void *pdev); + uint8_t (*IsoOUTIncomplete) (void *pdev); + + uint8_t *(*GetConfigDescriptor)( uint8_t speed , uint16_t *length); +#ifdef USB_OTG_HS_CORE + uint8_t *(*GetOtherConfigDescriptor)( uint8_t speed , uint16_t *length); +#endif + +#ifdef USB_SUPPORT_USER_STRING_DESC + uint8_t *(*GetUsrStrDescriptor)( uint8_t speed ,uint8_t index, uint16_t *length); +#endif + +} USBD_Class_cb_TypeDef; + + + +typedef struct _USBD_USR_PROP +{ + void (*Init)(void); + void (*DeviceReset)(uint8_t speed); + void (*DeviceConfigured)(void); + void (*DeviceSuspended)(void); + void (*DeviceResumed)(void); + + void (*DeviceConnected)(void); + void (*DeviceDisconnected)(void); + +} +USBD_Usr_cb_TypeDef; + +typedef struct _DCD +{ + uint8_t device_config; + uint8_t device_state; + uint8_t device_status; + uint8_t device_old_status; + uint8_t device_address; + uint8_t connection_status; + uint8_t test_mode; + uint32_t DevRemoteWakeup; + USB_OTG_EP in_ep [USB_OTG_MAX_TX_FIFOS]; + USB_OTG_EP out_ep [USB_OTG_MAX_TX_FIFOS]; + uint8_t setup_packet [8*3]; + USBD_Class_cb_TypeDef *class_cb; + USBD_Usr_cb_TypeDef *usr_cb; + USBD_DEVICE *usr_device; + uint8_t *pConfig_descriptor; + } +DCD_DEV , *DCD_PDEV; + + +typedef struct _HCD +{ + uint8_t Rx_Buffer [MAX_DATA_LENGTH]; + __IO uint32_t ConnSts; + __IO uint32_t ErrCnt[USB_OTG_MAX_TX_FIFOS]; + __IO uint32_t XferCnt[USB_OTG_MAX_TX_FIFOS]; + __IO HC_STATUS HC_Status[USB_OTG_MAX_TX_FIFOS]; + __IO URB_STATE URB_State[USB_OTG_MAX_TX_FIFOS]; + USB_OTG_HC hc [USB_OTG_MAX_TX_FIFOS]; + uint16_t channel [USB_OTG_MAX_TX_FIFOS]; +// USB_OTG_hPort_TypeDef *port_cb; +} +HCD_DEV , *USB_OTG_USBH_PDEV; + + +typedef struct _OTG +{ + uint8_t OTG_State; + uint8_t OTG_PrevState; + uint8_t OTG_Mode; +} +OTG_DEV , *USB_OTG_USBO_PDEV; + +typedef struct USB_OTG_handle +{ + USB_OTG_CORE_CFGS cfg; + USB_OTG_CORE_REGS regs; +#ifdef USE_DEVICE_MODE + DCD_DEV dev; +#endif +#ifdef USE_HOST_MODE + HCD_DEV host; +#endif +#ifdef USE_OTG_MODE + OTG_DEV otg; +#endif +} +USB_OTG_CORE_HANDLE , *PUSB_OTG_CORE_HANDLE; + +/** + * @} + */ + + +/** @defgroup USB_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_FunctionsPrototype + * @{ + */ + + +USB_OTG_STS USB_OTG_CoreInit (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_SelectCore (USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID); +USB_OTG_STS USB_OTG_EnableGlobalInt (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_DisableGlobalInt(USB_OTG_CORE_HANDLE *pdev); +void* USB_OTG_ReadPacket (USB_OTG_CORE_HANDLE *pdev , + uint8_t *dest, + uint16_t len); +USB_OTG_STS USB_OTG_WritePacket (USB_OTG_CORE_HANDLE *pdev , + uint8_t *src, + uint8_t ch_ep_num, + uint16_t len); +USB_OTG_STS USB_OTG_FlushTxFifo (USB_OTG_CORE_HANDLE *pdev , uint32_t num); +USB_OTG_STS USB_OTG_FlushRxFifo (USB_OTG_CORE_HANDLE *pdev); + +uint32_t USB_OTG_ReadCoreItr (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadOtgItr (USB_OTG_CORE_HANDLE *pdev); +uint8_t USB_OTG_IsHostMode (USB_OTG_CORE_HANDLE *pdev); +uint8_t USB_OTG_IsDeviceMode (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_GetMode (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_PhyInit (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_SetCurrentMode (USB_OTG_CORE_HANDLE *pdev, + uint8_t mode); + +/*********************** HOST APIs ********************************************/ +#ifdef USE_HOST_MODE +USB_OTG_STS USB_OTG_CoreInitHost (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EnableHostInt (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_HC_Init (USB_OTG_CORE_HANDLE *pdev, uint8_t hc_num); +USB_OTG_STS USB_OTG_HC_Halt (USB_OTG_CORE_HANDLE *pdev, uint8_t hc_num); +USB_OTG_STS USB_OTG_HC_StartXfer (USB_OTG_CORE_HANDLE *pdev, uint8_t hc_num); +USB_OTG_STS USB_OTG_HC_DoPing (USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num); +uint32_t USB_OTG_ReadHostAllChannels_intr (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ResetPort (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadHPRT0 (USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_DriveVbus (USB_OTG_CORE_HANDLE *pdev, uint8_t state); +void USB_OTG_InitFSLSPClkSel (USB_OTG_CORE_HANDLE *pdev ,uint8_t freq); +uint8_t USB_OTG_IsEvenFrame (USB_OTG_CORE_HANDLE *pdev) ; +void USB_OTG_StopHost (USB_OTG_CORE_HANDLE *pdev); +#endif +/********************* DEVICE APIs ********************************************/ +#ifdef USE_DEVICE_MODE +USB_OTG_STS USB_OTG_CoreInitDev (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EnableDevInt (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadDevAllInEPItr (USB_OTG_CORE_HANDLE *pdev); +enum USB_OTG_SPEED USB_OTG_GetDeviceSpeed (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EP0Activate (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EPActivate (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPDeactivate(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPStartXfer (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EP0StartXfer(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPSetStall (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPClearStall (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +uint32_t USB_OTG_ReadDevAllOutEp_itr (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadDevOutEP_itr (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum); +uint32_t USB_OTG_ReadDevAllInEPItr (USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_InitDevSpeed (USB_OTG_CORE_HANDLE *pdev , uint8_t speed); +uint8_t USBH_IsEvenFrame (USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_EP0_OutStart(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_ActiveRemoteWakeup(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_UngateClock(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_StopDevice(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep , uint32_t Status); +uint32_t USB_OTG_GetEPStatus(USB_OTG_CORE_HANDLE *pdev ,USB_OTG_EP *ep); +#endif +/** + * @} + */ + +#endif /* __USB_CORE_H__ */ + + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_dcd.c b/stm/lib/usb_dcd.c new file mode 100644 index 000000000..eac8c3371 --- /dev/null +++ b/stm/lib/usb_dcd.c @@ -0,0 +1,478 @@ +/** + ****************************************************************************** + * @file usb_dcd.c + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Peripheral Device Interface Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_dcd.h" +#include "usb_bsp.h" + + +/** @addtogroup USB_OTG_DRIVER +* @{ +*/ + +/** @defgroup USB_DCD +* @brief This file is the interface between EFSL ans Host mass-storage class +* @{ +*/ + + +/** @defgroup USB_DCD_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_DCD_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USB_DCD_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_DCD_Private_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_DCD_Private_FunctionPrototypes +* @{ +*/ + +/** +* @} +*/ + + +/** @defgroup USB_DCD_Private_Functions +* @{ +*/ + + + +void DCD_Init(USB_OTG_CORE_HANDLE *pdev , + USB_OTG_CORE_ID_TypeDef coreID) +{ + uint32_t i; + USB_OTG_EP *ep; + + USB_OTG_SelectCore (pdev , coreID); + + pdev->dev.device_status = USB_OTG_DEFAULT; + pdev->dev.device_address = 0; + + /* Init ep structure */ + for (i = 0; i < pdev->cfg.dev_endpoints ; i++) + { + ep = &pdev->dev.in_ep[i]; + /* Init ep structure */ + ep->is_in = 1; + ep->num = i; + ep->tx_fifo_num = i; + /* Control until ep is actvated */ + ep->type = EP_TYPE_CTRL; + ep->maxpacket = USB_OTG_MAX_EP0_SIZE; + ep->xfer_buff = 0; + ep->xfer_len = 0; + } + + for (i = 0; i < pdev->cfg.dev_endpoints; i++) + { + ep = &pdev->dev.out_ep[i]; + /* Init ep structure */ + ep->is_in = 0; + ep->num = i; + ep->tx_fifo_num = i; + /* Control until ep is activated */ + ep->type = EP_TYPE_CTRL; + ep->maxpacket = USB_OTG_MAX_EP0_SIZE; + ep->xfer_buff = 0; + ep->xfer_len = 0; + } + + USB_OTG_DisableGlobalInt(pdev); + + /*Init the Core (common init.) */ + USB_OTG_CoreInit(pdev); + + + /* Force Device Mode*/ + USB_OTG_SetCurrentMode(pdev, DEVICE_MODE); + + /* Init Device */ + USB_OTG_CoreInitDev(pdev); + + + /* Enable USB Global interrupt */ + USB_OTG_EnableGlobalInt(pdev); +} + + +/** +* @brief Configure an EP +* @param pdev : Device instance +* @param epdesc : Endpoint Descriptor +* @retval : status +*/ +uint32_t DCD_EP_Open(USB_OTG_CORE_HANDLE *pdev , + uint8_t ep_addr, + uint16_t ep_mps, + uint8_t ep_type) +{ + USB_OTG_EP *ep; + + if ((ep_addr & 0x80) == 0x80) + { + ep = &pdev->dev.in_ep[ep_addr & 0x7F]; + } + else + { + ep = &pdev->dev.out_ep[ep_addr & 0x7F]; + } + ep->num = ep_addr & 0x7F; + + ep->is_in = (0x80 & ep_addr) != 0; + ep->maxpacket = ep_mps; + ep->type = ep_type; + if (ep->is_in) + { + /* Assign a Tx FIFO */ + ep->tx_fifo_num = ep->num; + } + /* Set initial data PID. */ + if (ep_type == USB_OTG_EP_BULK ) + { + ep->data_pid_start = 0; + } + USB_OTG_EPActivate(pdev , ep ); + return 0; +} +/** +* @brief called when an EP is disabled +* @param pdev: device instance +* @param ep_addr: endpoint address +* @retval : status +*/ +uint32_t DCD_EP_Close(USB_OTG_CORE_HANDLE *pdev , uint8_t ep_addr) +{ + USB_OTG_EP *ep; + + if ((ep_addr&0x80) == 0x80) + { + ep = &pdev->dev.in_ep[ep_addr & 0x7F]; + } + else + { + ep = &pdev->dev.out_ep[ep_addr & 0x7F]; + } + ep->num = ep_addr & 0x7F; + ep->is_in = (0x80 & ep_addr) != 0; + USB_OTG_EPDeactivate(pdev , ep ); + return 0; +} + + +/** +* @brief DCD_EP_PrepareRx +* @param pdev: device instance +* @param ep_addr: endpoint address +* @param pbuf: pointer to Rx buffer +* @param buf_len: data length +* @retval : status +*/ +uint32_t DCD_EP_PrepareRx( USB_OTG_CORE_HANDLE *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t buf_len) +{ + USB_OTG_EP *ep; + + ep = &pdev->dev.out_ep[ep_addr & 0x7F]; + + /*setup and start the Xfer */ + ep->xfer_buff = pbuf; + ep->xfer_len = buf_len; + ep->xfer_count = 0; + ep->is_in = 0; + ep->num = ep_addr & 0x7F; + + if (pdev->cfg.dma_enable == 1) + { + ep->dma_addr = (uint32_t)pbuf; + } + + if ( ep->num == 0 ) + { + USB_OTG_EP0StartXfer(pdev , ep); + } + else + { + USB_OTG_EPStartXfer(pdev, ep ); + } + return 0; +} + +/** +* @brief Transmit data over USB +* @param pdev: device instance +* @param ep_addr: endpoint address +* @param pbuf: pointer to Tx buffer +* @param buf_len: data length +* @retval : status +*/ +uint32_t DCD_EP_Tx ( USB_OTG_CORE_HANDLE *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint32_t buf_len) +{ + USB_OTG_EP *ep; + + ep = &pdev->dev.in_ep[ep_addr & 0x7F]; + + /* Setup and start the Transfer */ + ep->is_in = 1; + ep->num = ep_addr & 0x7F; + ep->xfer_buff = pbuf; + ep->dma_addr = (uint32_t)pbuf; + ep->xfer_count = 0; + ep->xfer_len = buf_len; + + if ( ep->num == 0 ) + { + USB_OTG_EP0StartXfer(pdev , ep); + } + else + { + USB_OTG_EPStartXfer(pdev, ep ); + } + return 0; +} + + +/** +* @brief Stall an endpoint. +* @param pdev: device instance +* @param epnum: endpoint address +* @retval : status +*/ +uint32_t DCD_EP_Stall (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum) +{ + USB_OTG_EP *ep; + if ((0x80 & epnum) == 0x80) + { + ep = &pdev->dev.in_ep[epnum & 0x7F]; + } + else + { + ep = &pdev->dev.out_ep[epnum]; + } + + ep->is_stall = 1; + ep->num = epnum & 0x7F; + ep->is_in = ((epnum & 0x80) == 0x80); + + USB_OTG_EPSetStall(pdev , ep); + return (0); +} + + +/** +* @brief Clear stall condition on endpoints. +* @param pdev: device instance +* @param epnum: endpoint address +* @retval : status +*/ +uint32_t DCD_EP_ClrStall (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum) +{ + USB_OTG_EP *ep; + if ((0x80 & epnum) == 0x80) + { + ep = &pdev->dev.in_ep[epnum & 0x7F]; + } + else + { + ep = &pdev->dev.out_ep[epnum]; + } + + ep->is_stall = 0; + ep->num = epnum & 0x7F; + ep->is_in = ((epnum & 0x80) == 0x80); + + USB_OTG_EPClearStall(pdev , ep); + return (0); +} + + +/** +* @brief This Function flushes the FIFOs. +* @param pdev: device instance +* @param epnum: endpoint address +* @retval : status +*/ +uint32_t DCD_EP_Flush (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum) +{ + + if ((epnum & 0x80) == 0x80) + { + USB_OTG_FlushTxFifo(pdev, epnum & 0x7F); + } + else + { + USB_OTG_FlushRxFifo(pdev); + } + + return (0); +} + + +/** +* @brief This Function set USB device address +* @param pdev: device instance +* @param address: new device address +* @retval : status +*/ +void DCD_EP_SetAddress (USB_OTG_CORE_HANDLE *pdev, uint8_t address) +{ + USB_OTG_DCFG_TypeDef dcfg; + dcfg.d32 = 0; + dcfg.b.devaddr = address; + USB_OTG_MODIFY_REG32( &pdev->regs.DREGS->DCFG, 0, dcfg.d32); +} + +/** +* @brief Connect device (enable internal pull-up) +* @param pdev: device instance +* @retval : None +*/ +void DCD_DevConnect (USB_OTG_CORE_HANDLE *pdev) +{ +#ifndef USE_OTG_MODE + USB_OTG_DCTL_TypeDef dctl; + dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL); + /* Connect device */ + dctl.b.sftdiscon = 0; + USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, dctl.d32); + USB_OTG_BSP_mDelay(3); +#endif +} + + +/** +* @brief Disconnect device (disable internal pull-up) +* @param pdev: device instance +* @retval : None +*/ +void DCD_DevDisconnect (USB_OTG_CORE_HANDLE *pdev) +{ +#ifndef USE_OTG_MODE + USB_OTG_DCTL_TypeDef dctl; + dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL); + /* Disconnect device for 3ms */ + dctl.b.sftdiscon = 1; + USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, dctl.d32); + USB_OTG_BSP_mDelay(3); +#endif +} + + +/** +* @brief returns the EP Status +* @param pdev : Selected device +* epnum : endpoint address +* @retval : EP status +*/ + +uint32_t DCD_GetEPStatus(USB_OTG_CORE_HANDLE *pdev ,uint8_t epnum) +{ + USB_OTG_EP *ep; + uint32_t Status = 0; + + if ((0x80 & epnum) == 0x80) + { + ep = &pdev->dev.in_ep[epnum & 0x7F]; + } + else + { + ep = &pdev->dev.out_ep[epnum]; + } + + Status = USB_OTG_GetEPStatus(pdev ,ep); + + /* Return the current status */ + return Status; +} + +/** +* @brief Set the EP Status +* @param pdev : Selected device +* Status : new Status +* epnum : EP address +* @retval : None +*/ +void DCD_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum , uint32_t Status) +{ + USB_OTG_EP *ep; + + if ((0x80 & epnum) == 0x80) + { + ep = &pdev->dev.in_ep[epnum & 0x7F]; + } + else + { + ep = &pdev->dev.out_ep[epnum]; + } + + USB_OTG_SetEPStatus(pdev ,ep , Status); +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usb_dcd.h b/stm/lib/usb_dcd.h new file mode 100644 index 000000000..6922782a7 --- /dev/null +++ b/stm/lib/usb_dcd.h @@ -0,0 +1,164 @@ +/** + ****************************************************************************** + * @file usb_dcd.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Peripheral Driver Header file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __DCD_H__ +#define __DCD_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_core.h" + + +/** @addtogroup USB_OTG_DRIVER +* @{ +*/ + +/** @defgroup USB_DCD +* @brief This file is the +* @{ +*/ + + +/** @defgroup USB_DCD_Exported_Defines +* @{ +*/ +#define USB_OTG_EP_CONTROL 0 +#define USB_OTG_EP_ISOC 1 +#define USB_OTG_EP_BULK 2 +#define USB_OTG_EP_INT 3 +#define USB_OTG_EP_MASK 3 + +/* Device Status */ +#define USB_OTG_DEFAULT 1 +#define USB_OTG_ADDRESSED 2 +#define USB_OTG_CONFIGURED 3 +#define USB_OTG_SUSPENDED 4 + +/** +* @} +*/ + + +/** @defgroup USB_DCD_Exported_Types +* @{ +*/ +/******************************************************************************** +Data structure type +********************************************************************************/ +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} +EP_DESCRIPTOR , *PEP_DESCRIPTOR; + +/** +* @} +*/ + + +/** @defgroup USB_DCD_Exported_Macros +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USB_DCD_Exported_Variables +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USB_DCD_Exported_FunctionsPrototype +* @{ +*/ +/******************************************************************************** +EXPORTED FUNCTION FROM THE USB-OTG LAYER +********************************************************************************/ +void DCD_Init(USB_OTG_CORE_HANDLE *pdev , + USB_OTG_CORE_ID_TypeDef coreID); + +void DCD_DevConnect (USB_OTG_CORE_HANDLE *pdev); +void DCD_DevDisconnect (USB_OTG_CORE_HANDLE *pdev); +void DCD_EP_SetAddress (USB_OTG_CORE_HANDLE *pdev, + uint8_t address); +uint32_t DCD_EP_Open(USB_OTG_CORE_HANDLE *pdev , + uint8_t ep_addr, + uint16_t ep_mps, + uint8_t ep_type); + +uint32_t DCD_EP_Close (USB_OTG_CORE_HANDLE *pdev, + uint8_t ep_addr); + + +uint32_t DCD_EP_PrepareRx ( USB_OTG_CORE_HANDLE *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t buf_len); + +uint32_t DCD_EP_Tx (USB_OTG_CORE_HANDLE *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint32_t buf_len); +uint32_t DCD_EP_Stall (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum); +uint32_t DCD_EP_ClrStall (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum); +uint32_t DCD_EP_Flush (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum); +uint32_t DCD_Handle_ISR(USB_OTG_CORE_HANDLE *pdev); + +uint32_t DCD_GetEPStatus(USB_OTG_CORE_HANDLE *pdev , + uint8_t epnum); + +void DCD_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , + uint8_t epnum , + uint32_t Status); + +/** +* @} +*/ + + +#endif //__DCD_H__ + + +/** +* @} +*/ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_dcd_int.c b/stm/lib/usb_dcd_int.c new file mode 100644 index 000000000..32984e610 --- /dev/null +++ b/stm/lib/usb_dcd_int.c @@ -0,0 +1,869 @@ +/** + ****************************************************************************** + * @file usb_dcd_int.c + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Peripheral Device interrupt subroutines + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_dcd_int.h" +/** @addtogroup USB_OTG_DRIVER +* @{ +*/ + +/** @defgroup USB_DCD_INT +* @brief This file contains the interrupt subroutines for the Device mode. +* @{ +*/ + + +/** @defgroup USB_DCD_INT_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_DCD_INT_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USB_DCD_INT_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_DCD_INT_Private_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_DCD_INT_Private_FunctionPrototypes +* @{ +*/ +/* static functions */ +static uint32_t DCD_ReadDevInEP (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum); + +/* Interrupt Handlers */ +static uint32_t DCD_HandleInEP_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_HandleOutEP_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_HandleSof_ISR(USB_OTG_CORE_HANDLE *pdev); + +static uint32_t DCD_HandleRxStatusQueueLevel_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev , uint32_t epnum); + +static uint32_t DCD_HandleUsbReset_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_HandleEnumDone_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_HandleResume_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_HandleUSBSuspend_ISR(USB_OTG_CORE_HANDLE *pdev); + +static uint32_t DCD_IsoINIncomplete_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_IsoOUTIncomplete_ISR(USB_OTG_CORE_HANDLE *pdev); +#ifdef VBUS_SENSING_ENABLED +static uint32_t DCD_SessionRequest_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t DCD_OTG_ISR(USB_OTG_CORE_HANDLE *pdev); +#endif + +/** +* @} +*/ + + +/** @defgroup USB_DCD_INT_Private_Functions +* @{ +*/ + + +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED +/** +* @brief USBD_OTG_EP1OUT_ISR_Handler +* handles all USB Interrupts +* @param pdev: device instance +* @retval status +*/ +uint32_t USBD_OTG_EP1OUT_ISR_Handler (USB_OTG_CORE_HANDLE *pdev) +{ + + USB_OTG_DOEPINTn_TypeDef doepint; + USB_OTG_DEPXFRSIZ_TypeDef deptsiz; + + doepint.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[1]->DOEPINT); + doepint.d32&= USB_OTG_READ_REG32(&pdev->regs.DREGS->DOUTEP1MSK); + + /* Transfer complete */ + if ( doepint.b.xfercompl ) + { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(1, xfercompl); + if (pdev->cfg.dma_enable == 1) + { + deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[1]->DOEPTSIZ)); + /*ToDo : handle more than one single MPS size packet */ + pdev->dev.out_ep[1].xfer_count = pdev->dev.out_ep[1].maxpacket - \ + deptsiz.b.xfersize; + } + /* Inform upper layer: data ready */ + /* RX COMPLETE */ + USBD_DCD_INT_fops->DataOutStage(pdev , 1); + + } + + /* Endpoint disable */ + if ( doepint.b.epdisabled ) + { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(1, epdisabled); + } + + return 1; +} + +/** +* @brief USBD_OTG_EP1IN_ISR_Handler +* handles all USB Interrupts +* @param pdev: device instance +* @retval status +*/ +uint32_t USBD_OTG_EP1IN_ISR_Handler (USB_OTG_CORE_HANDLE *pdev) +{ + + USB_OTG_DIEPINTn_TypeDef diepint; + uint32_t fifoemptymsk, msk, emp; + + msk = USB_OTG_READ_REG32(&pdev->regs.DREGS->DINEP1MSK); + emp = USB_OTG_READ_REG32(&pdev->regs.DREGS->DIEPEMPMSK); + msk |= ((emp >> 1 ) & 0x1) << 7; + diepint.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[1]->DIEPINT) & msk; + + if ( diepint.b.xfercompl ) + { + fifoemptymsk = 0x1 << 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0); + CLEAR_IN_EP_INTR(1, xfercompl); + /* TX COMPLETE */ + USBD_DCD_INT_fops->DataInStage(pdev , 1); + } + if ( diepint.b.epdisabled ) + { + CLEAR_IN_EP_INTR(1, epdisabled); + } + if ( diepint.b.timeout ) + { + CLEAR_IN_EP_INTR(1, timeout); + } + if (diepint.b.intktxfemp) + { + CLEAR_IN_EP_INTR(1, intktxfemp); + } + if (diepint.b.inepnakeff) + { + CLEAR_IN_EP_INTR(1, inepnakeff); + } + if (diepint.b.emptyintr) + { + DCD_WriteEmptyTxFifo(pdev , 1); + CLEAR_IN_EP_INTR(1, emptyintr); + } + return 1; +} +#endif + +/** +* @brief STM32_USBF_OTG_ISR_Handler +* handles all USB Interrupts +* @param pdev: device instance +* @retval status +*/ +uint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintr_status; + uint32_t retval = 0; + + if (USB_OTG_IsDeviceMode(pdev)) /* ensure that we are in device mode */ + { + gintr_status.d32 = USB_OTG_ReadCoreItr(pdev); + if (!gintr_status.d32) /* avoid spurious interrupt */ + { + return 0; + } + + if (gintr_status.b.outepintr) + { + retval |= DCD_HandleOutEP_ISR(pdev); + } + + if (gintr_status.b.inepint) + { + retval |= DCD_HandleInEP_ISR(pdev); + } + + if (gintr_status.b.modemismatch) + { + USB_OTG_GINTSTS_TypeDef gintsts; + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.modemismatch = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32); + } + + if (gintr_status.b.wkupintr) + { + retval |= DCD_HandleResume_ISR(pdev); + } + + if (gintr_status.b.usbsuspend) + { + retval |= DCD_HandleUSBSuspend_ISR(pdev); + } + if (gintr_status.b.sofintr) + { + retval |= DCD_HandleSof_ISR(pdev); + + } + + if (gintr_status.b.rxstsqlvl) + { + retval |= DCD_HandleRxStatusQueueLevel_ISR(pdev); + + } + + if (gintr_status.b.usbreset) + { + retval |= DCD_HandleUsbReset_ISR(pdev); + + } + if (gintr_status.b.enumdone) + { + retval |= DCD_HandleEnumDone_ISR(pdev); + } + + if (gintr_status.b.incomplisoin) + { + retval |= DCD_IsoINIncomplete_ISR(pdev); + } + + if (gintr_status.b.incomplisoout) + { + retval |= DCD_IsoOUTIncomplete_ISR(pdev); + } +#ifdef VBUS_SENSING_ENABLED + if (gintr_status.b.sessreqintr) + { + retval |= DCD_SessionRequest_ISR(pdev); + } + + if (gintr_status.b.otgintr) + { + retval |= DCD_OTG_ISR(pdev); + } +#endif + } + return retval; +} + +#ifdef VBUS_SENSING_ENABLED +/** +* @brief DCD_SessionRequest_ISR +* Indicates that the USB_OTG controller has detected a connection +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_SessionRequest_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + USBD_DCD_INT_fops->DevConnected (pdev); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.sessreqintr = 1; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32); + return 1; +} + +/** +* @brief DCD_OTG_ISR +* Indicates that the USB_OTG controller has detected an OTG event: +* used to detect the end of session i.e. disconnection +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_OTG_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + + USB_OTG_GOTGINT_TypeDef gotgint; + + gotgint.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGINT); + + if (gotgint.b.sesenddet) + { + USBD_DCD_INT_fops->DevDisconnected (pdev); + } + /* Clear OTG interrupt */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GOTGINT, gotgint.d32); + return 1; +} +#endif +/** +* @brief DCD_HandleResume_ISR +* Indicates that the USB_OTG controller has detected a resume or +* remote Wake-up sequence +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleResume_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + USB_OTG_DCTL_TypeDef devctl; + USB_OTG_PCGCCTL_TypeDef power; + + if(pdev->cfg.low_power) + { + /* un-gate USB Core clock */ + power.d32 = USB_OTG_READ_REG32(&pdev->regs.PCGCCTL); + power.b.gatehclk = 0; + power.b.stoppclk = 0; + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, power.d32); + } + + /* Clear the Remote Wake-up Signaling */ + devctl.d32 = 0; + devctl.b.rmtwkupsig = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, devctl.d32, 0); + + /* Inform upper layer by the Resume Event */ + USBD_DCD_INT_fops->Resume (pdev); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.wkupintr = 1; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32); + return 1; +} + +/** +* @brief USB_OTG_HandleUSBSuspend_ISR +* Indicates that SUSPEND state has been detected on the USB +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleUSBSuspend_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + USB_OTG_PCGCCTL_TypeDef power; + USB_OTG_DSTS_TypeDef dsts; + __IO uint8_t prev_status = 0; + + prev_status = pdev->dev.device_status; + USBD_DCD_INT_fops->Suspend (pdev); + + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.usbsuspend = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32); + + if((pdev->cfg.low_power) && (dsts.b.suspsts == 1) && + (pdev->dev.connection_status == 1) && + (prev_status == USB_OTG_CONFIGURED)) + { + /* switch-off the clocks */ + power.d32 = 0; + power.b.stoppclk = 1; + USB_OTG_MODIFY_REG32(pdev->regs.PCGCCTL, 0, power.d32); + + power.b.gatehclk = 1; + USB_OTG_MODIFY_REG32(pdev->regs.PCGCCTL, 0, power.d32); + + /* Request to enter Sleep mode after exit from current ISR */ + SCB->SCR |= (SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk); + } + return 1; +} + +/** +* @brief DCD_HandleInEP_ISR +* Indicates that an IN EP has a pending Interrupt +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleInEP_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_DIEPINTn_TypeDef diepint; + + uint32_t ep_intr; + uint32_t epnum = 0; + uint32_t fifoemptymsk; + diepint.d32 = 0; + ep_intr = USB_OTG_ReadDevAllInEPItr(pdev); + + while ( ep_intr ) + { + if (ep_intr&0x1) /* In ITR */ + { + diepint.d32 = DCD_ReadDevInEP(pdev , epnum); /* Get In ITR status */ + if ( diepint.b.xfercompl ) + { + fifoemptymsk = 0x1 << epnum; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, fifoemptymsk, 0); + CLEAR_IN_EP_INTR(epnum, xfercompl); + /* TX COMPLETE */ + USBD_DCD_INT_fops->DataInStage(pdev , epnum); + + if (pdev->cfg.dma_enable == 1) + { + if((epnum == 0) && (pdev->dev.device_state == USB_OTG_EP0_STATUS_IN)) + { + /* prepare to rx more setup packets */ + USB_OTG_EP0_OutStart(pdev); + } + } + } + if ( diepint.b.timeout ) + { + CLEAR_IN_EP_INTR(epnum, timeout); + } + if (diepint.b.intktxfemp) + { + CLEAR_IN_EP_INTR(epnum, intktxfemp); + } + if (diepint.b.inepnakeff) + { + CLEAR_IN_EP_INTR(epnum, inepnakeff); + } + if ( diepint.b.epdisabled ) + { + CLEAR_IN_EP_INTR(epnum, epdisabled); + } + if (diepint.b.emptyintr) + { + + DCD_WriteEmptyTxFifo(pdev , epnum); + + CLEAR_IN_EP_INTR(epnum, emptyintr); + } + } + epnum++; + ep_intr >>= 1; + } + + return 1; +} + +/** +* @brief DCD_HandleOutEP_ISR +* Indicates that an OUT EP has a pending Interrupt +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleOutEP_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t ep_intr; + USB_OTG_DOEPINTn_TypeDef doepint; + USB_OTG_DEPXFRSIZ_TypeDef deptsiz; + uint32_t epnum = 0; + + doepint.d32 = 0; + + /* Read in the device interrupt bits */ + ep_intr = USB_OTG_ReadDevAllOutEp_itr(pdev); + + while ( ep_intr ) + { + if (ep_intr&0x1) + { + + doepint.d32 = USB_OTG_ReadDevOutEP_itr(pdev, epnum); + + /* Transfer complete */ + if ( doepint.b.xfercompl ) + { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(epnum, xfercompl); + if (pdev->cfg.dma_enable == 1) + { + deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[epnum]->DOEPTSIZ)); + /*ToDo : handle more than one single MPS size packet */ + pdev->dev.out_ep[epnum].xfer_count = pdev->dev.out_ep[epnum].maxpacket - \ + deptsiz.b.xfersize; + } + /* Inform upper layer: data ready */ + /* RX COMPLETE */ + USBD_DCD_INT_fops->DataOutStage(pdev , epnum); + + if (pdev->cfg.dma_enable == 1) + { + if((epnum == 0) && (pdev->dev.device_state == USB_OTG_EP0_STATUS_OUT)) + { + /* prepare to rx more setup packets */ + USB_OTG_EP0_OutStart(pdev); + } + } + } + /* Endpoint disable */ + if ( doepint.b.epdisabled ) + { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(epnum, epdisabled); + } + /* Setup Phase Done (control EPs) */ + if ( doepint.b.setup ) + { + + /* inform the upper layer that a setup packet is available */ + /* SETUP COMPLETE */ + USBD_DCD_INT_fops->SetupStage(pdev); + CLEAR_OUT_EP_INTR(epnum, setup); + } + } + epnum++; + ep_intr >>= 1; + } + return 1; +} + +/** +* @brief DCD_HandleSof_ISR +* Handles the SOF Interrupts +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleSof_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef GINTSTS; + + + USBD_DCD_INT_fops->SOF(pdev); + + /* Clear interrupt */ + GINTSTS.d32 = 0; + GINTSTS.b.sofintr = 1; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, GINTSTS.d32); + + return 1; +} + +/** +* @brief DCD_HandleRxStatusQueueLevel_ISR +* Handles the Rx Status Queue Level Interrupt +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleRxStatusQueueLevel_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTMSK_TypeDef int_mask; + USB_OTG_DRXSTS_TypeDef status; + USB_OTG_EP *ep; + + /* Disable the Rx Status Queue Level interrupt */ + int_mask.d32 = 0; + int_mask.b.rxstsqlvl = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, int_mask.d32, 0); + + /* Get the Status from the top of the FIFO */ + status.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRXSTSP ); + + ep = &pdev->dev.out_ep[status.b.epnum]; + + switch (status.b.pktsts) + { + case STS_GOUT_NAK: + break; + case STS_DATA_UPDT: + if (status.b.bcnt) + { + USB_OTG_ReadPacket(pdev,ep->xfer_buff, status.b.bcnt); + ep->xfer_buff += status.b.bcnt; + ep->xfer_count += status.b.bcnt; + } + break; + case STS_XFER_COMP: + break; + case STS_SETUP_COMP: + break; + case STS_SETUP_UPDT: + /* Copy the setup packet received in FIFO into the setup buffer in RAM */ + USB_OTG_ReadPacket(pdev , pdev->dev.setup_packet, 8); + ep->xfer_count += status.b.bcnt; + break; + default: + break; + } + + /* Enable the Rx Status Queue Level interrupt */ + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, int_mask.d32); + + return 1; +} + +/** +* @brief DCD_WriteEmptyTxFifo +* check FIFO for the next packet to be loaded +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_WriteEmptyTxFifo(USB_OTG_CORE_HANDLE *pdev, uint32_t epnum) +{ + USB_OTG_DTXFSTSn_TypeDef txstatus; + USB_OTG_EP *ep; + uint32_t len = 0; + uint32_t len32b; + txstatus.d32 = 0; + + ep = &pdev->dev.in_ep[epnum]; + + len = ep->xfer_len - ep->xfer_count; + + if (len > ep->maxpacket) + { + len = ep->maxpacket; + } + + len32b = (len + 3) / 4; + txstatus.d32 = USB_OTG_READ_REG32( &pdev->regs.INEP_REGS[epnum]->DTXFSTS); + + + + while (txstatus.b.txfspcavail > len32b && + ep->xfer_count < ep->xfer_len && + ep->xfer_len != 0) + { + /* Write the FIFO */ + len = ep->xfer_len - ep->xfer_count; + + if (len > ep->maxpacket) + { + len = ep->maxpacket; + } + len32b = (len + 3) / 4; + + USB_OTG_WritePacket (pdev , ep->xfer_buff, epnum, len); + + ep->xfer_buff += len; + ep->xfer_count += len; + + txstatus.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DTXFSTS); + } + + return 1; +} + +/** +* @brief DCD_HandleUsbReset_ISR +* This interrupt occurs when a USB Reset is detected +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleUsbReset_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_DAINT_TypeDef daintmsk; + USB_OTG_DOEPMSK_TypeDef doepmsk; + USB_OTG_DIEPMSK_TypeDef diepmsk; + USB_OTG_DCFG_TypeDef dcfg; + USB_OTG_DCTL_TypeDef dctl; + USB_OTG_GINTSTS_TypeDef gintsts; + uint32_t i; + + dctl.d32 = 0; + daintmsk.d32 = 0; + doepmsk.d32 = 0; + diepmsk.d32 = 0; + dcfg.d32 = 0; + gintsts.d32 = 0; + + /* Clear the Remote Wake-up Signaling */ + dctl.b.rmtwkupsig = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, 0 ); + + /* Flush the Tx FIFO */ + USB_OTG_FlushTxFifo(pdev , 0 ); + + for (i = 0; i < pdev->cfg.dev_endpoints ; i++) + { + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPINT, 0xFF); + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPINT, 0xFF); + } + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINT, 0xFFFFFFFF ); + + daintmsk.ep.in = 1; + daintmsk.ep.out = 1; + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINTMSK, daintmsk.d32 ); + + doepmsk.b.setup = 1; + doepmsk.b.xfercompl = 1; + doepmsk.b.epdisabled = 1; + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DOEPMSK, doepmsk.d32 ); +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DOUTEP1MSK, doepmsk.d32 ); +#endif + diepmsk.b.xfercompl = 1; + diepmsk.b.timeout = 1; + diepmsk.b.epdisabled = 1; + + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DIEPMSK, diepmsk.d32 ); +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DINEP1MSK, diepmsk.d32 ); +#endif + /* Reset Device Address */ + dcfg.d32 = USB_OTG_READ_REG32( &pdev->regs.DREGS->DCFG); + dcfg.b.devaddr = 0; + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DCFG, dcfg.d32); + + + /* setup EP0 to receive SETUP packets */ + USB_OTG_EP0_OutStart(pdev); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.usbreset = 1; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32); + + /*Reset internal state machine */ + USBD_DCD_INT_fops->Reset(pdev); + return 1; +} + +/** +* @brief DCD_HandleEnumDone_ISR +* Read the device status register and set the device speed +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_HandleEnumDone_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + USB_OTG_GUSBCFG_TypeDef gusbcfg; + + USB_OTG_EP0Activate(pdev); + + /* Set USB turn-around time based on device speed and PHY interface. */ + gusbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + + /* Full or High speed */ + if ( USB_OTG_GetDeviceSpeed(pdev) == USB_SPEED_HIGH) + { + pdev->cfg.speed = USB_OTG_SPEED_HIGH; + pdev->cfg.mps = USB_OTG_HS_MAX_PACKET_SIZE ; + gusbcfg.b.usbtrdtim = 9; + } + else + { + pdev->cfg.speed = USB_OTG_SPEED_FULL; + pdev->cfg.mps = USB_OTG_FS_MAX_PACKET_SIZE ; + gusbcfg.b.usbtrdtim = 5; + } + + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GUSBCFG, gusbcfg.d32); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.enumdone = 1; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTSTS, gintsts.d32 ); + return 1; +} + + +/** +* @brief DCD_IsoINIncomplete_ISR +* handle the ISO IN incomplete interrupt +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_IsoINIncomplete_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + + gintsts.d32 = 0; + + USBD_DCD_INT_fops->IsoINIncomplete (pdev); + + /* Clear interrupt */ + gintsts.b.incomplisoin = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32); + + return 1; +} + +/** +* @brief DCD_IsoOUTIncomplete_ISR +* handle the ISO OUT incomplete interrupt +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_IsoOUTIncomplete_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + + gintsts.d32 = 0; + + USBD_DCD_INT_fops->IsoOUTIncomplete (pdev); + + /* Clear interrupt */ + gintsts.b.incomplisoout = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32); + return 1; +} +/** +* @brief DCD_ReadDevInEP +* Reads ep flags +* @param pdev: device instance +* @retval status +*/ +static uint32_t DCD_ReadDevInEP (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum) +{ + uint32_t v, msk, emp; + msk = USB_OTG_READ_REG32(&pdev->regs.DREGS->DIEPMSK); + emp = USB_OTG_READ_REG32(&pdev->regs.DREGS->DIEPEMPMSK); + msk |= ((emp >> epnum) & 0x1) << 7; + v = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[epnum]->DIEPINT) & msk; + return v; +} + + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usb_dcd_int.h b/stm/lib/usb_dcd_int.h new file mode 100644 index 000000000..e2369e5dd --- /dev/null +++ b/stm/lib/usb_dcd_int.h @@ -0,0 +1,127 @@ +/** + ****************************************************************************** + * @file usb_dcd_int.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Peripheral Device Interface Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef USB_DCD_INT_H__ +#define USB_DCD_INT_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_dcd.h" + + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_DCD_INT + * @brief This file is the + * @{ + */ + + +/** @defgroup USB_DCD_INT_Exported_Defines + * @{ + */ + +typedef struct _USBD_DCD_INT +{ + uint8_t (* DataOutStage) (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum); + uint8_t (* DataInStage) (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum); + uint8_t (* SetupStage) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* SOF) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* Reset) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* Suspend) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* Resume) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* IsoINIncomplete) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* IsoOUTIncomplete) (USB_OTG_CORE_HANDLE *pdev); + + uint8_t (* DevConnected) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* DevDisconnected) (USB_OTG_CORE_HANDLE *pdev); + +}USBD_DCD_INT_cb_TypeDef; + +extern USBD_DCD_INT_cb_TypeDef *USBD_DCD_INT_fops; +/** + * @} + */ + + +/** @defgroup USB_DCD_INT_Exported_Types + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_DCD_INT_Exported_Macros + * @{ + */ + +#define CLEAR_IN_EP_INTR(epnum,intr) \ + diepint.d32=0; \ + diepint.b.intr = 1; \ + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[epnum]->DIEPINT,diepint.d32); + +#define CLEAR_OUT_EP_INTR(epnum,intr) \ + doepint.d32=0; \ + doepint.b.intr = 1; \ + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[epnum]->DOEPINT,doepint.d32); + +/** + * @} + */ + +/** @defgroup USB_DCD_INT_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_DCD_INT_Exported_FunctionsPrototype + * @{ + */ + +uint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev); + +/** + * @} + */ + + +#endif // USB_DCD_INT_H__ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_defines.h b/stm/lib/usb_defines.h new file mode 100644 index 000000000..28e6d1687 --- /dev/null +++ b/stm/lib/usb_defines.h @@ -0,0 +1,249 @@ +/** + ****************************************************************************** + * @file usb_defines.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Header of the Core Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_DEF_H__ +#define __USB_DEF_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_DEFINES + * @brief This file is the + * @{ + */ + + +/** @defgroup USB_DEFINES_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup _CORE_DEFINES_ + * @{ + */ + +#define USB_OTG_SPEED_PARAM_HIGH 0 +#define USB_OTG_SPEED_PARAM_HIGH_IN_FULL 1 +#define USB_OTG_SPEED_PARAM_FULL 3 + +#define USB_OTG_SPEED_HIGH 0 +#define USB_OTG_SPEED_FULL 1 + +#define USB_OTG_ULPI_PHY 1 +#define USB_OTG_EMBEDDED_PHY 2 + +/** + * @} + */ + + +/** @defgroup _GLOBAL_DEFINES_ + * @{ + */ +#define GAHBCFG_TXFEMPTYLVL_EMPTY 1 +#define GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 +#define GAHBCFG_GLBINT_ENABLE 1 +#define GAHBCFG_INT_DMA_BURST_SINGLE 0 +#define GAHBCFG_INT_DMA_BURST_INCR 1 +#define GAHBCFG_INT_DMA_BURST_INCR4 3 +#define GAHBCFG_INT_DMA_BURST_INCR8 5 +#define GAHBCFG_INT_DMA_BURST_INCR16 7 +#define GAHBCFG_DMAENABLE 1 +#define GAHBCFG_TXFEMPTYLVL_EMPTY 1 +#define GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 +#define GRXSTS_PKTSTS_IN 2 +#define GRXSTS_PKTSTS_IN_XFER_COMP 3 +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5 +#define GRXSTS_PKTSTS_CH_HALTED 7 +/** + * @} + */ + + +/** @defgroup _OnTheGo_DEFINES_ + * @{ + */ +#define MODE_HNP_SRP_CAPABLE 0 +#define MODE_SRP_ONLY_CAPABLE 1 +#define MODE_NO_HNP_SRP_CAPABLE 2 +#define MODE_SRP_CAPABLE_DEVICE 3 +#define MODE_NO_SRP_CAPABLE_DEVICE 4 +#define MODE_SRP_CAPABLE_HOST 5 +#define MODE_NO_SRP_CAPABLE_HOST 6 +#define A_HOST 1 +#define A_SUSPEND 2 +#define A_PERIPHERAL 3 +#define B_PERIPHERAL 4 +#define B_HOST 5 +#define DEVICE_MODE 0 +#define HOST_MODE 1 +#define OTG_MODE 2 +/** + * @} + */ + + +/** @defgroup __DEVICE_DEFINES_ + * @{ + */ +#define DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 +#define DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 +#define DSTS_ENUMSPD_LS_PHY_6MHZ 2 +#define DSTS_ENUMSPD_FS_PHY_48MHZ 3 + +#define DCFG_FRAME_INTERVAL_80 0 +#define DCFG_FRAME_INTERVAL_85 1 +#define DCFG_FRAME_INTERVAL_90 2 +#define DCFG_FRAME_INTERVAL_95 3 + +#define DEP0CTL_MPS_64 0 +#define DEP0CTL_MPS_32 1 +#define DEP0CTL_MPS_16 2 +#define DEP0CTL_MPS_8 3 + +#define EP_SPEED_LOW 0 +#define EP_SPEED_FULL 1 +#define EP_SPEED_HIGH 2 + +#define EP_TYPE_CTRL 0 +#define EP_TYPE_ISOC 1 +#define EP_TYPE_BULK 2 +#define EP_TYPE_INTR 3 +#define EP_TYPE_MSK 3 + +#define STS_GOUT_NAK 1 +#define STS_DATA_UPDT 2 +#define STS_XFER_COMP 3 +#define STS_SETUP_COMP 4 +#define STS_SETUP_UPDT 6 +/** + * @} + */ + + +/** @defgroup __HOST_DEFINES_ + * @{ + */ +#define HC_PID_DATA0 0 +#define HC_PID_DATA2 1 +#define HC_PID_DATA1 2 +#define HC_PID_SETUP 3 + +#define HPRT0_PRTSPD_HIGH_SPEED 0 +#define HPRT0_PRTSPD_FULL_SPEED 1 +#define HPRT0_PRTSPD_LOW_SPEED 2 + +#define HCFG_30_60_MHZ 0 +#define HCFG_48_MHZ 1 +#define HCFG_6_MHZ 2 + +#define HCCHAR_CTRL 0 +#define HCCHAR_ISOC 1 +#define HCCHAR_BULK 2 +#define HCCHAR_INTR 3 + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +/** + * @} + */ + + +/** @defgroup USB_DEFINES_Exported_Types + * @{ + */ + +typedef enum +{ + USB_OTG_HS_CORE_ID = 0, + USB_OTG_FS_CORE_ID = 1 +}USB_OTG_CORE_ID_TypeDef; +/** + * @} + */ + + +/** @defgroup USB_DEFINES_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_DEFINES_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_DEFINES_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +/** @defgroup Internal_Macro's + * @{ + */ +#define USB_OTG_READ_REG32(reg) (*(__IO uint32_t *)reg) +#define USB_OTG_WRITE_REG32(reg,value) (*(__IO uint32_t *)reg = value) +#define USB_OTG_MODIFY_REG32(reg,clear_mask,set_mask) \ + USB_OTG_WRITE_REG32(reg, (((USB_OTG_READ_REG32(reg)) & ~clear_mask) | set_mask ) ) + +/******************************************************************************** + ENUMERATION TYPE +********************************************************************************/ +enum USB_OTG_SPEED { + USB_SPEED_UNKNOWN = 0, + USB_SPEED_LOW, + USB_SPEED_FULL, + USB_SPEED_HIGH +}; + +#endif //__USB_DEFINES__H__ + + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_hcd.c b/stm/lib/usb_hcd.c new file mode 100644 index 000000000..56e224418 --- /dev/null +++ b/stm/lib/usb_hcd.c @@ -0,0 +1,262 @@ +/** + ****************************************************************************** + * @file usb_hcd.c + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Host Interface Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_core.h" +#include "usb_hcd.h" +#include "usb_conf.h" +#include "usb_bsp.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_HCD + * @brief This file is the interface between EFSL ans Host mass-storage class + * @{ + */ + + +/** @defgroup USB_HCD_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_HCD_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USB_HCD_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_HCD_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_HCD_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_HCD_Private_Functions + * @{ + */ + +/** + * @brief HCD_Init + * Initialize the HOST portion of the driver. + * @param pdev: Selected device + * @param base_address: OTG base address + * @retval Status + */ +uint32_t HCD_Init(USB_OTG_CORE_HANDLE *pdev , + USB_OTG_CORE_ID_TypeDef coreID) +{ + uint8_t i = 0; + pdev->host.ConnSts = 0; + + for (i= 0; i< USB_OTG_MAX_TX_FIFOS; i++) + { + pdev->host.ErrCnt[i] = 0; + pdev->host.XferCnt[i] = 0; + pdev->host.HC_Status[i] = HC_IDLE; + } + pdev->host.hc[0].max_packet = 8; + + USB_OTG_SelectCore(pdev, coreID); +#ifndef DUAL_ROLE_MODE_ENABLED + USB_OTG_DisableGlobalInt(pdev); + USB_OTG_CoreInit(pdev); + + /* Force Host Mode*/ + USB_OTG_SetCurrentMode(pdev , HOST_MODE); + USB_OTG_CoreInitHost(pdev); + USB_OTG_EnableGlobalInt(pdev); +#endif + + return 0; +} + + +/** + * @brief HCD_GetCurrentSpeed + * Get Current device Speed. + * @param pdev : Selected device + * @retval Status + */ + +uint32_t HCD_GetCurrentSpeed (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HPRT0_TypeDef HPRT0; + HPRT0.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); + + return HPRT0.b.prtspd; +} + +/** + * @brief HCD_ResetPort + * Issues the reset command to device + * @param pdev : Selected device + * @retval Status + */ +uint32_t HCD_ResetPort(USB_OTG_CORE_HANDLE *pdev) +{ + /* + Before starting to drive a USB reset, the application waits for the OTG + interrupt triggered by the debounce done bit (DBCDNE bit in OTG_FS_GOTGINT), + which indicates that the bus is stable again after the electrical debounce + caused by the attachment of a pull-up resistor on DP (FS) or DM (LS). + */ + + USB_OTG_ResetPort(pdev); + return 0; +} + +/** + * @brief HCD_IsDeviceConnected + * Check if the device is connected. + * @param pdev : Selected device + * @retval Device connection status. 1 -> connected and 0 -> disconnected + * + */ +uint32_t HCD_IsDeviceConnected(USB_OTG_CORE_HANDLE *pdev) +{ + return (pdev->host.ConnSts); +} + +/** + * @brief HCD_GetCurrentFrame + * This function returns the frame number for sof packet + * @param pdev : Selected device + * @retval Frame number + * + */ +uint32_t HCD_GetCurrentFrame (USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_READ_REG32(&pdev->regs.HREGS->HFNUM) & 0xFFFF) ; +} + +/** + * @brief HCD_GetURB_State + * This function returns the last URBstate + * @param pdev: Selected device + * @retval URB_STATE + * + */ +URB_STATE HCD_GetURB_State (USB_OTG_CORE_HANDLE *pdev , uint8_t ch_num) +{ + return pdev->host.URB_State[ch_num] ; +} + +/** + * @brief HCD_GetXferCnt + * This function returns the last URBstate + * @param pdev: Selected device + * @retval No. of data bytes transferred + * + */ +uint32_t HCD_GetXferCnt (USB_OTG_CORE_HANDLE *pdev, uint8_t ch_num) +{ + return pdev->host.XferCnt[ch_num] ; +} + + + +/** + * @brief HCD_GetHCState + * This function returns the HC Status + * @param pdev: Selected device + * @retval HC_STATUS + * + */ +HC_STATUS HCD_GetHCState (USB_OTG_CORE_HANDLE *pdev , uint8_t ch_num) +{ + return pdev->host.HC_Status[ch_num] ; +} + +/** + * @brief HCD_HC_Init + * This function prepare a HC and start a transfer + * @param pdev: Selected device + * @param hc_num: Channel number + * @retval status + */ +uint32_t HCD_HC_Init (USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + return USB_OTG_HC_Init(pdev, hc_num); +} + +/** + * @brief HCD_SubmitRequest + * This function prepare a HC and start a transfer + * @param pdev: Selected device + * @param hc_num: Channel number + * @retval status + */ +uint32_t HCD_SubmitRequest (USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + + pdev->host.URB_State[hc_num] = URB_IDLE; + pdev->host.hc[hc_num].xfer_count = 0 ; + return USB_OTG_HC_StartXfer(pdev, hc_num); +} + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usb_hcd.h b/stm/lib/usb_hcd.h new file mode 100644 index 000000000..ca2ba3c37 --- /dev/null +++ b/stm/lib/usb_hcd.h @@ -0,0 +1,108 @@ +/** + ****************************************************************************** + * @file usb_hcd.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Host layer Header file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_HCD_H__ +#define __USB_HCD_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_regs.h" +#include "usb_core.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_HCD + * @brief This file is the + * @{ + */ + + +/** @defgroup USB_HCD_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_HCD_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_HCD_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_HCD_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_HCD_Exported_FunctionsPrototype + * @{ + */ +uint32_t HCD_Init (USB_OTG_CORE_HANDLE *pdev , + USB_OTG_CORE_ID_TypeDef coreID); +uint32_t HCD_HC_Init (USB_OTG_CORE_HANDLE *pdev , + uint8_t hc_num); +uint32_t HCD_SubmitRequest (USB_OTG_CORE_HANDLE *pdev , + uint8_t hc_num) ; +uint32_t HCD_GetCurrentSpeed (USB_OTG_CORE_HANDLE *pdev); +uint32_t HCD_ResetPort (USB_OTG_CORE_HANDLE *pdev); +uint32_t HCD_IsDeviceConnected (USB_OTG_CORE_HANDLE *pdev); +uint32_t HCD_GetCurrentFrame (USB_OTG_CORE_HANDLE *pdev) ; +URB_STATE HCD_GetURB_State (USB_OTG_CORE_HANDLE *pdev, uint8_t ch_num); +uint32_t HCD_GetXferCnt (USB_OTG_CORE_HANDLE *pdev, uint8_t ch_num); +HC_STATUS HCD_GetHCState (USB_OTG_CORE_HANDLE *pdev, uint8_t ch_num) ; +/** + * @} + */ + +#endif //__USB_HCD_H__ + + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_hcd_int.c b/stm/lib/usb_hcd_int.c new file mode 100644 index 000000000..4fdbe2fac --- /dev/null +++ b/stm/lib/usb_hcd_int.c @@ -0,0 +1,858 @@ +/** + ****************************************************************************** + * @file usb_hcd_int.c + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Host driver interrupt subroutines + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_core.h" +#include "usb_defines.h" +#include "usb_hcd_int.h" + +#if defined (__CC_ARM) /*!< ARM Compiler */ +#pragma O0 +#elif defined (__GNUC__) /*!< GNU Compiler */ +#pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING Compiler */ +#pragma optimize=0 + +#endif /* __CC_ARM */ + +/** @addtogroup USB_OTG_DRIVER +* @{ +*/ + +/** @defgroup USB_HCD_INT +* @brief This file contains the interrupt subroutines for the Host mode. +* @{ +*/ + + +/** @defgroup USB_HCD_INT_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_HCD_INT_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USB_HCD_INT_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_HCD_INT_Private_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_HCD_INT_Private_FunctionPrototypes +* @{ +*/ + +static uint32_t USB_OTG_USBH_handle_sof_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_USBH_handle_port_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_USBH_handle_hc_ISR (USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_USBH_handle_hc_n_In_ISR (USB_OTG_CORE_HANDLE *pdev , + uint32_t num); +static uint32_t USB_OTG_USBH_handle_hc_n_Out_ISR (USB_OTG_CORE_HANDLE *pdev , + uint32_t num); +static uint32_t USB_OTG_USBH_handle_rx_qlvl_ISR (USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_USBH_handle_nptxfempty_ISR (USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_USBH_handle_ptxfempty_ISR (USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_USBH_handle_Disconnect_ISR (USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_USBH_handle_IncompletePeriodicXfer_ISR (USB_OTG_CORE_HANDLE *pdev); + +/** +* @} +*/ + + +/** @defgroup USB_HCD_INT_Private_Functions +* @{ +*/ + +/** +* @brief HOST_Handle_ISR +* This function handles all USB Host Interrupts +* @param pdev: Selected device +* @retval status +*/ + +uint32_t USBH_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + uint32_t retval = 0; + + gintsts.d32 = 0; + + /* Check if HOST Mode */ + if (USB_OTG_IsHostMode(pdev)) + { + gintsts.d32 = USB_OTG_ReadCoreItr(pdev); + if (!gintsts.d32) + { + return 0; + } + + if (gintsts.b.sofintr) + { + retval |= USB_OTG_USBH_handle_sof_ISR (pdev); + } + + if (gintsts.b.rxstsqlvl) + { + retval |= USB_OTG_USBH_handle_rx_qlvl_ISR (pdev); + } + + if (gintsts.b.nptxfempty) + { + retval |= USB_OTG_USBH_handle_nptxfempty_ISR (pdev); + } + + if (gintsts.b.ptxfempty) + { + retval |= USB_OTG_USBH_handle_ptxfempty_ISR (pdev); + } + + if (gintsts.b.hcintr) + { + retval |= USB_OTG_USBH_handle_hc_ISR (pdev); + } + + if (gintsts.b.portintr) + { + retval |= USB_OTG_USBH_handle_port_ISR (pdev); + } + + if (gintsts.b.disconnect) + { + retval |= USB_OTG_USBH_handle_Disconnect_ISR (pdev); + + } + + if (gintsts.b.incomplisoout) + { + retval |= USB_OTG_USBH_handle_IncompletePeriodicXfer_ISR (pdev); + } + + + } + return retval; +} + +/** +* @brief USB_OTG_USBH_handle_hc_ISR +* This function indicates that one or more host channels has a pending +* @param pdev: Selected device +* @retval status +*/ +static uint32_t USB_OTG_USBH_handle_hc_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HAINT_TypeDef haint; + USB_OTG_HCCHAR_TypeDef hcchar; + uint32_t i = 0; + uint32_t retval = 0; + + /* Clear appropriate bits in HCINTn to clear the interrupt bit in + * GINTSTS */ + + haint.d32 = USB_OTG_ReadHostAllChannels_intr(pdev); + + for (i = 0; i < pdev->cfg.host_channels ; i++) + { + if (haint.b.chint & (1 << i)) + { + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[i]->HCCHAR); + + if (hcchar.b.epdir) + { + retval |= USB_OTG_USBH_handle_hc_n_In_ISR (pdev, i); + } + else + { + retval |= USB_OTG_USBH_handle_hc_n_Out_ISR (pdev, i); + } + } + } + + return retval; +} + +/** +* @brief USB_OTG_otg_hcd_handle_sof_intr +* Handles the start-of-frame interrupt in host mode. +* @param pdev: Selected device +* @retval status +*/ +static uint32_t USB_OTG_USBH_handle_sof_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + gintsts.d32 = 0; + + USBH_HCD_INT_fops->SOF(pdev); + + /* Clear interrupt */ + gintsts.b.sofintr = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32); + + return 1; +} + +/** +* @brief USB_OTG_USBH_handle_Disconnect_ISR +* Handles disconnect event. +* @param pdev: Selected device +* @retval status +*/ +static uint32_t USB_OTG_USBH_handle_Disconnect_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + + gintsts.d32 = 0; + + USBH_HCD_INT_fops->DevDisconnected(pdev); + + /* Clear interrupt */ + gintsts.b.disconnect = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32); + + return 1; +} +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma optimize = none +#endif /* __CC_ARM */ +/** +* @brief USB_OTG_USBH_handle_nptxfempty_ISR +* Handles non periodic tx fifo empty. +* @param pdev: Selected device +* @retval status +*/ +static uint32_t USB_OTG_USBH_handle_nptxfempty_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTMSK_TypeDef intmsk; + USB_OTG_HNPTXSTS_TypeDef hnptxsts; + uint16_t len_words , len; + + hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS); + + len_words = (pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_len + 3) / 4; + + while ((hnptxsts.b.nptxfspcavail > len_words)&& + (pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_len != 0)) + { + + len = hnptxsts.b.nptxfspcavail * 4; + + if (len > pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_len) + { + /* Last packet */ + len = pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_len; + + intmsk.d32 = 0; + intmsk.b.nptxfempty = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, intmsk.d32, 0); + } + + len_words = (pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_len + 3) / 4; + + USB_OTG_WritePacket (pdev , pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_buff, hnptxsts.b.nptxqtop.chnum, len); + + pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_buff += len; + pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_len -= len; + pdev->host.hc[hnptxsts.b.nptxqtop.chnum].xfer_count += len; + + hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS); + } + + return 1; +} +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma optimize = none +#endif /* __CC_ARM */ +/** +* @brief USB_OTG_USBH_handle_ptxfempty_ISR +* Handles periodic tx fifo empty +* @param pdev: Selected device +* @retval status +*/ +static uint32_t USB_OTG_USBH_handle_ptxfempty_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTMSK_TypeDef intmsk; + USB_OTG_HPTXSTS_TypeDef hptxsts; + uint16_t len_words , len; + + hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS); + + len_words = (pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_len + 3) / 4; + + while ((hptxsts.b.ptxfspcavail > len_words)&& + (pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_len != 0)) + { + + len = hptxsts.b.ptxfspcavail * 4; + + if (len > pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_len) + { + len = pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_len; + /* Last packet */ + intmsk.d32 = 0; + intmsk.b.ptxfempty = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, intmsk.d32, 0); + } + + len_words = (pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_len + 3) / 4; + + USB_OTG_WritePacket (pdev , pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_buff, hptxsts.b.ptxqtop.chnum, len); + + pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_buff += len; + pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_len -= len; + pdev->host.hc[hptxsts.b.ptxqtop.chnum].xfer_count += len; + + hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS); + } + + return 1; +} + +/** +* @brief USB_OTG_USBH_handle_port_ISR +* This function determines which interrupt conditions have occurred +* @param pdev: Selected device +* @retval status +*/ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma optimize = none +#endif /* __CC_ARM */ +static uint32_t USB_OTG_USBH_handle_port_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HPRT0_TypeDef hprt0; + USB_OTG_HPRT0_TypeDef hprt0_dup; + USB_OTG_HCFG_TypeDef hcfg; + uint32_t do_reset = 0; + uint32_t retval = 0; + + hcfg.d32 = 0; + hprt0.d32 = 0; + hprt0_dup.d32 = 0; + + hprt0.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); + hprt0_dup.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); + + /* Clear the interrupt bits in GINTSTS */ + + hprt0_dup.b.prtena = 0; + hprt0_dup.b.prtconndet = 0; + hprt0_dup.b.prtenchng = 0; + hprt0_dup.b.prtovrcurrchng = 0; + + /* Port Connect Detected */ + if (hprt0.b.prtconndet) + { + + hprt0_dup.b.prtconndet = 1; + USBH_HCD_INT_fops->DevConnected(pdev); + retval |= 1; + } + + /* Port Enable Changed */ + if (hprt0.b.prtenchng) + { + hprt0_dup.b.prtenchng = 1; + + if (hprt0.b.prtena == 1) + { + + USBH_HCD_INT_fops->DevConnected(pdev); + + if ((hprt0.b.prtspd == HPRT0_PRTSPD_LOW_SPEED) || + (hprt0.b.prtspd == HPRT0_PRTSPD_FULL_SPEED)) + { + + hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); + + if (hprt0.b.prtspd == HPRT0_PRTSPD_LOW_SPEED) + { + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFIR, 6000 ); + if (hcfg.b.fslspclksel != HCFG_6_MHZ) + { + if(pdev->cfg.phy_itface == USB_OTG_EMBEDDED_PHY) + { + USB_OTG_InitFSLSPClkSel(pdev ,HCFG_6_MHZ ); + } + do_reset = 1; + } + } + else + { + + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFIR, 48000 ); + if (hcfg.b.fslspclksel != HCFG_48_MHZ) + { + USB_OTG_InitFSLSPClkSel(pdev ,HCFG_48_MHZ ); + do_reset = 1; + } + } + } + else + { + do_reset = 1; + } + } + } + /* Overcurrent Change Interrupt */ + if (hprt0.b.prtovrcurrchng) + { + hprt0_dup.b.prtovrcurrchng = 1; + retval |= 1; + } + if (do_reset) + { + USB_OTG_ResetPort(pdev); + } + /* Clear Port Interrupts */ + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0_dup.d32); + + return retval; +} +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma optimize = none +#endif /* __CC_ARM */ +/** +* @brief USB_OTG_USBH_handle_hc_n_Out_ISR +* Handles interrupt for a specific Host Channel +* @param pdev: Selected device +* @param hc_num: Channel number +* @retval status +*/ +uint32_t USB_OTG_USBH_handle_hc_n_Out_ISR (USB_OTG_CORE_HANDLE *pdev , uint32_t num) +{ + + USB_OTG_HCINTn_TypeDef hcint; + USB_OTG_HCINTMSK_TypeDef hcintmsk; + USB_OTG_HC_REGS *hcreg; + USB_OTG_HCCHAR_TypeDef hcchar; + + hcreg = pdev->regs.HC_REGS[num]; + hcint.d32 = USB_OTG_READ_REG32(&hcreg->HCINT); + hcintmsk.d32 = USB_OTG_READ_REG32(&hcreg->HCINTMSK); + hcint.d32 = hcint.d32 & hcintmsk.d32; + + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[num]->HCCHAR); + + if (hcint.b.ahberr) + { + CLEAR_HC_INT(hcreg ,ahberr); + UNMASK_HOST_INT_CHH (num); + } + else if (hcint.b.ack) + { + CLEAR_HC_INT(hcreg , ack); + } + else if (hcint.b.frmovrun) + { + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg ,frmovrun); + } + else if (hcint.b.xfercompl) + { + pdev->host.ErrCnt[num] = 0; + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg , xfercompl); + pdev->host.HC_Status[num] = HC_XFRC; + } + + else if (hcint.b.stall) + { + CLEAR_HC_INT(hcreg , stall); + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + pdev->host.HC_Status[num] = HC_STALL; + } + + else if (hcint.b.nak) + { + pdev->host.ErrCnt[num] = 0; + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg , nak); + pdev->host.HC_Status[num] = HC_NAK; + } + + else if (hcint.b.xacterr) + { + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + pdev->host.ErrCnt[num] ++; + pdev->host.HC_Status[num] = HC_XACTERR; + CLEAR_HC_INT(hcreg , xacterr); + } + else if (hcint.b.nyet) + { + pdev->host.ErrCnt[num] = 0; + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg , nyet); + pdev->host.HC_Status[num] = HC_NYET; + } + else if (hcint.b.datatglerr) + { + + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg , nak); + pdev->host.HC_Status[num] = HC_DATATGLERR; + + CLEAR_HC_INT(hcreg , datatglerr); + } + else if (hcint.b.chhltd) + { + MASK_HOST_INT_CHH (num); + + if(pdev->host.HC_Status[num] == HC_XFRC) + { + pdev->host.URB_State[num] = URB_DONE; + + if (hcchar.b.eptype == EP_TYPE_BULK) + { + pdev->host.hc[num].toggle_out ^= 1; + } + } + else if(pdev->host.HC_Status[num] == HC_NAK) + { + pdev->host.URB_State[num] = URB_NOTREADY; + } + else if(pdev->host.HC_Status[num] == HC_NYET) + { + if(pdev->host.hc[num].do_ping == 1) + { + USB_OTG_HC_DoPing(pdev, num); + } + pdev->host.URB_State[num] = URB_NOTREADY; + } + else if(pdev->host.HC_Status[num] == HC_STALL) + { + pdev->host.URB_State[num] = URB_STALL; + } + else if(pdev->host.HC_Status[num] == HC_XACTERR) + { + if (pdev->host.ErrCnt[num] == 3) + { + pdev->host.URB_State[num] = URB_ERROR; + pdev->host.ErrCnt[num] = 0; + } + } + CLEAR_HC_INT(hcreg , chhltd); + } + + + return 1; +} +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma optimize = none +#endif /* __CC_ARM */ +/** +* @brief USB_OTG_USBH_handle_hc_n_In_ISR +* Handles interrupt for a specific Host Channel +* @param pdev: Selected device +* @param hc_num: Channel number +* @retval status +*/ +uint32_t USB_OTG_USBH_handle_hc_n_In_ISR (USB_OTG_CORE_HANDLE *pdev , uint32_t num) +{ + USB_OTG_HCINTn_TypeDef hcint; + USB_OTG_HCINTMSK_TypeDef hcintmsk; + USB_OTG_HCCHAR_TypeDef hcchar; + USB_OTG_HCTSIZn_TypeDef hctsiz; + USB_OTG_HC_REGS *hcreg; + + + hcreg = pdev->regs.HC_REGS[num]; + hcint.d32 = USB_OTG_READ_REG32(&hcreg->HCINT); + hcintmsk.d32 = USB_OTG_READ_REG32(&hcreg->HCINTMSK); + hcint.d32 = hcint.d32 & hcintmsk.d32; + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[num]->HCCHAR); + hcintmsk.d32 = 0; + + + if (hcint.b.ahberr) + { + CLEAR_HC_INT(hcreg ,ahberr); + UNMASK_HOST_INT_CHH (num); + } + else if (hcint.b.ack) + { + CLEAR_HC_INT(hcreg ,ack); + } + + else if (hcint.b.stall) + { + UNMASK_HOST_INT_CHH (num); + pdev->host.HC_Status[num] = HC_STALL; + CLEAR_HC_INT(hcreg , nak); /* Clear the NAK Condition */ + CLEAR_HC_INT(hcreg , stall); /* Clear the STALL Condition */ + hcint.b.nak = 0; /* NOTE: When there is a 'stall', reset also nak, + else, the pdev->host.HC_Status = HC_STALL + will be overwritten by 'nak' in code below */ + USB_OTG_HC_Halt(pdev, num); + } + else if (hcint.b.datatglerr) + { + + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg , nak); + pdev->host.HC_Status[num] = HC_DATATGLERR; + CLEAR_HC_INT(hcreg , datatglerr); + } + + if (hcint.b.frmovrun) + { + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg ,frmovrun); + } + + else if (hcint.b.xfercompl) + { + + if (pdev->cfg.dma_enable == 1) + { + hctsiz.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[num]->HCTSIZ); + pdev->host.XferCnt[num] = pdev->host.hc[num].xfer_len - hctsiz.b.xfersize; + } + + pdev->host.HC_Status[num] = HC_XFRC; + pdev->host.ErrCnt [num]= 0; + CLEAR_HC_INT(hcreg , xfercompl); + + if ((hcchar.b.eptype == EP_TYPE_CTRL)|| + (hcchar.b.eptype == EP_TYPE_BULK)) + { + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg , nak); + pdev->host.hc[num].toggle_in ^= 1; + + } + else if(hcchar.b.eptype == EP_TYPE_INTR) + { + hcchar.b.oddfrm = 1; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[num]->HCCHAR, hcchar.d32); + pdev->host.URB_State[num] = URB_DONE; + } + + } + else if (hcint.b.chhltd) + { + MASK_HOST_INT_CHH (num); + + if(pdev->host.HC_Status[num] == HC_XFRC) + { + pdev->host.URB_State[num] = URB_DONE; + } + + else if (pdev->host.HC_Status[num] == HC_STALL) + { + pdev->host.URB_State[num] = URB_STALL; + } + + else if((pdev->host.HC_Status[num] == HC_XACTERR) || + (pdev->host.HC_Status[num] == HC_DATATGLERR)) + { + pdev->host.ErrCnt[num] = 0; + pdev->host.URB_State[num] = URB_ERROR; + + } + else if(hcchar.b.eptype == EP_TYPE_INTR) + { + pdev->host.hc[num].toggle_in ^= 1; + } + + CLEAR_HC_INT(hcreg , chhltd); + + } + else if (hcint.b.xacterr) + { + UNMASK_HOST_INT_CHH (num); + pdev->host.ErrCnt[num] ++; + pdev->host.HC_Status[num] = HC_XACTERR; + USB_OTG_HC_Halt(pdev, num); + CLEAR_HC_INT(hcreg , xacterr); + + } + else if (hcint.b.nak) + { + if(hcchar.b.eptype == EP_TYPE_INTR) + { + UNMASK_HOST_INT_CHH (num); + USB_OTG_HC_Halt(pdev, num); + } + else if ((hcchar.b.eptype == EP_TYPE_CTRL)|| + (hcchar.b.eptype == EP_TYPE_BULK)) + { + /* re-activate the channel */ + hcchar.b.chen = 1; + hcchar.b.chdis = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[num]->HCCHAR, hcchar.d32); + } + pdev->host.HC_Status[num] = HC_NAK; + CLEAR_HC_INT(hcreg , nak); + } + + + return 1; + +} + +/** +* @brief USB_OTG_USBH_handle_rx_qlvl_ISR +* Handles the Rx Status Queue Level Interrupt +* @param pdev: Selected device +* @retval status +*/ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma optimize = none +#endif /* __CC_ARM */ +static uint32_t USB_OTG_USBH_handle_rx_qlvl_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GRXFSTS_TypeDef grxsts; + USB_OTG_GINTMSK_TypeDef intmsk; + USB_OTG_HCTSIZn_TypeDef hctsiz; + USB_OTG_HCCHAR_TypeDef hcchar; + __IO uint8_t channelnum =0; + uint32_t count; + + /* Disable the Rx Status Queue Level interrupt */ + intmsk.d32 = 0; + intmsk.b.rxstsqlvl = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, intmsk.d32, 0); + + grxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GRXSTSP); + channelnum = grxsts.b.chnum; + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[channelnum]->HCCHAR); + + switch (grxsts.b.pktsts) + { + case GRXSTS_PKTSTS_IN: + /* Read the data into the host buffer. */ + if ((grxsts.b.bcnt > 0) && (pdev->host.hc[channelnum].xfer_buff != (void *)0)) + { + + USB_OTG_ReadPacket(pdev, pdev->host.hc[channelnum].xfer_buff, grxsts.b.bcnt); + /*manage multiple Xfer */ + pdev->host.hc[grxsts.b.chnum].xfer_buff += grxsts.b.bcnt; + pdev->host.hc[grxsts.b.chnum].xfer_count += grxsts.b.bcnt; + + + count = pdev->host.hc[channelnum].xfer_count; + pdev->host.XferCnt[channelnum] = count; + + hctsiz.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[channelnum]->HCTSIZ); + if(hctsiz.b.pktcnt > 0) + { + /* re-activate the channel when more packets are expected */ + hcchar.b.chen = 1; + hcchar.b.chdis = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[channelnum]->HCCHAR, hcchar.d32); + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + case GRXSTS_PKTSTS_CH_HALTED: + default: + break; + } + + /* Enable the Rx Status Queue Level interrupt */ + intmsk.b.rxstsqlvl = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, 0, intmsk.d32); + return 1; +} + +/** +* @brief USB_OTG_USBH_handle_IncompletePeriodicXfer_ISR +* Handles the incomplete Periodic transfer Interrupt +* @param pdev: Selected device +* @retval status +*/ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ +#pragma optimize = none +#endif /* __CC_ARM */ +static uint32_t USB_OTG_USBH_handle_IncompletePeriodicXfer_ISR (USB_OTG_CORE_HANDLE *pdev) +{ + + USB_OTG_GINTSTS_TypeDef gintsts; + USB_OTG_HCCHAR_TypeDef hcchar; + + + + + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[0]->HCCHAR); + hcchar.b.chen = 1; + hcchar.b.chdis = 1; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[0]->HCCHAR, hcchar.d32); + + gintsts.d32 = 0; + /* Clear interrupt */ + gintsts.b.incomplisoout = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, gintsts.d32); + + return 1; +} + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_hcd_int.h b/stm/lib/usb_hcd_int.h new file mode 100644 index 000000000..5bc5b8a88 --- /dev/null +++ b/stm/lib/usb_hcd_int.h @@ -0,0 +1,141 @@ +/** + ****************************************************************************** + * @file usb_hcd_int.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief Peripheral Device Interface Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __HCD_INT_H__ +#define __HCD_INT_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_hcd.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_HCD_INT + * @brief This file is the + * @{ + */ + + +/** @defgroup USB_HCD_INT_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_HCD_INT_Exported_Types + * @{ + */ + +typedef struct _USBH_HCD_INT +{ + uint8_t (* SOF) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* DevConnected) (USB_OTG_CORE_HANDLE *pdev); + uint8_t (* DevDisconnected) (USB_OTG_CORE_HANDLE *pdev); + +}USBH_HCD_INT_cb_TypeDef; + +extern USBH_HCD_INT_cb_TypeDef *USBH_HCD_INT_fops; +/** + * @} + */ + + +/** @defgroup USB_HCD_INT_Exported_Macros + * @{ + */ + +#define CLEAR_HC_INT(HC_REGS, intr) \ + {\ + USB_OTG_HCINTn_TypeDef hcint_clear; \ + hcint_clear.d32 = 0; \ + hcint_clear.b.intr = 1; \ + USB_OTG_WRITE_REG32(&((HC_REGS)->HCINT), hcint_clear.d32);\ + }\ + +#define MASK_HOST_INT_CHH(hc_num) { USB_OTG_HCINTMSK_TypeDef INTMSK; \ + INTMSK.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK); \ + INTMSK.b.chhltd = 0; \ + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK, INTMSK.d32);} + +#define UNMASK_HOST_INT_CHH(hc_num) { USB_OTG_HCINTMSK_TypeDef INTMSK; \ + INTMSK.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK); \ + INTMSK.b.chhltd = 1; \ + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK, INTMSK.d32);} + +#define MASK_HOST_INT_ACK(hc_num) { USB_OTG_HCINTMSK_TypeDef INTMSK; \ + INTMSK.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK); \ + INTMSK.b.ack = 0; \ + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK, GINTMSK.d32);} + +#define UNMASK_HOST_INT_ACK(hc_num) { USB_OTG_HCGINTMSK_TypeDef INTMSK; \ + INTMSK.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK); \ + INTMSK.b.ack = 1; \ + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCINTMSK, INTMSK.d32);} + +/** + * @} + */ + +/** @defgroup USB_HCD_INT_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_HCD_INT_Exported_FunctionsPrototype + * @{ + */ +/* Callbacks handler */ +void ConnectCallback_Handler(USB_OTG_CORE_HANDLE *pdev); +void Disconnect_Callback_Handler(USB_OTG_CORE_HANDLE *pdev); +void Overcurrent_Callback_Handler(USB_OTG_CORE_HANDLE *pdev); +uint32_t USBH_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev); + +/** + * @} + */ + + + +#endif //__HCD_INT_H__ + + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_otg.c b/stm/lib/usb_otg.c new file mode 100644 index 000000000..17c5eb685 --- /dev/null +++ b/stm/lib/usb_otg.c @@ -0,0 +1,418 @@ +/** + ****************************************************************************** + * @file usb_otg.c + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief OTG Core Layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_defines.h" +#include "usb_regs.h" +#include "usb_core.h" +#include "usb_otg.h" + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_OTG + * @brief This file is the interface between EFSL ans Host mass-storage class + * @{ + */ + + +/** @defgroup USB_OTG_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_OTG_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USB_OTG_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_OTG_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_OTG_Private_FunctionPrototypes + * @{ + */ + +uint32_t USB_OTG_HandleOTG_ISR(USB_OTG_CORE_HANDLE *pdev); + +static uint32_t USB_OTG_HandleConnectorIDStatusChange_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_HandleSessionRequest_ISR(USB_OTG_CORE_HANDLE *pdev); +static uint32_t USB_OTG_Read_itr(USB_OTG_CORE_HANDLE *pdev); + +/** + * @} + */ + + +/** @defgroup USB_OTG_Private_Functions + * @{ + */ + + +/* OTG Interrupt Handler */ + + +/** + * @brief STM32_USBO_OTG_ISR_Handler + * + * @param None + * @retval : None + */ +uint32_t STM32_USBO_OTG_ISR_Handler(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t retval = 0; + USB_OTG_GINTSTS_TypeDef gintsts ; + gintsts.d32 = 0; + + gintsts.d32 = USB_OTG_Read_itr(pdev); + if (gintsts.d32 == 0) + { + return 0; + } + if (gintsts.b.otgintr) + { + retval |= USB_OTG_HandleOTG_ISR(pdev); + } + if (gintsts.b.conidstschng) + { + retval |= USB_OTG_HandleConnectorIDStatusChange_ISR(pdev); + } + if (gintsts.b.sessreqintr) + { + retval |= USB_OTG_HandleSessionRequest_ISR(pdev); + } + return retval; +} + + +/** + * @brief USB_OTG_Read_itr + * returns the Core Interrupt register + * @param None + * @retval : status + */ +static uint32_t USB_OTG_Read_itr(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + USB_OTG_GINTMSK_TypeDef gintmsk; + USB_OTG_GINTMSK_TypeDef gintmsk_common; + + + gintsts.d32 = 0; + gintmsk.d32 = 0; + gintmsk_common.d32 = 0; + + /* OTG interrupts */ + gintmsk_common.b.sessreqintr = 1; + gintmsk_common.b.conidstschng = 1; + gintmsk_common.b.otgintr = 1; + + gintsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTSTS); + gintmsk.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTMSK); + return ((gintsts.d32 & gintmsk.d32 ) & gintmsk_common.d32); +} + + +/** + * @brief USB_OTG_HandleOTG_ISR + * handles the OTG Interrupts + * @param None + * @retval : status + */ +static uint32_t USB_OTG_HandleOTG_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GOTGINT_TypeDef gotgint; + USB_OTG_GOTGCTL_TypeDef gotgctl; + + + gotgint.d32 = 0; + gotgctl.d32 = 0; + + gotgint.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGINT); + gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); + + if (gotgint.b.sesenddet) + { + gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); + + + if (USB_OTG_IsDeviceMode(pdev)) + { + + } + else if (USB_OTG_IsHostMode(pdev)) + { + + } + } + + /* ----> SRP SUCCESS or FAILURE INTERRUPT <---- */ + if (gotgint.b.sesreqsucstschng) + { + gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); + if (gotgctl.b.sesreqscs) /* Session request success */ + { + if (USB_OTG_IsDeviceMode(pdev)) + { + + } + /* Clear Session Request */ + gotgctl.d32 = 0; + gotgctl.b.sesreq = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GOTGCTL, gotgctl.d32, 0); + } + else /* Session request failure */ + { + if (USB_OTG_IsDeviceMode(pdev)) + { + + } + } + } + /* ----> HNP SUCCESS or FAILURE INTERRUPT <---- */ + if (gotgint.b.hstnegsucstschng) + { + gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); + + if (gotgctl.b.hstnegscs) /* Host negotiation success */ + { + if (USB_OTG_IsHostMode(pdev)) /* The core AUTOMATICALLY sets the Host mode */ + { + + } + } + else /* Host negotiation failure */ + { + + } + gotgint.b.hstnegsucstschng = 1; /* Ack "Host Negotiation Success Status Change" interrupt. */ + } + /* ----> HOST NEGOTIATION DETECTED INTERRUPT <---- */ + if (gotgint.b.hstnegdet) + { + if (USB_OTG_IsDeviceMode(pdev)) /* The core AUTOMATICALLY sets the Host mode */ + { + + } + else + { + + } + } + if (gotgint.b.adevtoutchng) + {} + if (gotgint.b.debdone) + { + USB_OTG_ResetPort(pdev); + } + /* Clear OTG INT */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GOTGINT, gotgint.d32); + return 1; +} + + +/** + * @brief USB_OTG_HandleConnectorIDStatusChange_ISR + * handles the Connector ID Status Change Interrupt + * @param None + * @retval : status + */ +static uint32_t USB_OTG_HandleConnectorIDStatusChange_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTMSK_TypeDef gintmsk; + USB_OTG_GOTGCTL_TypeDef gotgctl; + USB_OTG_GINTSTS_TypeDef gintsts; + + gintsts.d32 = 0 ; + gintmsk.d32 = 0 ; + gotgctl.d32 = 0 ; + gintmsk.b.sofintr = 1; + + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, gintmsk.d32, 0); + gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); + + /* B-Device connector (Device Mode) */ + if (gotgctl.b.conidsts) + { + USB_OTG_DisableGlobalInt(pdev); + USB_OTG_CoreInitDev(pdev); + USB_OTG_EnableGlobalInt(pdev); + pdev->otg.OTG_State = B_PERIPHERAL; + } + else + { + USB_OTG_DisableGlobalInt(pdev); + USB_OTG_CoreInitHost(pdev); + USB_OTG_EnableGlobalInt(pdev); + pdev->otg.OTG_State = A_HOST; + } + /* Set flag and clear interrupt */ + gintsts.b.conidstschng = 1; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32); + return 1; +} + + +/** + * @brief USB_OTG_HandleSessionRequest_ISR + * Initiating the Session Request Protocol + * @param None + * @retval : status + */ +static uint32_t USB_OTG_HandleSessionRequest_ISR(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTSTS_TypeDef gintsts; + USB_OTG_GOTGCTL_TypeDef gotgctl; + + + gotgctl.d32 = 0; + gintsts.d32 = 0; + + gotgctl.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GOTGCTL ); + if (USB_OTG_IsDeviceMode(pdev) && (gotgctl.b.bsesvld)) + { + + } + else if (gotgctl.b.asesvld) + { + } + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.sessreqintr = 1; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GINTSTS, gintsts.d32); + return 1; +} + + +/** + * @brief USB_OTG_InitiateSRP + * Initiate an srp session + * @param None + * @retval : None + */ +void USB_OTG_InitiateSRP(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GOTGCTL_TypeDef otgctl; + + otgctl.d32 = 0; + + otgctl.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GOTGCTL ); + if (otgctl.b.sesreq) + { + return; /* SRP in progress */ + } + otgctl.b.sesreq = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GOTGCTL, otgctl.d32); +} + + +/** + * @brief USB_OTG_InitiateHNP + * Initiate HNP + * @param None + * @retval : None + */ +void USB_OTG_InitiateHNP(USB_OTG_CORE_HANDLE *pdev , uint8_t state, uint8_t mode) +{ + USB_OTG_GOTGCTL_TypeDef otgctl; + USB_OTG_HPRT0_TypeDef hprt0; + + otgctl.d32 = 0; + hprt0.d32 = 0; + + otgctl.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GOTGCTL ); + if (mode) + { /* Device mode */ + if (state) + { + + otgctl.b.devhnpen = 1; /* B-Dev has been enabled to perform HNP */ + otgctl.b.hnpreq = 1; /* Initiate an HNP req. to the connected USB host*/ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GOTGCTL, otgctl.d32); + } + } + else + { /* Host mode */ + if (state) + { + otgctl.b.hstsethnpen = 1; /* A-Dev has enabled B-device for HNP */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GOTGCTL, otgctl.d32); + /* Suspend the bus so that B-dev will disconnect indicating the initial condition for HNP to DWC_Core */ + hprt0.d32 = USB_OTG_ReadHPRT0(pdev); + hprt0.b.prtsusp = 1; /* The core clear this bit when disconnect interrupt generated (GINTSTS.DisconnInt = '1') */ + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + } + } +} + + +/** + * @brief USB_OTG_GetCurrentState + * Return current OTG State + * @param None + * @retval : None + */ +uint32_t USB_OTG_GetCurrentState (USB_OTG_CORE_HANDLE *pdev) +{ + return pdev->otg.OTG_State; +} + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usb_otg.h b/stm/lib/usb_otg.h new file mode 100644 index 000000000..54d35f996 --- /dev/null +++ b/stm/lib/usb_otg.h @@ -0,0 +1,99 @@ +/** + ****************************************************************************** + * @file usb_otg.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief OTG Core Header + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_OTG__ +#define __USB_OTG__ + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_OTG + * @brief This file is the + * @{ + */ + + +/** @defgroup USB_OTG_Exported_Defines + * @{ + */ + + +void USB_OTG_InitiateSRP(void); +void USB_OTG_InitiateHNP(uint8_t state , uint8_t mode); +void USB_OTG_Switchback (USB_OTG_CORE_DEVICE *pdev); +uint32_t USB_OTG_GetCurrentState (USB_OTG_CORE_DEVICE *pdev); + +/** + * @} + */ + + +/** @defgroup USB_OTG_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_OTG_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_OTG_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_OTG_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +#endif //__USB_OTG__ + + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usb_regs.h b/stm/lib/usb_regs.h new file mode 100644 index 000000000..323e87056 --- /dev/null +++ b/stm/lib/usb_regs.h @@ -0,0 +1,1188 @@ +/** + ****************************************************************************** + * @file usb_regs.h + * @author MCD Application Team + * @version V2.1.0 + * @date 19-March-2012 + * @brief hardware registers + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_OTG_REGS_H__ +#define __USB_OTG_REGS_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_REGS + * @brief This file is the + * @{ + */ + + +/** @defgroup USB_REGS_Exported_Defines + * @{ + */ + +#define USB_OTG_HS_BASE_ADDR 0x40040000 +#define USB_OTG_FS_BASE_ADDR 0x50000000 + +#define USB_OTG_CORE_GLOBAL_REGS_OFFSET 0x000 +#define USB_OTG_DEV_GLOBAL_REG_OFFSET 0x800 +#define USB_OTG_DEV_IN_EP_REG_OFFSET 0x900 +#define USB_OTG_EP_REG_OFFSET 0x20 +#define USB_OTG_DEV_OUT_EP_REG_OFFSET 0xB00 +#define USB_OTG_HOST_GLOBAL_REG_OFFSET 0x400 +#define USB_OTG_HOST_PORT_REGS_OFFSET 0x440 +#define USB_OTG_HOST_CHAN_REGS_OFFSET 0x500 +#define USB_OTG_CHAN_REGS_OFFSET 0x20 +#define USB_OTG_PCGCCTL_OFFSET 0xE00 +#define USB_OTG_DATA_FIFO_OFFSET 0x1000 +#define USB_OTG_DATA_FIFO_SIZE 0x1000 + + +#define USB_OTG_MAX_TX_FIFOS 15 + +#define USB_OTG_HS_MAX_PACKET_SIZE 512 +#define USB_OTG_FS_MAX_PACKET_SIZE 64 +#define USB_OTG_MAX_EP0_SIZE 64 +/** + * @} + */ + +/** @defgroup USB_REGS_Exported_Types + * @{ + */ + +/** @defgroup __USB_OTG_Core_register + * @{ + */ +typedef struct _USB_OTG_GREGS //000h +{ + __IO uint32_t GOTGCTL; /* USB_OTG Control and Status Register 000h*/ + __IO uint32_t GOTGINT; /* USB_OTG Interrupt Register 004h*/ + __IO uint32_t GAHBCFG; /* Core AHB Configuration Register 008h*/ + __IO uint32_t GUSBCFG; /* Core USB Configuration Register 00Ch*/ + __IO uint32_t GRSTCTL; /* Core Reset Register 010h*/ + __IO uint32_t GINTSTS; /* Core Interrupt Register 014h*/ + __IO uint32_t GINTMSK; /* Core Interrupt Mask Register 018h*/ + __IO uint32_t GRXSTSR; /* Receive Sts Q Read Register 01Ch*/ + __IO uint32_t GRXSTSP; /* Receive Sts Q Read & POP Register 020h*/ + __IO uint32_t GRXFSIZ; /* Receive FIFO Size Register 024h*/ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /* EP0 / Non Periodic Tx FIFO Size Register 028h*/ + __IO uint32_t HNPTXSTS; /* Non Periodic Tx FIFO/Queue Sts reg 02Ch*/ + uint32_t Reserved30[2]; /* Reserved 030h*/ + __IO uint32_t GCCFG; /* General Purpose IO Register 038h*/ + __IO uint32_t CID; /* User ID Register 03Ch*/ + uint32_t Reserved40[48]; /* Reserved 040h-0FFh*/ + __IO uint32_t HPTXFSIZ; /* Host Periodic Tx FIFO Size Reg 100h*/ + __IO uint32_t DIEPTXF[USB_OTG_MAX_TX_FIFOS];/* dev Periodic Transmit FIFO */ +} +USB_OTG_GREGS; +/** + * @} + */ + + +/** @defgroup __device_Registers + * @{ + */ +typedef struct _USB_OTG_DREGS // 800h +{ + __IO uint32_t DCFG; /* dev Configuration Register 800h*/ + __IO uint32_t DCTL; /* dev Control Register 804h*/ + __IO uint32_t DSTS; /* dev Status Register (RO) 808h*/ + uint32_t Reserved0C; /* Reserved 80Ch*/ + __IO uint32_t DIEPMSK; /* dev IN Endpoint Mask 810h*/ + __IO uint32_t DOEPMSK; /* dev OUT Endpoint Mask 814h*/ + __IO uint32_t DAINT; /* dev All Endpoints Itr Reg 818h*/ + __IO uint32_t DAINTMSK; /* dev All Endpoints Itr Mask 81Ch*/ + uint32_t Reserved20; /* Reserved 820h*/ + uint32_t Reserved9; /* Reserved 824h*/ + __IO uint32_t DVBUSDIS; /* dev VBUS discharge Register 828h*/ + __IO uint32_t DVBUSPULSE; /* dev VBUS Pulse Register 82Ch*/ + __IO uint32_t DTHRCTL; /* dev thr 830h*/ + __IO uint32_t DIEPEMPMSK; /* dev empty msk 834h*/ + __IO uint32_t DEACHINT; /* dedicated EP interrupt 838h*/ + __IO uint32_t DEACHMSK; /* dedicated EP msk 83Ch*/ + uint32_t Reserved40; /* dedicated EP mask 840h*/ + __IO uint32_t DINEP1MSK; /* dedicated EP mask 844h*/ + uint32_t Reserved44[15]; /* Reserved 844-87Ch*/ + __IO uint32_t DOUTEP1MSK; /* dedicated EP msk 884h*/ +} +USB_OTG_DREGS; +/** + * @} + */ + + +/** @defgroup __IN_Endpoint-Specific_Register + * @{ + */ +typedef struct _USB_OTG_INEPREGS +{ + __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/ + __IO uint32_t DIEPINT; /* dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved 900h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DIEPTSIZ; /* IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/ + __IO uint32_t DIEPDMA; /* IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/ + __IO uint32_t DTXFSTS;/*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/ + uint32_t Reserved18; /* Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/ +} +USB_OTG_INEPREGS; +/** + * @} + */ + + +/** @defgroup __OUT_Endpoint-Specific_Registers + * @{ + */ +typedef struct _USB_OTG_OUTEPREGS +{ + __IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/ + __IO uint32_t DOEPINT; /* dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved B00h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DOEPTSIZ; /* dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/ + __IO uint32_t DOEPDMA; /* dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/ + uint32_t Reserved18[2]; /* Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/ +} +USB_OTG_OUTEPREGS; +/** + * @} + */ + + +/** @defgroup __Host_Mode_Register_Structures + * @{ + */ +typedef struct _USB_OTG_HREGS +{ + __IO uint32_t HCFG; /* Host Configuration Register 400h*/ + __IO uint32_t HFIR; /* Host Frame Interval Register 404h*/ + __IO uint32_t HFNUM; /* Host Frame Nbr/Frame Remaining 408h*/ + uint32_t Reserved40C; /* Reserved 40Ch*/ + __IO uint32_t HPTXSTS; /* Host Periodic Tx FIFO/ Queue Status 410h*/ + __IO uint32_t HAINT; /* Host All Channels Interrupt Register 414h*/ + __IO uint32_t HAINTMSK; /* Host All Channels Interrupt Mask 418h*/ +} +USB_OTG_HREGS; +/** + * @} + */ + + +/** @defgroup __Host_Channel_Specific_Registers + * @{ + */ +typedef struct _USB_OTG_HC_REGS +{ + __IO uint32_t HCCHAR; + __IO uint32_t HCSPLT; + __IO uint32_t HCINT; + __IO uint32_t HCINTMSK; + __IO uint32_t HCTSIZ; + __IO uint32_t HCDMA; + uint32_t Reserved[2]; +} +USB_OTG_HC_REGS; +/** + * @} + */ + + +/** @defgroup __otg_Core_registers + * @{ + */ +typedef struct USB_OTG_core_regs //000h +{ + USB_OTG_GREGS *GREGS; + USB_OTG_DREGS *DREGS; + USB_OTG_HREGS *HREGS; + USB_OTG_INEPREGS *INEP_REGS[USB_OTG_MAX_TX_FIFOS]; + USB_OTG_OUTEPREGS *OUTEP_REGS[USB_OTG_MAX_TX_FIFOS]; + USB_OTG_HC_REGS *HC_REGS[USB_OTG_MAX_TX_FIFOS]; + __IO uint32_t *HPRT0; + __IO uint32_t *DFIFO[USB_OTG_MAX_TX_FIFOS]; + __IO uint32_t *PCGCCTL; +} +USB_OTG_CORE_REGS , *PUSB_OTG_CORE_REGS; +typedef union _USB_OTG_GOTGCTL_TypeDef +{ + uint32_t d32; + struct + { +uint32_t sesreqscs : + 1; +uint32_t sesreq : + 1; +uint32_t Reserved2_7 : + 6; +uint32_t hstnegscs : + 1; +uint32_t hnpreq : + 1; +uint32_t hstsethnpen : + 1; +uint32_t devhnpen : + 1; +uint32_t Reserved12_15 : + 4; +uint32_t conidsts : + 1; +uint32_t dbct : + 1; +uint32_t asesvld : + 1; +uint32_t bsesvld : + 1; +uint32_t Reserved20_31 : + 12; + } + b; +} USB_OTG_GOTGCTL_TypeDef ; + +typedef union _USB_OTG_GOTGINT_TypeDef +{ + uint32_t d32; + struct + { +uint32_t Reserved0_1 : + 2; +uint32_t sesenddet : + 1; +uint32_t Reserved3_7 : + 5; +uint32_t sesreqsucstschng : + 1; +uint32_t hstnegsucstschng : + 1; +uint32_t reserver10_16 : + 7; +uint32_t hstnegdet : + 1; +uint32_t adevtoutchng : + 1; +uint32_t debdone : + 1; +uint32_t Reserved31_20 : + 12; + } + b; +} USB_OTG_GOTGINT_TypeDef ; +typedef union _USB_OTG_GAHBCFG_TypeDef +{ + uint32_t d32; + struct + { +uint32_t glblintrmsk : + 1; +uint32_t hburstlen : + 4; +uint32_t dmaenable : + 1; +uint32_t Reserved : + 1; +uint32_t nptxfemplvl_txfemplvl : + 1; +uint32_t ptxfemplvl : + 1; +uint32_t Reserved9_31 : + 23; + } + b; +} USB_OTG_GAHBCFG_TypeDef ; +typedef union _USB_OTG_GUSBCFG_TypeDef +{ + uint32_t d32; + struct + { +uint32_t toutcal : + 3; +uint32_t Reserved3_5 : + 3; +uint32_t physel : + 1; +uint32_t Reserved7 : + 1; +uint32_t srpcap : + 1; +uint32_t hnpcap : + 1; +uint32_t usbtrdtim : + 4; +uint32_t Reserved14 : + 1; +uint32_t phylpwrclksel : + 1; +uint32_t Reserved16 : + 1; +uint32_t ulpi_fsls : + 1; +uint32_t ulpi_auto_res : + 1; +uint32_t ulpi_clk_sus_m : + 1; +uint32_t ulpi_ext_vbus_drv : + 1; +uint32_t ulpi_int_vbus_ind : + 1; +uint32_t term_sel_dl_pulse : + 1; +uint32_t ulpi_ind_cpl : + 1; +uint32_t ulpi_passthrough : + 1; +uint32_t ulpi_protect_disable : + 1; +uint32_t Reserved26_28 : + 3; +uint32_t force_host : + 1; +uint32_t force_dev : + 1; +uint32_t corrupt_tx : + 1; + } + b; +} USB_OTG_GUSBCFG_TypeDef ; +typedef union _USB_OTG_GRSTCTL_TypeDef +{ + uint32_t d32; + struct + { +uint32_t csftrst : + 1; +uint32_t hsftrst : + 1; +uint32_t hstfrm : + 1; +uint32_t Reserved3 : + 1; +uint32_t rxfflsh : + 1; +uint32_t txfflsh : + 1; +uint32_t txfnum : + 5; +uint32_t Reserved11_29 : + 19; +uint32_t dmareq : + 1; +uint32_t ahbidle : + 1; + } + b; +} USB_OTG_GRSTCTL_TypeDef ; +typedef union _USB_OTG_GINTMSK_TypeDef +{ + uint32_t d32; + struct + { +uint32_t Reserved0 : + 1; +uint32_t modemismatch : + 1; +uint32_t otgintr : + 1; +uint32_t sofintr : + 1; +uint32_t rxstsqlvl : + 1; +uint32_t nptxfempty : + 1; +uint32_t ginnakeff : + 1; +uint32_t goutnakeff : + 1; +uint32_t Reserved8_9 : + 2; +uint32_t erlysuspend : + 1; +uint32_t usbsuspend : + 1; +uint32_t usbreset : + 1; +uint32_t enumdone : + 1; +uint32_t isooutdrop : + 1; +uint32_t eopframe : + 1; +uint32_t Reserved16 : + 1; +uint32_t epmismatch : + 1; +uint32_t inepintr : + 1; +uint32_t outepintr : + 1; +uint32_t incomplisoin : + 1; +uint32_t incomplisoout : + 1; +uint32_t Reserved22_23 : + 2; +uint32_t portintr : + 1; +uint32_t hcintr : + 1; +uint32_t ptxfempty : + 1; +uint32_t Reserved27 : + 1; +uint32_t conidstschng : + 1; +uint32_t disconnect : + 1; +uint32_t sessreqintr : + 1; +uint32_t wkupintr : + 1; + } + b; +} USB_OTG_GINTMSK_TypeDef ; +typedef union _USB_OTG_GINTSTS_TypeDef +{ + uint32_t d32; + struct + { +uint32_t curmode : + 1; +uint32_t modemismatch : + 1; +uint32_t otgintr : + 1; +uint32_t sofintr : + 1; +uint32_t rxstsqlvl : + 1; +uint32_t nptxfempty : + 1; +uint32_t ginnakeff : + 1; +uint32_t goutnakeff : + 1; +uint32_t Reserved8_9 : + 2; +uint32_t erlysuspend : + 1; +uint32_t usbsuspend : + 1; +uint32_t usbreset : + 1; +uint32_t enumdone : + 1; +uint32_t isooutdrop : + 1; +uint32_t eopframe : + 1; +uint32_t Reserved16_17 : + 2; +uint32_t inepint: + 1; +uint32_t outepintr : + 1; +uint32_t incomplisoin : + 1; +uint32_t incomplisoout : + 1; +uint32_t Reserved22_23 : + 2; +uint32_t portintr : + 1; +uint32_t hcintr : + 1; +uint32_t ptxfempty : + 1; +uint32_t Reserved27 : + 1; +uint32_t conidstschng : + 1; +uint32_t disconnect : + 1; +uint32_t sessreqintr : + 1; +uint32_t wkupintr : + 1; + } + b; +} USB_OTG_GINTSTS_TypeDef ; +typedef union _USB_OTG_DRXSTS_TypeDef +{ + uint32_t d32; + struct + { +uint32_t epnum : + 4; +uint32_t bcnt : + 11; +uint32_t dpid : + 2; +uint32_t pktsts : + 4; +uint32_t fn : + 4; +uint32_t Reserved : + 7; + } + b; +} USB_OTG_DRXSTS_TypeDef ; +typedef union _USB_OTG_GRXSTS_TypeDef +{ + uint32_t d32; + struct + { +uint32_t chnum : + 4; +uint32_t bcnt : + 11; +uint32_t dpid : + 2; +uint32_t pktsts : + 4; +uint32_t Reserved : + 11; + } + b; +} USB_OTG_GRXFSTS_TypeDef ; +typedef union _USB_OTG_FSIZ_TypeDef +{ + uint32_t d32; + struct + { +uint32_t startaddr : + 16; +uint32_t depth : + 16; + } + b; +} USB_OTG_FSIZ_TypeDef ; +typedef union _USB_OTG_HNPTXSTS_TypeDef +{ + uint32_t d32; + struct + { + uint32_t nptxfspcavail : + 16; + uint32_t nptxqspcavail : + 8; + struct + { + uint32_t terminate : + 1; + uint32_t token : + 2; + uint32_t chnum : + 4; + } nptxqtop; + uint32_t Reserved : + 1; + } + b; +} USB_OTG_HNPTXSTS_TypeDef ; +typedef union _USB_OTG_DTXFSTSn_TypeDef +{ + uint32_t d32; + struct + { +uint32_t txfspcavail : + 16; +uint32_t Reserved : + 16; + } + b; +} USB_OTG_DTXFSTSn_TypeDef ; + +typedef union _USB_OTG_GCCFG_TypeDef +{ + uint32_t d32; + struct + { +uint32_t Reserved_in : + 16; +uint32_t pwdn : + 1; +uint32_t Reserved_17 : + 1; +uint32_t vbussensingA : + 1; +uint32_t vbussensingB : + 1; +uint32_t sofouten : + 1; +uint32_t disablevbussensing : + 1; +uint32_t Reserved_out : + 10; + } + b; +} USB_OTG_GCCFG_TypeDef ; + +typedef union _USB_OTG_DCFG_TypeDef +{ + uint32_t d32; + struct + { +uint32_t devspd : + 2; +uint32_t nzstsouthshk : + 1; +uint32_t Reserved3 : + 1; +uint32_t devaddr : + 7; +uint32_t perfrint : + 2; +uint32_t Reserved12_31 : + 19; + } + b; +} USB_OTG_DCFG_TypeDef ; +typedef union _USB_OTG_DCTL_TypeDef +{ + uint32_t d32; + struct + { +uint32_t rmtwkupsig : + 1; +uint32_t sftdiscon : + 1; +uint32_t gnpinnaksts : + 1; +uint32_t goutnaksts : + 1; +uint32_t tstctl : + 3; +uint32_t sgnpinnak : + 1; +uint32_t cgnpinnak : + 1; +uint32_t sgoutnak : + 1; +uint32_t cgoutnak : + 1; +uint32_t poprg_done : + 1; +uint32_t Reserved : + 20; + } + b; +} USB_OTG_DCTL_TypeDef ; +typedef union _USB_OTG_DSTS_TypeDef +{ + uint32_t d32; + struct + { +uint32_t suspsts : + 1; +uint32_t enumspd : + 2; +uint32_t errticerr : + 1; +uint32_t Reserved4_7: + 4; +uint32_t soffn : + 14; +uint32_t Reserved22_31 : + 10; + } + b; +} USB_OTG_DSTS_TypeDef ; +typedef union _USB_OTG_DIEPINTn_TypeDef +{ + uint32_t d32; + struct + { +uint32_t xfercompl : + 1; +uint32_t epdisabled : + 1; +uint32_t Reserved2 : + 1; +uint32_t timeout : + 1; +uint32_t intktxfemp : + 1; +uint32_t Reserved5 : + 1; +uint32_t inepnakeff : + 1; +uint32_t emptyintr : + 1; +uint32_t txfifoundrn : + 1; +uint32_t Reserved14_31 : + 23; + } + b; +} USB_OTG_DIEPINTn_TypeDef ; +typedef union _USB_OTG_DIEPINTn_TypeDef USB_OTG_DIEPMSK_TypeDef ; +typedef union _USB_OTG_DOEPINTn_TypeDef +{ + uint32_t d32; + struct + { +uint32_t xfercompl : + 1; +uint32_t epdisabled : + 1; +uint32_t Reserved2 : + 1; +uint32_t setup : + 1; +uint32_t Reserved04_31 : + 28; + } + b; +} USB_OTG_DOEPINTn_TypeDef ; +typedef union _USB_OTG_DOEPINTn_TypeDef USB_OTG_DOEPMSK_TypeDef ; + +typedef union _USB_OTG_DAINT_TypeDef +{ + uint32_t d32; + struct + { +uint32_t in : + 16; +uint32_t out : + 16; + } + ep; +} USB_OTG_DAINT_TypeDef ; + +typedef union _USB_OTG_DTHRCTL_TypeDef +{ + uint32_t d32; + struct + { +uint32_t non_iso_thr_en : + 1; +uint32_t iso_thr_en : + 1; +uint32_t tx_thr_len : + 9; +uint32_t Reserved11_15 : + 5; +uint32_t rx_thr_en : + 1; +uint32_t rx_thr_len : + 9; +uint32_t Reserved26 : + 1; +uint32_t arp_en : + 1; +uint32_t Reserved28_31 : + 4; + } + b; +} USB_OTG_DTHRCTL_TypeDef ; +typedef union _USB_OTG_DEPCTL_TypeDef +{ + uint32_t d32; + struct + { +uint32_t mps : + 11; +uint32_t reserved : + 4; +uint32_t usbactep : + 1; +uint32_t dpid : + 1; +uint32_t naksts : + 1; +uint32_t eptype : + 2; +uint32_t snp : + 1; +uint32_t stall : + 1; +uint32_t txfnum : + 4; +uint32_t cnak : + 1; +uint32_t snak : + 1; +uint32_t setd0pid : + 1; +uint32_t setd1pid : + 1; +uint32_t epdis : + 1; +uint32_t epena : + 1; + } + b; +} USB_OTG_DEPCTL_TypeDef ; +typedef union _USB_OTG_DEPXFRSIZ_TypeDef +{ + uint32_t d32; + struct + { +uint32_t xfersize : + 19; +uint32_t pktcnt : + 10; +uint32_t mc : + 2; +uint32_t Reserved : + 1; + } + b; +} USB_OTG_DEPXFRSIZ_TypeDef ; +typedef union _USB_OTG_DEP0XFRSIZ_TypeDef +{ + uint32_t d32; + struct + { +uint32_t xfersize : + 7; +uint32_t Reserved7_18 : + 12; +uint32_t pktcnt : + 2; +uint32_t Reserved20_28 : + 9; +uint32_t supcnt : + 2; + uint32_t Reserved31; + } + b; +} USB_OTG_DEP0XFRSIZ_TypeDef ; +typedef union _USB_OTG_HCFG_TypeDef +{ + uint32_t d32; + struct + { +uint32_t fslspclksel : + 2; +uint32_t fslssupp : + 1; + } + b; +} USB_OTG_HCFG_TypeDef ; +typedef union _USB_OTG_HFRMINTRVL_TypeDef +{ + uint32_t d32; + struct + { +uint32_t frint : + 16; +uint32_t Reserved : + 16; + } + b; +} USB_OTG_HFRMINTRVL_TypeDef ; + +typedef union _USB_OTG_HFNUM_TypeDef +{ + uint32_t d32; + struct + { +uint32_t frnum : + 16; +uint32_t frrem : + 16; + } + b; +} USB_OTG_HFNUM_TypeDef ; +typedef union _USB_OTG_HPTXSTS_TypeDef +{ + uint32_t d32; + struct + { +uint32_t ptxfspcavail : + 16; +uint32_t ptxqspcavail : + 8; + struct + { + uint32_t terminate : + 1; + uint32_t token : + 2; + uint32_t chnum : + 4; + uint32_t odd_even : + 1; + } ptxqtop; + } + b; +} USB_OTG_HPTXSTS_TypeDef ; +typedef union _USB_OTG_HPRT0_TypeDef +{ + uint32_t d32; + struct + { +uint32_t prtconnsts : + 1; +uint32_t prtconndet : + 1; +uint32_t prtena : + 1; +uint32_t prtenchng : + 1; +uint32_t prtovrcurract : + 1; +uint32_t prtovrcurrchng : + 1; +uint32_t prtres : + 1; +uint32_t prtsusp : + 1; +uint32_t prtrst : + 1; +uint32_t Reserved9 : + 1; +uint32_t prtlnsts : + 2; +uint32_t prtpwr : + 1; +uint32_t prttstctl : + 4; +uint32_t prtspd : + 2; +uint32_t Reserved19_31 : + 13; + } + b; +} USB_OTG_HPRT0_TypeDef ; +typedef union _USB_OTG_HAINT_TypeDef +{ + uint32_t d32; + struct + { +uint32_t chint : + 16; +uint32_t Reserved : + 16; + } + b; +} USB_OTG_HAINT_TypeDef ; +typedef union _USB_OTG_HAINTMSK_TypeDef +{ + uint32_t d32; + struct + { +uint32_t chint : + 16; +uint32_t Reserved : + 16; + } + b; +} USB_OTG_HAINTMSK_TypeDef ; +typedef union _USB_OTG_HCCHAR_TypeDef +{ + uint32_t d32; + struct + { +uint32_t mps : + 11; +uint32_t epnum : + 4; +uint32_t epdir : + 1; +uint32_t Reserved : + 1; +uint32_t lspddev : + 1; +uint32_t eptype : + 2; +uint32_t multicnt : + 2; +uint32_t devaddr : + 7; +uint32_t oddfrm : + 1; +uint32_t chdis : + 1; +uint32_t chen : + 1; + } + b; +} USB_OTG_HCCHAR_TypeDef ; +typedef union _USB_OTG_HCSPLT_TypeDef +{ + uint32_t d32; + struct + { +uint32_t prtaddr : + 7; +uint32_t hubaddr : + 7; +uint32_t xactpos : + 2; +uint32_t compsplt : + 1; +uint32_t Reserved : + 14; +uint32_t spltena : + 1; + } + b; +} USB_OTG_HCSPLT_TypeDef ; +typedef union _USB_OTG_HCINTn_TypeDef +{ + uint32_t d32; + struct + { +uint32_t xfercompl : + 1; +uint32_t chhltd : + 1; +uint32_t ahberr : + 1; +uint32_t stall : + 1; +uint32_t nak : + 1; +uint32_t ack : + 1; +uint32_t nyet : + 1; +uint32_t xacterr : + 1; +uint32_t bblerr : + 1; +uint32_t frmovrun : + 1; +uint32_t datatglerr : + 1; +uint32_t Reserved : + 21; + } + b; +} USB_OTG_HCINTn_TypeDef ; +typedef union _USB_OTG_HCTSIZn_TypeDef +{ + uint32_t d32; + struct + { +uint32_t xfersize : + 19; +uint32_t pktcnt : + 10; +uint32_t pid : + 2; +uint32_t dopng : + 1; + } + b; +} USB_OTG_HCTSIZn_TypeDef ; +typedef union _USB_OTG_HCINTMSK_TypeDef +{ + uint32_t d32; + struct + { +uint32_t xfercompl : + 1; +uint32_t chhltd : + 1; +uint32_t ahberr : + 1; +uint32_t stall : + 1; +uint32_t nak : + 1; +uint32_t ack : + 1; +uint32_t nyet : + 1; +uint32_t xacterr : + 1; +uint32_t bblerr : + 1; +uint32_t frmovrun : + 1; +uint32_t datatglerr : + 1; +uint32_t Reserved : + 21; + } + b; +} USB_OTG_HCINTMSK_TypeDef ; + +typedef union _USB_OTG_PCGCCTL_TypeDef +{ + uint32_t d32; + struct + { +uint32_t stoppclk : + 1; +uint32_t gatehclk : + 1; +uint32_t Reserved2_3 : + 2; +uint32_t phy_susp : + 1; +uint32_t Reserved5_31 : + 27; + } + b; +} USB_OTG_PCGCCTL_TypeDef ; + +/** + * @} + */ + + +/** @defgroup USB_REGS_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_REGS_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_REGS_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +#endif //__USB_OTG_REGS_H__ + + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_cdc_conf.h b/stm/lib/usbd_cdc_conf.h new file mode 100644 index 000000000..2a1608ac9 --- /dev/null +++ b/stm/lib/usbd_cdc_conf.h @@ -0,0 +1,105 @@ +/** + ****************************************************************************** + * @file usbd_conf.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief USB Device configuration file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_VCP_CONF__H__ +#define __USBD_VCP_CONF__H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" + +/** @defgroup USB_CONF_Exported_Defines + * @{ + */ +//#define USBD_CFG_MAX_NUM 1 +//#define USBD_ITF_MAX_NUM 1 + +//#define USBD_SELF_POWERED + +/** @defgroup USB_VCP_Class_Layer_Parameter + * @{ + */ +#define CDC_IN_EP 0x81 /* EP1 for data IN */ +#define CDC_OUT_EP 0x01 /* EP1 for data OUT */ +#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */ + +/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#ifdef USE_USB_OTG_HS + #define CDC_DATA_MAX_PACKET_SIZE 512 /* Endpoint IN & OUT Packet size */ + #define CDC_CMD_PACKET_SZE 8 /* Control Endpoint Packet size */ + + #define CDC_IN_FRAME_INTERVAL 40 /* Number of micro-frames between IN transfers */ + #define APP_RX_DATA_SIZE 2048 /* Total size of IN buffer: + APP_RX_DATA_SIZE*8/MAX_BAUDARATE*1000 should be > CDC_IN_FRAME_INTERVAL*8 */ +#else + #define CDC_DATA_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */ + #define CDC_CMD_PACKET_SZE 8 /* Control Endpoint Packet size */ + + #define CDC_IN_FRAME_INTERVAL 5 /* Number of frames between IN transfers */ + #define APP_RX_DATA_SIZE 2048 /* Total size of IN buffer: + APP_RX_DATA_SIZE*8/MAX_BAUDARATE*1000 should be > CDC_IN_FRAME_INTERVAL */ +#endif /* USE_USB_OTG_HS */ + +#define APP_FOPS VCP_fops +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +#endif //__USBD_VCP_CONF__H__ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_cdc_core.c b/stm/lib/usbd_cdc_core.c new file mode 100644 index 000000000..28c4e0336 --- /dev/null +++ b/stm/lib/usbd_cdc_core.c @@ -0,0 +1,818 @@ +/** + ****************************************************************************** + * @file usbd_cdc_core.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB CDC Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as CDC Device (and enumeration for each implemented memory interface) + * - OUT/IN data transfer + * - Command IN transfer (class requests management) + * - Error management + * + * @verbatim + * + * =================================================================== + * CDC Class Driver Description + * =================================================================== + * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus + * Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007" + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN) + * - Requests management (as described in section 6.2 in specification) + * - Abstract Control Model compliant + * - Union Functional collection (using 1 IN endpoint for control) + * - Data interface class + + * @note + * For the Abstract Control Model, this core allows only transmitting the requests to + * lower layer dispatcher (ie. usbd_cdc_vcp.c/.h) which should manage each request and + * perform relative actions. + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Any class-specific aspect relative to communication classes should be managed by user application. + * - All communication classes other than PSTN are not managed + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_core.h" +#include "usbd_desc.h" +#include "usbd_req.h" +#include "usbd_cdc_conf.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup usbd_cdc + * @brief usbd core module + * @{ + */ + +/** @defgroup usbd_cdc_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup usbd_cdc_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup usbd_cdc_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup usbd_cdc_Private_FunctionPrototypes + * @{ + */ + +/********************************************* + CDC Device library callbacks + *********************************************/ +static uint8_t usbd_cdc_Init (void *pdev, uint8_t cfgidx); +static uint8_t usbd_cdc_DeInit (void *pdev, uint8_t cfgidx); +static uint8_t usbd_cdc_Setup (void *pdev, USB_SETUP_REQ *req); +static uint8_t usbd_cdc_EP0_RxReady (void *pdev); +static uint8_t usbd_cdc_DataIn (void *pdev, uint8_t epnum); +static uint8_t usbd_cdc_DataOut (void *pdev, uint8_t epnum); +static uint8_t usbd_cdc_SOF (void *pdev); + +/********************************************* + CDC specific management functions + *********************************************/ +static void Handle_USBAsynchXfer (void *pdev); +static uint8_t *USBD_cdc_GetCfgDesc (uint8_t speed, uint16_t *length); +#ifdef USE_USB_OTG_HS +static uint8_t *USBD_cdc_GetOtherCfgDesc (uint8_t speed, uint16_t *length); +#endif +/** + * @} + */ + +/** @defgroup usbd_cdc_Private_Variables + * @{ + */ +extern CDC_IF_Prop_TypeDef APP_FOPS; +extern uint8_t USBD_DeviceDesc [USB_SIZ_DEVICE_DESC]; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t usbd_cdc_CfgDesc [USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t usbd_cdc_OtherCfgDesc [USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN static __IO uint32_t usbd_cdc_AltSet __ALIGN_END = 0; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t USB_Rx_Buffer [CDC_DATA_MAX_PACKET_SIZE] __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t APP_Rx_Buffer [APP_RX_DATA_SIZE] __ALIGN_END ; + + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t CmdBuff[CDC_CMD_PACKET_SZE] __ALIGN_END ; + +uint32_t APP_Rx_ptr_in = 0; +uint32_t APP_Rx_ptr_out = 0; +uint32_t APP_Rx_length = 0; + +uint8_t USB_Tx_State = 0; + +static uint32_t cdcCmd = 0xFF; +static uint32_t cdcLen = 0; + +/* CDC interface class callbacks structure */ +USBD_Class_cb_TypeDef USBD_CDC_cb = +{ + usbd_cdc_Init, + usbd_cdc_DeInit, + usbd_cdc_Setup, + NULL, /* EP0_TxSent, */ + usbd_cdc_EP0_RxReady, + usbd_cdc_DataIn, + usbd_cdc_DataOut, + usbd_cdc_SOF, + NULL, + NULL, + USBD_cdc_GetCfgDesc, +#ifdef USE_USB_OTG_HS + USBD_cdc_GetOtherCfgDesc, /* use same cobfig as per FS */ +#endif /* USE_USB_OTG_HS */ +}; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN uint8_t usbd_cdc_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ + USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ + 0x00, + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ + 0xC0, /* bmAttributes: self powered */ + 0x32, /* MaxPower 0 mA */ + + /*---------------------------------------------------------------------------*/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SZE), +#ifdef USE_USB_OTG_HS + 0x10, /* bInterval: */ +#else + 0xFF, /* bInterval: */ +#endif /* USE_USB_OTG_HS */ + + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_MAX_PACKET_SIZE), + 0x00 /* bInterval: ignore for Bulk transfer */ +} ; + +#ifdef USE_USB_OTG_HS +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t usbd_cdc_OtherCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION, + USB_CDC_CONFIG_DESC_SIZ, + 0x00, + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SZE), + 0xFF, /* bInterval: */ + + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00 /* bInterval */ +}; +#endif /* USE_USB_OTG_HS */ + +/** + * @} + */ + +/** @defgroup usbd_cdc_Private_Functions + * @{ + */ + +/** + * @brief usbd_cdc_Init + * Initilaize the CDC interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t usbd_cdc_Init (void *pdev, + uint8_t cfgidx) +{ + uint8_t *pbuf; + + /* Open EP IN */ + DCD_EP_Open(pdev, + CDC_IN_EP, + CDC_DATA_IN_PACKET_SIZE, + USB_OTG_EP_BULK); + + /* Open EP OUT */ + DCD_EP_Open(pdev, + CDC_OUT_EP, + CDC_DATA_OUT_PACKET_SIZE, + USB_OTG_EP_BULK); + + /* Open Command IN EP */ + DCD_EP_Open(pdev, + CDC_CMD_EP, + CDC_CMD_PACKET_SZE, + USB_OTG_EP_INT); + + pbuf = (uint8_t *)USBD_DeviceDesc; + pbuf[4] = DEVICE_CLASS_CDC; + pbuf[5] = DEVICE_SUBCLASS_CDC; + + /* Initialize the Interface physical components */ + APP_FOPS.pIf_Init(); + + /* Prepare Out endpoint to receive next packet */ + DCD_EP_PrepareRx(pdev, + CDC_OUT_EP, + (uint8_t*)(USB_Rx_Buffer), + CDC_DATA_OUT_PACKET_SIZE); + + return USBD_OK; +} + +/** + * @brief usbd_cdc_Init + * DeInitialize the CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t usbd_cdc_DeInit (void *pdev, + uint8_t cfgidx) +{ + /* Open EP IN */ + DCD_EP_Close(pdev, + CDC_IN_EP); + + /* Open EP OUT */ + DCD_EP_Close(pdev, + CDC_OUT_EP); + + /* Open Command IN EP */ + DCD_EP_Close(pdev, + CDC_CMD_EP); + + /* Restore default state of the Interface physical components */ + APP_FOPS.pIf_DeInit(); + + return USBD_OK; +} + +/** + * @brief usbd_cdc_Setup + * Handle the CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t usbd_cdc_Setup (void *pdev, + USB_SETUP_REQ *req) +{ + uint16_t len=USB_CDC_DESC_SIZ; + uint8_t *pbuf=usbd_cdc_CfgDesc + 9; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + /* CDC Class Requests -------------------------------*/ + case USB_REQ_TYPE_CLASS : + /* Check if the request is a data setup packet */ + if (req->wLength) + { + /* Check if the request is Device-to-Host */ + if (req->bmRequest & 0x80) + { + /* Get the data to be sent to Host from interface layer */ + APP_FOPS.pIf_Ctrl(req->bRequest, CmdBuff, req->wLength); + + /* Send the data to the host */ + USBD_CtlSendData (pdev, + CmdBuff, + req->wLength); + } + else /* Host-to-Device requeset */ + { + /* Set the value of the current command to be processed */ + cdcCmd = req->bRequest; + cdcLen = req->wLength; + + /* Prepare the reception of the buffer over EP0 + Next step: the received data will be managed in usbd_cdc_EP0_TxSent() + function. */ + USBD_CtlPrepareRx (pdev, + CmdBuff, + req->wLength); + } + } + else /* No Data request */ + { + /* Transfer the command to the interface layer */ + APP_FOPS.pIf_Ctrl(req->bRequest, NULL, 0); + } + + return USBD_OK; + + default: + USBD_CtlError (pdev, req); + return USBD_FAIL; + + + + /* Standard Requests -------------------------------*/ + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_DESCRIPTOR: + if( (req->wValue >> 8) == CDC_DESCRIPTOR_TYPE) + { +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + pbuf = usbd_cdc_Desc; +#else + pbuf = usbd_cdc_CfgDesc + 9 + (9 * USBD_ITF_MAX_NUM); +#endif + len = MIN(USB_CDC_DESC_SIZ , req->wLength); + } + + USBD_CtlSendData (pdev, + pbuf, + len); + break; + + case USB_REQ_GET_INTERFACE : + USBD_CtlSendData (pdev, + (uint8_t *)&usbd_cdc_AltSet, + 1); + break; + + case USB_REQ_SET_INTERFACE : + if ((uint8_t)(req->wValue) < USBD_ITF_MAX_NUM) + { + usbd_cdc_AltSet = (uint8_t)(req->wValue); + } + else + { + /* Call the error management function (command will be nacked */ + USBD_CtlError (pdev, req); + } + break; + } + } + return USBD_OK; +} + +/** + * @brief usbd_cdc_EP0_RxReady + * Data received on control endpoint + * @param pdev: device device instance + * @retval status + */ +static uint8_t usbd_cdc_EP0_RxReady (void *pdev) +{ + if (cdcCmd != NO_CMD) + { + /* Process the data */ + APP_FOPS.pIf_Ctrl(cdcCmd, CmdBuff, cdcLen); + + /* Reset the command variable to default value */ + cdcCmd = NO_CMD; + } + + return USBD_OK; +} + +/** + * @brief usbd_audio_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t usbd_cdc_DataIn (void *pdev, uint8_t epnum) +{ + uint16_t USB_Tx_ptr; + uint16_t USB_Tx_length; + + if (USB_Tx_State == 1) + { + if (APP_Rx_length == 0) + { + USB_Tx_State = 0; + } + else + { + if (APP_Rx_length > CDC_DATA_IN_PACKET_SIZE){ + USB_Tx_ptr = APP_Rx_ptr_out; + USB_Tx_length = CDC_DATA_IN_PACKET_SIZE; + + APP_Rx_ptr_out += CDC_DATA_IN_PACKET_SIZE; + APP_Rx_length -= CDC_DATA_IN_PACKET_SIZE; + } + else + { + USB_Tx_ptr = APP_Rx_ptr_out; + USB_Tx_length = APP_Rx_length; + + APP_Rx_ptr_out += APP_Rx_length; + APP_Rx_length = 0; + } + + /* Prepare the available data buffer to be sent on IN endpoint */ + DCD_EP_Tx (pdev, + CDC_IN_EP, + (uint8_t*)&APP_Rx_Buffer[USB_Tx_ptr], + USB_Tx_length); + } + } + + return USBD_OK; +} + +/** + * @brief usbd_cdc_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t usbd_cdc_DataOut (void *pdev, uint8_t epnum) +{ + uint16_t USB_Rx_Cnt; + + /* Get the received data buffer and update the counter */ + USB_Rx_Cnt = ((USB_OTG_CORE_HANDLE*)pdev)->dev.out_ep[epnum].xfer_count; + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + APP_FOPS.pIf_DataRx(USB_Rx_Buffer, USB_Rx_Cnt); + + /* Prepare Out endpoint to receive next packet */ + DCD_EP_PrepareRx(pdev, + CDC_OUT_EP, + (uint8_t*)(USB_Rx_Buffer), + CDC_DATA_OUT_PACKET_SIZE); + + return USBD_OK; +} + +/** + * @brief usbd_audio_SOF + * Start Of Frame event management + * @param pdev: instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t usbd_cdc_SOF (void *pdev) +{ + static uint32_t FrameCount = 0; + + if (FrameCount++ == CDC_IN_FRAME_INTERVAL) + { + /* Reset the frame counter */ + FrameCount = 0; + + /* Check the data to be sent through IN pipe */ + Handle_USBAsynchXfer(pdev); + } + + return USBD_OK; +} + +/** + * @brief Handle_USBAsynchXfer + * Send data to USB + * @param pdev: instance + * @retval None + */ +static void Handle_USBAsynchXfer (void *pdev) +{ + uint16_t USB_Tx_ptr; + uint16_t USB_Tx_length; + + if(USB_Tx_State != 1) + { + if (APP_Rx_ptr_out == APP_RX_DATA_SIZE) + { + APP_Rx_ptr_out = 0; + } + + if(APP_Rx_ptr_out == APP_Rx_ptr_in) + { + USB_Tx_State = 0; + return; + } + + if(APP_Rx_ptr_out > APP_Rx_ptr_in) /* rollback */ + { + APP_Rx_length = APP_RX_DATA_SIZE - APP_Rx_ptr_out; + + } + else + { + APP_Rx_length = APP_Rx_ptr_in - APP_Rx_ptr_out; + + } +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + APP_Rx_length &= ~0x03; +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ + + if (APP_Rx_length > CDC_DATA_IN_PACKET_SIZE) + { + USB_Tx_ptr = APP_Rx_ptr_out; + USB_Tx_length = CDC_DATA_IN_PACKET_SIZE; + + APP_Rx_ptr_out += CDC_DATA_IN_PACKET_SIZE; + APP_Rx_length -= CDC_DATA_IN_PACKET_SIZE; + } + else + { + USB_Tx_ptr = APP_Rx_ptr_out; + USB_Tx_length = APP_Rx_length; + + APP_Rx_ptr_out += APP_Rx_length; + APP_Rx_length = 0; + } + USB_Tx_State = 1; + + DCD_EP_Tx (pdev, + CDC_IN_EP, + (uint8_t*)&APP_Rx_Buffer[USB_Tx_ptr], + USB_Tx_length); + } + +} + +/** + * @brief USBD_cdc_GetCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_cdc_GetCfgDesc (uint8_t speed, uint16_t *length) +{ + *length = sizeof (usbd_cdc_CfgDesc); + return usbd_cdc_CfgDesc; +} + +/** + * @brief USBD_cdc_GetCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +#ifdef USE_USB_OTG_HS +static uint8_t *USBD_cdc_GetOtherCfgDesc (uint8_t speed, uint16_t *length) +{ + *length = sizeof (usbd_cdc_OtherCfgDesc); + return usbd_cdc_OtherCfgDesc; +} +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_cdc_core.h b/stm/lib/usbd_cdc_core.h new file mode 100644 index 000000000..4fd1d6aaa --- /dev/null +++ b/stm/lib/usbd_cdc_core.h @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * @file usbd_cdc_core.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header file for the usbd_cdc_core.c file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#ifndef __USB_CDC_CORE_H_ +#define __USB_CDC_CORE_H_ + +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_cdc + * @brief This file is the Header file for USBD_cdc.c + * @{ + */ + + +/** @defgroup usbd_cdc_Exported_Defines + * @{ + */ +#define USB_CDC_CONFIG_DESC_SIZ (67) +#define USB_CDC_DESC_SIZ (67-9) + +#define CDC_DESCRIPTOR_TYPE 0x21 + +#define DEVICE_CLASS_CDC 0x02 +#define DEVICE_SUBCLASS_CDC 0x00 + + +#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 +#define USB_STRING_DESCRIPTOR_TYPE 0x03 +#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 + +#define STANDARD_ENDPOINT_DESC_SIZE 0x09 + +#define CDC_DATA_IN_PACKET_SIZE CDC_DATA_MAX_PACKET_SIZE + +#define CDC_DATA_OUT_PACKET_SIZE CDC_DATA_MAX_PACKET_SIZE + +/*---------------------------------------------------------------------*/ +/* CDC definitions */ +/*---------------------------------------------------------------------*/ + +/**************************************************/ +/* CDC Requests */ +/**************************************************/ +#define SEND_ENCAPSULATED_COMMAND 0x00 +#define GET_ENCAPSULATED_RESPONSE 0x01 +#define SET_COMM_FEATURE 0x02 +#define GET_COMM_FEATURE 0x03 +#define CLEAR_COMM_FEATURE 0x04 +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 +#define SEND_BREAK 0x23 +#define NO_CMD 0xFF + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ +typedef struct _CDC_IF_PROP +{ + uint16_t (*pIf_Init) (void); + uint16_t (*pIf_DeInit) (void); + uint16_t (*pIf_Ctrl) (uint32_t Cmd, uint8_t* Buf, uint32_t Len); + uint16_t (*pIf_DataTx) (uint8_t* Buf, uint32_t Len); + uint16_t (*pIf_DataRx) (uint8_t* Buf, uint32_t Len); +} +CDC_IF_Prop_TypeDef; +/** + * @} + */ + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_Class_cb_TypeDef USBD_CDC_cb; +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +/** + * @} + */ + +#endif // __USB_CDC_CORE_H_ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_cdc_vcp.c b/stm/lib/usbd_cdc_vcp.c new file mode 100644 index 000000000..b8e2af2b5 --- /dev/null +++ b/stm/lib/usbd_cdc_vcp.c @@ -0,0 +1,219 @@ +/** + ****************************************************************************** + * @file usbd_cdc_vcp.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief Generic media access Layer. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED +#pragma data_alignment = 4 +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_vcp.h" +#include "usbd_cdc_conf.h" +#include "std.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +LINE_CODING linecoding = + { + 115200, /* baud rate*/ + 0x00, /* stop bits-1*/ + 0x00, /* parity - none*/ + 0x08 /* nb. of bits 8*/ + }; + + +/* These are external variables imported from CDC core to be used for IN + transfer management. */ +extern uint8_t APP_Rx_Buffer []; /* Write CDC received data in this buffer. + These data will be sent over USB IN endpoint + in the CDC core functions. */ +extern uint32_t APP_Rx_ptr_in; /* Increment this pointer or roll it back to + start address when writing received data + in the buffer APP_Rx_Buffer. */ + +/* Private function prototypes -----------------------------------------------*/ +static uint16_t VCP_Init (void); +static uint16_t VCP_DeInit (void); +static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len); +static uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len); +static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len); + +CDC_IF_Prop_TypeDef VCP_fops = +{ + VCP_Init, + VCP_DeInit, + VCP_Ctrl, + VCP_DataTx, + VCP_DataRx +}; + +/* Private functions ---------------------------------------------------------*/ +/** + * @brief VCP_Init + * Initializes the Media on the STM32 + * @param None + * @retval Result of the opeartion (USBD_OK in all cases) + */ +static uint16_t VCP_Init(void) { + return USBD_OK; +} + +/** + * @brief VCP_DeInit + * DeInitializes the Media on the STM32 + * @param None + * @retval Result of the opeartion (USBD_OK in all cases) + */ +static uint16_t VCP_DeInit(void) +{ + + return USBD_OK; +} + + +/** + * @brief VCP_Ctrl + * Manage the CDC class requests + * @param Cmd: Command code + * @param Buf: Buffer containing command data (request parameters) + * @param Len: Number of data to be sent (in bytes) + * @retval Result of the opeartion (USBD_OK in all cases) + */ +static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len) +{ + switch (Cmd) + { + case SEND_ENCAPSULATED_COMMAND: + /* Not needed for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* Not needed for this driver */ + break; + + case SET_COMM_FEATURE: + /* Not needed for this driver */ + break; + + case GET_COMM_FEATURE: + /* Not needed for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* Not needed for this driver */ + break; + + case SET_LINE_CODING: + /* + linecoding.bitrate = (uint32_t)(Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24)); + linecoding.format = Buf[4]; + linecoding.paritytype = Buf[5]; + linecoding.datatype = Buf[6]; + // Set the new configuration + VCP_COMConfig(OTHER_CONFIG); + */ + break; + + case GET_LINE_CODING: + /* + Buf[0] = (uint8_t)(linecoding.bitrate); + Buf[1] = (uint8_t)(linecoding.bitrate >> 8); + Buf[2] = (uint8_t)(linecoding.bitrate >> 16); + Buf[3] = (uint8_t)(linecoding.bitrate >> 24); + Buf[4] = linecoding.format; + Buf[5] = linecoding.paritytype; + Buf[6] = linecoding.datatype; + */ + Buf[0] = 0; + Buf[1] = 0; + Buf[2] = 0; + Buf[3] = 0; + Buf[4] = 0; + Buf[5] = 0; + Buf[6] = 0; + break; + + case SET_CONTROL_LINE_STATE: + /* Not needed for this driver */ + break; + + case SEND_BREAK: + /* Not needed for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +/** + * @brief VCP_DataTx + * CDC received data to be send over USB IN endpoint are managed in + * this function. + * @param Buf: Buffer of data to be sent + * @param Len: Number of data to be sent (in bytes) + * @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL + */ +static uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len) +{ + for (int i = 0; i < Len; i++) { + APP_Rx_Buffer[APP_Rx_ptr_in] = Buf[i]; + APP_Rx_ptr_in++; + + /* To avoid buffer overflow */ + if(APP_Rx_ptr_in == APP_RX_DATA_SIZE) { + APP_Rx_ptr_in = 0; + } + } + + return USBD_OK; +} + +/** + * @brief VCP_DataRx + * Data received over USB OUT endpoint are sent over CDC interface + * through this function. + * + * @note + * This function will block any OUT packet reception on USB endpoint + * untill exiting this function. If you exit this function before transfer + * is complete on CDC interface (ie. using DMA controller) it will result + * in receiving more data while previous ones are still not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL + */ +static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len) { + printf("%.*s", (int)Len, Buf); + return USBD_OK; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_cdc_vcp.h b/stm/lib/usbd_cdc_vcp.h new file mode 100644 index 000000000..a80e287fa --- /dev/null +++ b/stm/lib/usbd_cdc_vcp.h @@ -0,0 +1,52 @@ +/** + ****************************************************************************** + * @file usbd_cdc_vcp.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief Header for usbd_cdc_vcp.c file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CDC_VCP_H +#define __USBD_CDC_VCP_H + +#include "usbd_cdc_core.h" +#include "usbd_conf.h" + +/* Exported typef ------------------------------------------------------------*/ +/* The following structures groups all needed parameters to be configured for the + ComPort. These parameters can modified on the fly by the host through CDC class + command class requests. */ +typedef struct +{ + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; +} LINE_CODING; + +#define DEFAULT_CONFIG 0 +#define OTHER_CONFIG 1 + +#endif /* __USBD_CDC_VCP_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_conf.h b/stm/lib/usbd_conf.h new file mode 100644 index 000000000..de5d25038 --- /dev/null +++ b/stm/lib/usbd_conf.h @@ -0,0 +1,7 @@ +#ifndef __USBD_CONF__H__ +#define __USBD_CONF__H__ + +#define USBD_CFG_MAX_NUM 1 // TODO need more than 1? +#define USBD_ITF_MAX_NUM 1 // TODO need more than 1? + +#endif //__USBD_CONF__H__ diff --git a/stm/lib/usbd_core.c b/stm/lib/usbd_core.c new file mode 100644 index 000000000..fa647eb0f --- /dev/null +++ b/stm/lib/usbd_core.c @@ -0,0 +1,506 @@ +/** + ****************************************************************************** + * @file usbd_core.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides all the USBD core functions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" +#include "usbd_req.h" +#include "usbd_ioreq.h" +#include "usb_dcd_int.h" +#include "usb_bsp.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY +* @{ +*/ + + +/** @defgroup USBD_CORE +* @brief usbd core module +* @{ +*/ + +/** @defgroup USBD_CORE_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBD_CORE_Private_Defines +* @{ +*/ + +/** +* @} +*/ + + +/** @defgroup USBD_CORE_Private_Macros +* @{ +*/ +/** +* @} +*/ + + + + +/** @defgroup USBD_CORE_Private_FunctionPrototypes +* @{ +*/ +static uint8_t USBD_SetupStage(USB_OTG_CORE_HANDLE *pdev); +static uint8_t USBD_DataOutStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum); +static uint8_t USBD_DataInStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum); +static uint8_t USBD_SOF(USB_OTG_CORE_HANDLE *pdev); +static uint8_t USBD_Reset(USB_OTG_CORE_HANDLE *pdev); +static uint8_t USBD_Suspend(USB_OTG_CORE_HANDLE *pdev); +static uint8_t USBD_Resume(USB_OTG_CORE_HANDLE *pdev); +#ifdef VBUS_SENSING_ENABLED +static uint8_t USBD_DevConnected(USB_OTG_CORE_HANDLE *pdev); +static uint8_t USBD_DevDisconnected(USB_OTG_CORE_HANDLE *pdev); +#endif +static uint8_t USBD_IsoINIncomplete(USB_OTG_CORE_HANDLE *pdev); +static uint8_t USBD_IsoOUTIncomplete(USB_OTG_CORE_HANDLE *pdev); +static uint8_t USBD_RunTestMode (USB_OTG_CORE_HANDLE *pdev) ; +/** +* @} +*/ + +/** @defgroup USBD_CORE_Private_Variables +* @{ +*/ + +__IO USB_OTG_DCTL_TypeDef SET_TEST_MODE; + +USBD_DCD_INT_cb_TypeDef USBD_DCD_INT_cb = +{ + USBD_DataOutStage, + USBD_DataInStage, + USBD_SetupStage, + USBD_SOF, + USBD_Reset, + USBD_Suspend, + USBD_Resume, + USBD_IsoINIncomplete, + USBD_IsoOUTIncomplete, +#ifdef VBUS_SENSING_ENABLED +USBD_DevConnected, +USBD_DevDisconnected, +#endif +}; + +USBD_DCD_INT_cb_TypeDef *USBD_DCD_INT_fops = &USBD_DCD_INT_cb; +/** +* @} +*/ + +/** @defgroup USBD_CORE_Private_Functions +* @{ +*/ + +/** +* @brief USBD_Init +* Initailizes the device stack and load the class driver +* @param pdev: device instance +* @param core_address: USB OTG core ID +* @param class_cb: Class callback structure address +* @param usr_cb: User callback structure address +* @retval None +*/ +void USBD_Init(USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID, + USBD_DEVICE *pDevice, + USBD_Class_cb_TypeDef *class_cb, + USBD_Usr_cb_TypeDef *usr_cb) +{ + /* Hardware Init */ + USB_OTG_BSP_Init(pdev); + + USBD_DeInit(pdev); + + /*Register class and user callbacks */ + pdev->dev.class_cb = class_cb; + pdev->dev.usr_cb = usr_cb; + pdev->dev.usr_device = pDevice; + + /* set USB OTG core params */ + DCD_Init(pdev , coreID); + + /* Upon Init call usr callback */ + pdev->dev.usr_cb->Init(); + + /* Enable Interrupts */ + USB_OTG_BSP_EnableInterrupt(pdev); +} + +/** +* @brief USBD_DeInit +* Re-Initialize th device library +* @param pdev: device instance +* @retval status: status +*/ +USBD_Status USBD_DeInit(USB_OTG_CORE_HANDLE *pdev) +{ + /* Software Init */ + + return USBD_OK; +} + +/** +* @brief USBD_SetupStage +* Handle the setup stage +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_SetupStage(USB_OTG_CORE_HANDLE *pdev) +{ + USB_SETUP_REQ req; + + USBD_ParseSetupRequest(pdev , &req); + + switch (req.bmRequest & 0x1F) + { + case USB_REQ_RECIPIENT_DEVICE: + USBD_StdDevReq (pdev, &req); + break; + + case USB_REQ_RECIPIENT_INTERFACE: + USBD_StdItfReq(pdev, &req); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + USBD_StdEPReq(pdev, &req); + break; + + default: + DCD_EP_Stall(pdev , req.bmRequest & 0x80); + break; + } + return USBD_OK; +} + +/** +* @brief USBD_DataOutStage +* Handle data out stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +static uint8_t USBD_DataOutStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum) +{ + USB_OTG_EP *ep; + + if(epnum == 0) + { + ep = &pdev->dev.out_ep[0]; + if ( pdev->dev.device_state == USB_OTG_EP0_DATA_OUT) + { + if(ep->rem_data_len > ep->maxpacket) + { + ep->rem_data_len -= ep->maxpacket; + + if(pdev->cfg.dma_enable == 1) + { + /* in slave mode this, is handled by the RxSTSQLvl ISR */ + ep->xfer_buff += ep->maxpacket; + } + USBD_CtlContinueRx (pdev, + ep->xfer_buff, + MIN(ep->rem_data_len ,ep->maxpacket)); + } + else + { + if((pdev->dev.class_cb->EP0_RxReady != NULL)&& + (pdev->dev.device_status == USB_OTG_CONFIGURED)) + { + pdev->dev.class_cb->EP0_RxReady(pdev); + } + USBD_CtlSendStatus(pdev); + } + } + } + else if((pdev->dev.class_cb->DataOut != NULL)&& + (pdev->dev.device_status == USB_OTG_CONFIGURED)) + { + pdev->dev.class_cb->DataOut(pdev, epnum); + } + return USBD_OK; +} + +/** +* @brief USBD_DataInStage +* Handle data in stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +static uint8_t USBD_DataInStage(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum) +{ + USB_OTG_EP *ep; + + if(epnum == 0) + { + ep = &pdev->dev.in_ep[0]; + if ( pdev->dev.device_state == USB_OTG_EP0_DATA_IN) + { + if(ep->rem_data_len > ep->maxpacket) + { + ep->rem_data_len -= ep->maxpacket; + if(pdev->cfg.dma_enable == 1) + { + /* in slave mode this, is handled by the TxFifoEmpty ISR */ + ep->xfer_buff += ep->maxpacket; + } + USBD_CtlContinueSendData (pdev, + ep->xfer_buff, + ep->rem_data_len); + } + else + { /* last packet is MPS multiple, so send ZLP packet */ + if((ep->total_data_len % ep->maxpacket == 0) && + (ep->total_data_len >= ep->maxpacket) && + (ep->total_data_len < ep->ctl_data_len )) + { + + USBD_CtlContinueSendData(pdev , NULL, 0); + ep->ctl_data_len = 0; + } + else + { + if((pdev->dev.class_cb->EP0_TxSent != NULL)&& + (pdev->dev.device_status == USB_OTG_CONFIGURED)) + { + pdev->dev.class_cb->EP0_TxSent(pdev); + } + USBD_CtlReceiveStatus(pdev); + } + } + } + if (pdev->dev.test_mode == 1) + { + USBD_RunTestMode(pdev); + pdev->dev.test_mode = 0; + } + } + else if((pdev->dev.class_cb->DataIn != NULL)&& + (pdev->dev.device_status == USB_OTG_CONFIGURED)) + { + pdev->dev.class_cb->DataIn(pdev, epnum); + } + return USBD_OK; +} + + + + +/** +* @brief USBD_RunTestMode +* Launch test mode process +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_RunTestMode (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, SET_TEST_MODE.d32); + return USBD_OK; +} + +/** +* @brief USBD_Reset +* Handle Reset event +* @param pdev: device instance +* @retval status +*/ + +static uint8_t USBD_Reset(USB_OTG_CORE_HANDLE *pdev) +{ + /* Open EP0 OUT */ + DCD_EP_Open(pdev, + 0x00, + USB_OTG_MAX_EP0_SIZE, + EP_TYPE_CTRL); + + /* Open EP0 IN */ + DCD_EP_Open(pdev, + 0x80, + USB_OTG_MAX_EP0_SIZE, + EP_TYPE_CTRL); + + /* Upon Reset call usr call back */ + pdev->dev.device_status = USB_OTG_DEFAULT; + pdev->dev.usr_cb->DeviceReset(pdev->cfg.speed); + + return USBD_OK; +} + +/** +* @brief USBD_Resume +* Handle Resume event +* @param pdev: device instance +* @retval status +*/ + +static uint8_t USBD_Resume(USB_OTG_CORE_HANDLE *pdev) +{ + /* Upon Resume call usr call back */ + pdev->dev.usr_cb->DeviceResumed(); + pdev->dev.device_status = pdev->dev.device_old_status; + pdev->dev.device_status = USB_OTG_CONFIGURED; + return USBD_OK; +} + + +/** +* @brief USBD_Suspend +* Handle Suspend event +* @param pdev: device instance +* @retval status +*/ + +static uint8_t USBD_Suspend(USB_OTG_CORE_HANDLE *pdev) +{ + pdev->dev.device_old_status = pdev->dev.device_status; + pdev->dev.device_status = USB_OTG_SUSPENDED; + /* Upon Resume call usr call back */ + pdev->dev.usr_cb->DeviceSuspended(); + return USBD_OK; +} + + +/** +* @brief USBD_SOF +* Handle SOF event +* @param pdev: device instance +* @retval status +*/ + +static uint8_t USBD_SOF(USB_OTG_CORE_HANDLE *pdev) +{ + if(pdev->dev.class_cb->SOF) + { + pdev->dev.class_cb->SOF(pdev); + } + return USBD_OK; +} +/** +* @brief USBD_SetCfg +* Configure device and start the interface +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status +*/ + +USBD_Status USBD_SetCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx) +{ + pdev->dev.class_cb->Init(pdev, cfgidx); + + /* Upon set config call usr call back */ + pdev->dev.usr_cb->DeviceConfigured(); + return USBD_OK; +} + +/** +* @brief USBD_ClrCfg +* Clear current configuration +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status: USBD_Status +*/ +USBD_Status USBD_ClrCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx) +{ + pdev->dev.class_cb->DeInit(pdev, cfgidx); + return USBD_OK; +} + +/** +* @brief USBD_IsoINIncomplete +* Handle iso in incomplete event +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_IsoINIncomplete(USB_OTG_CORE_HANDLE *pdev) +{ + pdev->dev.class_cb->IsoINIncomplete(pdev); + return USBD_OK; +} + +/** +* @brief USBD_IsoOUTIncomplete +* Handle iso out incomplete event +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_IsoOUTIncomplete(USB_OTG_CORE_HANDLE *pdev) +{ + pdev->dev.class_cb->IsoOUTIncomplete(pdev); + return USBD_OK; +} + +#ifdef VBUS_SENSING_ENABLED +/** +* @brief USBD_DevConnected +* Handle device connection event +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_DevConnected(USB_OTG_CORE_HANDLE *pdev) +{ + pdev->dev.usr_cb->DeviceConnected(); + pdev->dev.connection_status = 1; + return USBD_OK; +} + +/** +* @brief USBD_DevDisconnected +* Handle device disconnection event +* @param pdev: device instance +* @retval status +*/ +static uint8_t USBD_DevDisconnected(USB_OTG_CORE_HANDLE *pdev) +{ + pdev->dev.usr_cb->DeviceDisconnected(); + pdev->dev.class_cb->DeInit(pdev, 0); + pdev->dev.connection_status = 0; + return USBD_OK; +} +#endif +/** +* @} +*/ + + +/** +* @} +*/ + + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_core.h b/stm/lib/usbd_core.h new file mode 100644 index 000000000..60d185b78 --- /dev/null +++ b/stm/lib/usbd_core.h @@ -0,0 +1,120 @@ +/** + ****************************************************************************** + * @file usbd_core.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief Header file for usbd_core.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +/* Includes ------------------------------------------------------------------*/ +#include "usb_dcd.h" +#include "usbd_def.h" +//#include "usbd_conf.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CORE + * @brief This file is the Header file for usbd_core.c file + * @{ + */ + + +/** @defgroup USBD_CORE_Exported_Defines + * @{ + */ + +typedef enum { + USBD_OK = 0, + USBD_BUSY, + USBD_FAIL, +}USBD_Status; +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_FunctionsPrototype + * @{ + */ +void USBD_Init(USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID, + USBD_DEVICE *pDevice, + USBD_Class_cb_TypeDef *class_cb, + USBD_Usr_cb_TypeDef *usr_cb); + +USBD_Status USBD_DeInit(USB_OTG_CORE_HANDLE *pdev); + +USBD_Status USBD_ClrCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx); + +USBD_Status USBD_SetCfg(USB_OTG_CORE_HANDLE *pdev, uint8_t cfgidx); + +/** + * @} + */ + +#endif /* __USBD_CORE_H */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/stm/lib/usbd_def.h b/stm/lib/usbd_def.h new file mode 100644 index 000000000..bdf72d249 --- /dev/null +++ b/stm/lib/usbd_def.h @@ -0,0 +1,157 @@ +/** + ****************************************************************************** + * @file usbd_def.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief general defines for the usb device library + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __USBD_DEF_H +#define __USBD_DEF_H + +/* Includes ------------------------------------------------------------------*/ +//#include "usbd_conf.h" +#define USB_MAX_STR_DESC_SIZ 255 + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_DEF + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_DEF_Exported_Defines + * @{ + */ + +#ifndef NULL +#define NULL 0 +#endif + +#define USB_LEN_DEV_QUALIFIER_DESC 0x0A +#define USB_LEN_DEV_DESC 0x12 +#define USB_LEN_CFG_DESC 0x09 +#define USB_LEN_IF_DESC 0x09 +#define USB_LEN_EP_DESC 0x07 +#define USB_LEN_OTG_DESC 0x03 + +#define USBD_IDX_LANGID_STR 0x00 +#define USBD_IDX_MFC_STR 0x01 +#define USBD_IDX_PRODUCT_STR 0x02 +#define USBD_IDX_SERIAL_STR 0x03 +#define USBD_IDX_CONFIG_STR 0x04 +#define USBD_IDX_INTERFACE_STR 0x05 + +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_MASK 0x60 + +#define USB_REQ_RECIPIENT_DEVICE 0x00 +#define USB_REQ_RECIPIENT_INTERFACE 0x01 +#define USB_REQ_RECIPIENT_ENDPOINT 0x02 +#define USB_REQ_RECIPIENT_MASK 0x03 + +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +#define USB_DESC_TYPE_DEVICE 1 +#define USB_DESC_TYPE_CONFIGURATION 2 +#define USB_DESC_TYPE_STRING 3 +#define USB_DESC_TYPE_INTERFACE 4 +#define USB_DESC_TYPE_ENDPOINT 5 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 6 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 + + +#define USB_CONFIG_REMOTE_WAKEUP 2 +#define USB_CONFIG_SELF_POWERED 1 + +#define USB_FEATURE_EP_HALT 0 +#define USB_FEATURE_REMOTE_WAKEUP 1 +#define USB_FEATURE_TEST_MODE 2 + +/** + * @} + */ + + +/** @defgroup USBD_DEF_Exported_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_DEF_Exported_Macros + * @{ + */ +#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) + +#define LOBYTE(x) ((uint8_t)(x & 0x00FF)) +#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8)) +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_FunctionsPrototype + * @{ + */ + +/** + * @} + */ + +#endif /* __USBD_DEF_H */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_desc.c b/stm/lib/usbd_desc.c new file mode 100644 index 000000000..da68679d1 --- /dev/null +++ b/stm/lib/usbd_desc.c @@ -0,0 +1,317 @@ +/** + ****************************************************************************** + * @file usbd_desc.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides the USBD descriptors and string formating method. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_req.h" +#include "usb_regs.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_DESC + * @brief USBD descriptors module + * @{ + */ + +/** @defgroup USBD_DESC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Defines + * @{ + */ +#define USBD_VID 0x0483 // TODO set VID + +#define USBD_PID 0x5720 // TODO set PID + +/** @defgroup USB_String_Descriptors + * @{ + */ +#define USBD_LANGID_STRING 0x409 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" // TODO set +#define USBD_PRODUCT_HS_STRING "VCP/MSC in HS Mode" // TODO set +#define USBD_SERIALNUMBER_HS_STRING "00000000001A" // TODO set +#define USBD_PRODUCT_FS_STRING "VCP/MSC in FS Mode" // TODO set +#define USBD_SERIALNUMBER_FS_STRING "00000000001B" // TODO set +#define USBD_CONFIGURATION_HS_STRING "VCP/MSC Config" // TODO set +#define USBD_INTERFACE_HS_STRING "VCP/MSC Interface" // TODO set +#define USBD_CONFIGURATION_FS_STRING "VCP/MSC Config" // TODO set +#define USBD_INTERFACE_FS_STRING "VCP/MSC Interface" // TODO set +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Variables + * @{ + */ + +USBD_DEVICE USR_desc = +{ + USBD_USR_DeviceDescriptor, + USBD_USR_LangIDStrDescriptor, + USBD_USR_ManufacturerStrDescriptor, + USBD_USR_ProductStrDescriptor, + USBD_USR_SerialStrDescriptor, + USBD_USR_ConfigStrDescriptor, + USBD_USR_InterfaceStrDescriptor, + +}; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_DeviceDesc[USB_SIZ_DEVICE_DESC] __ALIGN_END = + { + 0x12, /*bLength */ + USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/ + 0x00, /*bcdUSB */ + 0x02, + 0x00, /*bDeviceClass*/ + 0x00, /*bDeviceSubClass*/ + 0x00, /*bDeviceProtocol*/ + USB_OTG_MAX_EP0_SIZE, /*bMaxPacketSize*/ + LOBYTE(USBD_VID), /*idVendor*/ + HIBYTE(USBD_VID), /*idVendor*/ + LOBYTE(USBD_PID), /*idVendor*/ + HIBYTE(USBD_PID), /*idVendor*/ + 0x00, /*bcdDevice rel. 2.00*/ + 0x02, + USBD_IDX_MFC_STR, /*Index of manufacturer string*/ + USBD_IDX_PRODUCT_STR, /*Index of product string*/ + USBD_IDX_SERIAL_STR, /*Index of serial number string*/ + USBD_CFG_MAX_NUM /*bNumConfigurations*/ + } ; /* USB_DeviceDescriptor */ + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = +{ + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID] __ALIGN_END = +{ + USB_SIZ_STRING_LANGID, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING), +}; +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Functions + * @{ + */ + +/** +* @brief USBD_USR_DeviceDescriptor +* return the device descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length) +{ + *length = sizeof(USBD_DeviceDesc); + return USBD_DeviceDesc; +} + +/** +* @brief USBD_USR_LangIDStrDescriptor +* return the LangID string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length) +{ + *length = sizeof(USBD_LangIDDesc); + return USBD_LangIDDesc; +} + + +/** +* @brief USBD_USR_ProductStrDescriptor +* return the product string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_ProductStrDescriptor( uint8_t speed , uint16_t *length) +{ + + + if(speed == 0) + { + USBD_GetString (USBD_PRODUCT_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_PRODUCT_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** +* @brief USBD_USR_ManufacturerStrDescriptor +* return the manufacturer string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_ManufacturerStrDescriptor( uint8_t speed , uint16_t *length) +{ + USBD_GetString (USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** +* @brief USBD_USR_SerialStrDescriptor +* return the serial number string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length) +{ + if(speed == USB_OTG_SPEED_HIGH) + { + USBD_GetString (USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** +* @brief USBD_USR_ConfigStrDescriptor +* return the configuration string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length) +{ + if(speed == USB_OTG_SPEED_HIGH) + { + USBD_GetString (USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + + +/** +* @brief USBD_USR_InterfaceStrDescriptor +* return the interface string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString (USBD_INTERFACE_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_INTERFACE_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_desc.h b/stm/lib/usbd_desc.h new file mode 100644 index 000000000..e28e14ae0 --- /dev/null +++ b/stm/lib/usbd_desc.h @@ -0,0 +1,120 @@ +/** + ****************************************************************************** + * @file usbd_desc.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header file for the usbd_desc.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __USB_DESC_H +#define __USB_DESC_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_DESC + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_DESC_Exported_Defines + * @{ + */ +#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 +#define USB_STRING_DESCRIPTOR_TYPE 0x03 +#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 +#define USB_SIZ_DEVICE_DESC 18 +#define USB_SIZ_STRING_LANGID 4 + +/** + * @} + */ + + +/** @defgroup USBD_DESC_Exported_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_DESC_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_Variables + * @{ + */ +extern uint8_t USBD_DeviceDesc [USB_SIZ_DEVICE_DESC]; +extern uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ]; +extern uint8_t USBD_OtherSpeedCfgDesc[USB_LEN_CFG_DESC]; +extern uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC]; +extern uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID]; +extern USBD_DEVICE USR_desc; +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_FunctionsPrototype + * @{ + */ + + +uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_ManufacturerStrDescriptor ( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_ProductStrDescriptor ( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length); + +#ifdef USB_SUPPORT_USER_STRING_DESC +uint8_t * USBD_USR_USRStringDesc (uint8_t speed, uint8_t idx , uint16_t *length); +#endif /* USB_SUPPORT_USER_STRING_DESC */ + +/** + * @} + */ + +#endif /* __USBD_DESC_H */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_ioreq.c b/stm/lib/usbd_ioreq.c new file mode 100644 index 000000000..a9e4a8636 --- /dev/null +++ b/stm/lib/usbd_ioreq.c @@ -0,0 +1,244 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides the IO requests APIs for control endpoints. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_IOREQ + * @brief control I/O requests module + * @{ + */ + +/** @defgroup USBD_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Functions + * @{ + */ + +/** +* @brief USBD_CtlSendData +* send data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be sent +* @retval status +*/ +USBD_Status USBD_CtlSendData (USB_OTG_CORE_HANDLE *pdev, + uint8_t *pbuf, + uint16_t len) +{ + USBD_Status ret = USBD_OK; + + pdev->dev.in_ep[0].total_data_len = len; + pdev->dev.in_ep[0].rem_data_len = len; + pdev->dev.device_state = USB_OTG_EP0_DATA_IN; + + DCD_EP_Tx (pdev, 0, pbuf, len); + + return ret; +} + +/** +* @brief USBD_CtlContinueSendData +* continue sending data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be sent +* @retval status +*/ +USBD_Status USBD_CtlContinueSendData (USB_OTG_CORE_HANDLE *pdev, + uint8_t *pbuf, + uint16_t len) +{ + USBD_Status ret = USBD_OK; + + DCD_EP_Tx (pdev, 0, pbuf, len); + + + return ret; +} + +/** +* @brief USBD_CtlPrepareRx +* receive data on the ctl pipe +* @param pdev: USB OTG device instance +* @param buff: pointer to data buffer +* @param len: length of data to be received +* @retval status +*/ +USBD_Status USBD_CtlPrepareRx (USB_OTG_CORE_HANDLE *pdev, + uint8_t *pbuf, + uint16_t len) +{ + USBD_Status ret = USBD_OK; + + pdev->dev.out_ep[0].total_data_len = len; + pdev->dev.out_ep[0].rem_data_len = len; + pdev->dev.device_state = USB_OTG_EP0_DATA_OUT; + + DCD_EP_PrepareRx (pdev, + 0, + pbuf, + len); + + + return ret; +} + +/** +* @brief USBD_CtlContinueRx +* continue receive data on the ctl pipe +* @param pdev: USB OTG device instance +* @param buff: pointer to data buffer +* @param len: length of data to be received +* @retval status +*/ +USBD_Status USBD_CtlContinueRx (USB_OTG_CORE_HANDLE *pdev, + uint8_t *pbuf, + uint16_t len) +{ + USBD_Status ret = USBD_OK; + + DCD_EP_PrepareRx (pdev, + 0, + pbuf, + len); + return ret; +} +/** +* @brief USBD_CtlSendStatus +* send zero lzngth packet on the ctl pipe +* @param pdev: USB OTG device instance +* @retval status +*/ +USBD_Status USBD_CtlSendStatus (USB_OTG_CORE_HANDLE *pdev) +{ + USBD_Status ret = USBD_OK; + pdev->dev.device_state = USB_OTG_EP0_STATUS_IN; + DCD_EP_Tx (pdev, + 0, + NULL, + 0); + + USB_OTG_EP0_OutStart(pdev); + + return ret; +} + +/** +* @brief USBD_CtlReceiveStatus +* receive zero lzngth packet on the ctl pipe +* @param pdev: USB OTG device instance +* @retval status +*/ +USBD_Status USBD_CtlReceiveStatus (USB_OTG_CORE_HANDLE *pdev) +{ + USBD_Status ret = USBD_OK; + pdev->dev.device_state = USB_OTG_EP0_STATUS_OUT; + DCD_EP_PrepareRx ( pdev, + 0, + NULL, + 0); + + USB_OTG_EP0_OutStart(pdev); + + return ret; +} + + +/** +* @brief USBD_GetRxCount +* returns the received data length +* @param pdev: USB OTG device instance +* epnum: endpoint index +* @retval Rx Data blength +*/ +uint16_t USBD_GetRxCount (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum) +{ + return pdev->dev.out_ep[epnum].xfer_count; +} + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_ioreq.h b/stm/lib/usbd_ioreq.h new file mode 100644 index 000000000..3f6aea1a9 --- /dev/null +++ b/stm/lib/usbd_ioreq.h @@ -0,0 +1,121 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header file for the usbd_ioreq.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __USBD_IOREQ_H_ +#define __USBD_IOREQ_H_ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_core.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_IOREQ + * @brief header file for the usbd_ioreq.c file + * @{ + */ + +/** @defgroup USBD_IOREQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Exported_Types + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_IOREQ_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_Status USBD_CtlSendData (USB_OTG_CORE_HANDLE *pdev, + uint8_t *buf, + uint16_t len); + +USBD_Status USBD_CtlContinueSendData (USB_OTG_CORE_HANDLE *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_Status USBD_CtlPrepareRx (USB_OTG_CORE_HANDLE *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_Status USBD_CtlContinueRx (USB_OTG_CORE_HANDLE *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_Status USBD_CtlSendStatus (USB_OTG_CORE_HANDLE *pdev); + +USBD_Status USBD_CtlReceiveStatus (USB_OTG_CORE_HANDLE *pdev); + +uint16_t USBD_GetRxCount (USB_OTG_CORE_HANDLE *pdev , + uint8_t epnum); + +/** + * @} + */ + +#endif /* __USBD_IOREQ_H_ */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_bot.c b/stm/lib/usbd_msc_bot.c new file mode 100644 index 000000000..7b8b4c580 --- /dev/null +++ b/stm/lib/usbd_msc_bot.c @@ -0,0 +1,401 @@ +/** + ****************************************************************************** + * @file usbd_msc_bot.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides all the BOT protocol core functions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_ioreq.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_conf.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_BOT + * @brief BOT protocol module + * @{ + */ + +/** @defgroup MSC_BOT_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Variables + * @{ + */ +uint16_t MSC_BOT_DataLen; +uint8_t MSC_BOT_State; +uint8_t MSC_BOT_Status; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t MSC_BOT_Data[MSC_MEDIA_PACKET] __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN MSC_BOT_CBW_TypeDef MSC_BOT_cbw __ALIGN_END ; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN MSC_BOT_CSW_TypeDef MSC_BOT_csw __ALIGN_END ; +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_FunctionPrototypes + * @{ + */ +static void MSC_BOT_CBW_Decode (USB_OTG_CORE_HANDLE *pdev); + +static void MSC_BOT_SendData (USB_OTG_CORE_HANDLE *pdev, + uint8_t* pbuf, + uint16_t len); + +static void MSC_BOT_Abort(USB_OTG_CORE_HANDLE *pdev); +/** + * @} + */ + + +/** @defgroup MSC_BOT_Private_Functions + * @{ + */ + + + +/** +* @brief MSC_BOT_Init +* Initialize the BOT Process +* @param pdev: device instance +* @retval None +*/ +void MSC_BOT_Init (USB_OTG_CORE_HANDLE *pdev) +{ + MSC_BOT_State = BOT_IDLE; + MSC_BOT_Status = BOT_STATE_NORMAL; + USBD_STORAGE_fops->Init(0); + + DCD_EP_Flush(pdev, MSC_OUT_EP); + DCD_EP_Flush(pdev, MSC_IN_EP); + /* Prapare EP to Receive First BOT Cmd */ + DCD_EP_PrepareRx (pdev, + MSC_OUT_EP, + (uint8_t *)&MSC_BOT_cbw, + BOT_CBW_LENGTH); +} + +/** +* @brief MSC_BOT_Reset +* Reset the BOT Machine +* @param pdev: device instance +* @retval None +*/ +void MSC_BOT_Reset (USB_OTG_CORE_HANDLE *pdev) +{ + MSC_BOT_State = BOT_IDLE; + MSC_BOT_Status = BOT_STATE_RECOVERY; + /* Prapare EP to Receive First BOT Cmd */ + DCD_EP_PrepareRx (pdev, + MSC_OUT_EP, + (uint8_t *)&MSC_BOT_cbw, + BOT_CBW_LENGTH); +} + +/** +* @brief MSC_BOT_DeInit +* Uninitialize the BOT Machine +* @param pdev: device instance +* @retval None +*/ +void MSC_BOT_DeInit (USB_OTG_CORE_HANDLE *pdev) +{ + MSC_BOT_State = BOT_IDLE; +} + +/** +* @brief MSC_BOT_DataIn +* Handle BOT IN data stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval None +*/ +void MSC_BOT_DataIn (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum) +{ + + switch (MSC_BOT_State) + { + case BOT_DATA_IN: + if(SCSI_ProcessCmd(pdev, + MSC_BOT_cbw.bLUN, + &MSC_BOT_cbw.CB[0]) < 0) + { + MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED); + } + break; + + case BOT_SEND_DATA: + case BOT_LAST_DATA_IN: + MSC_BOT_SendCSW (pdev, CSW_CMD_PASSED); + + break; + + default: + break; + } +} +/** +* @brief MSC_BOT_DataOut +* Proccess MSC OUT data +* @param pdev: device instance +* @param epnum: endpoint index +* @retval None +*/ +void MSC_BOT_DataOut (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum) +{ + switch (MSC_BOT_State) + { + case BOT_IDLE: + MSC_BOT_CBW_Decode(pdev); + break; + + case BOT_DATA_OUT: + + if(SCSI_ProcessCmd(pdev, + MSC_BOT_cbw.bLUN, + &MSC_BOT_cbw.CB[0]) < 0) + { + MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED); + } + + break; + + default: + break; + } + +} + +/** +* @brief MSC_BOT_CBW_Decode +* Decode the CBW command and set the BOT state machine accordingtly +* @param pdev: device instance +* @retval None +*/ +static void MSC_BOT_CBW_Decode (USB_OTG_CORE_HANDLE *pdev) +{ + + MSC_BOT_csw.dTag = MSC_BOT_cbw.dTag; + MSC_BOT_csw.dDataResidue = MSC_BOT_cbw.dDataLength; + + if ((USBD_GetRxCount (pdev ,MSC_OUT_EP) != BOT_CBW_LENGTH) || + (MSC_BOT_cbw.dSignature != BOT_CBW_SIGNATURE)|| + (MSC_BOT_cbw.bLUN > 1) || + (MSC_BOT_cbw.bCBLength < 1) || + (MSC_BOT_cbw.bCBLength > 16)) + { + + SCSI_SenseCode(MSC_BOT_cbw.bLUN, + ILLEGAL_REQUEST, + INVALID_CDB); + MSC_BOT_Status = BOT_STATE_ERROR; + MSC_BOT_Abort(pdev); + + } + else + { + if(SCSI_ProcessCmd(pdev, + MSC_BOT_cbw.bLUN, + &MSC_BOT_cbw.CB[0]) < 0) + { + MSC_BOT_Abort(pdev); + } + /*Burst xfer handled internally*/ + else if ((MSC_BOT_State != BOT_DATA_IN) && + (MSC_BOT_State != BOT_DATA_OUT) && + (MSC_BOT_State != BOT_LAST_DATA_IN)) + { + if (MSC_BOT_DataLen > 0) + { + MSC_BOT_SendData(pdev, + MSC_BOT_Data, + MSC_BOT_DataLen); + } + else if (MSC_BOT_DataLen == 0) + { + MSC_BOT_SendCSW (pdev, + CSW_CMD_PASSED); + } + } + } +} + +/** +* @brief MSC_BOT_SendData +* Send the requested data +* @param pdev: device instance +* @param buf: pointer to data buffer +* @param len: Data Length +* @retval None +*/ +static void MSC_BOT_SendData(USB_OTG_CORE_HANDLE *pdev, + uint8_t* buf, + uint16_t len) +{ + + len = MIN (MSC_BOT_cbw.dDataLength, len); + MSC_BOT_csw.dDataResidue -= len; + MSC_BOT_csw.bStatus = CSW_CMD_PASSED; + MSC_BOT_State = BOT_SEND_DATA; + + DCD_EP_Tx (pdev, MSC_IN_EP, buf, len); +} + +/** +* @brief MSC_BOT_SendCSW +* Send the Command Status Wrapper +* @param pdev: device instance +* @param status : CSW status +* @retval None +*/ +void MSC_BOT_SendCSW (USB_OTG_CORE_HANDLE *pdev, + uint8_t CSW_Status) +{ + MSC_BOT_csw.dSignature = BOT_CSW_SIGNATURE; + MSC_BOT_csw.bStatus = CSW_Status; + MSC_BOT_State = BOT_IDLE; + + DCD_EP_Tx (pdev, + MSC_IN_EP, + (uint8_t *)&MSC_BOT_csw, + BOT_CSW_LENGTH); + + /* Prapare EP to Receive next Cmd */ + DCD_EP_PrepareRx (pdev, + MSC_OUT_EP, + (uint8_t *)&MSC_BOT_cbw, + BOT_CBW_LENGTH); + +} + +/** +* @brief MSC_BOT_Abort +* Abort the current transfer +* @param pdev: device instance +* @retval status +*/ + +static void MSC_BOT_Abort (USB_OTG_CORE_HANDLE *pdev) +{ + + if ((MSC_BOT_cbw.bmFlags == 0) && + (MSC_BOT_cbw.dDataLength != 0) && + (MSC_BOT_Status == BOT_STATE_NORMAL) ) + { + DCD_EP_Stall(pdev, MSC_OUT_EP ); + } + DCD_EP_Stall(pdev, MSC_IN_EP); + + if(MSC_BOT_Status == BOT_STATE_ERROR) + { + DCD_EP_PrepareRx (pdev, + MSC_OUT_EP, + (uint8_t *)&MSC_BOT_cbw, + BOT_CBW_LENGTH); + } +} + +/** +* @brief MSC_BOT_CplClrFeature +* Complete the clear feature request +* @param pdev: device instance +* @param epnum: endpoint index +* @retval None +*/ + +void MSC_BOT_CplClrFeature (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum) +{ + if(MSC_BOT_Status == BOT_STATE_ERROR )/* Bad CBW Signature */ + { + DCD_EP_Stall(pdev, MSC_IN_EP); + MSC_BOT_Status = BOT_STATE_NORMAL; + } + else if(((epnum & 0x80) == 0x80) && ( MSC_BOT_Status != BOT_STATE_RECOVERY)) + { + MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED); + } + +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_bot.h b/stm/lib/usbd_msc_bot.h new file mode 100644 index 000000000..53c95fbe4 --- /dev/null +++ b/stm/lib/usbd_msc_bot.h @@ -0,0 +1,153 @@ +/** + ****************************************************************************** + * @file usbd_msc_bot.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header for the usbd_msc_bot.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#include "usbd_core.h" + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_BOT_H +#define __USBD_MSC_BOT_H + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup MSC_BOT + * @brief This file is the Header file for usbd_bot.c + * @{ + */ + + +/** @defgroup USBD_CORE_Exported_Defines + * @{ + */ +#define BOT_IDLE 0 /* Idle state */ +#define BOT_DATA_OUT 1 /* Data Out state */ +#define BOT_DATA_IN 2 /* Data In state */ +#define BOT_LAST_DATA_IN 3 /* Last Data In Last */ +#define BOT_SEND_DATA 4 /* Send Immediate data */ + +#define BOT_CBW_SIGNATURE 0x43425355 +#define BOT_CSW_SIGNATURE 0x53425355 +#define BOT_CBW_LENGTH 31 +#define BOT_CSW_LENGTH 13 + +/* CSW Status Definitions */ +#define CSW_CMD_PASSED 0x00 +#define CSW_CMD_FAILED 0x01 +#define CSW_PHASE_ERROR 0x02 + +/* BOT Status */ +#define BOT_STATE_NORMAL 0 +#define BOT_STATE_RECOVERY 1 +#define BOT_STATE_ERROR 2 + + +#define DIR_IN 0 +#define DIR_OUT 1 +#define BOTH_DIR 2 + +/** + * @} + */ + +/** @defgroup MSC_CORE_Private_TypesDefinitions + * @{ + */ + +typedef struct _MSC_BOT_CBW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataLength; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLength; + uint8_t CB[16]; +} +MSC_BOT_CBW_TypeDef; + + +typedef struct _MSC_BOT_CSW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; +} +MSC_BOT_CSW_TypeDef; + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_Types + * @{ + */ + +extern uint8_t MSC_BOT_Data[]; +extern uint16_t MSC_BOT_DataLen; +extern uint8_t MSC_BOT_State; +extern uint8_t MSC_BOT_BurstMode; +extern MSC_BOT_CBW_TypeDef MSC_BOT_cbw; +extern MSC_BOT_CSW_TypeDef MSC_BOT_csw; +/** + * @} + */ +/** @defgroup USBD_CORE_Exported_FunctionsPrototypes + * @{ + */ +void MSC_BOT_Init (USB_OTG_CORE_HANDLE *pdev); +void MSC_BOT_Reset (USB_OTG_CORE_HANDLE *pdev); +void MSC_BOT_DeInit (USB_OTG_CORE_HANDLE *pdev); +void MSC_BOT_DataIn (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum); + +void MSC_BOT_DataOut (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum); + +void MSC_BOT_SendCSW (USB_OTG_CORE_HANDLE *pdev, + uint8_t CSW_Status); + +void MSC_BOT_CplClrFeature (USB_OTG_CORE_HANDLE *pdev, + uint8_t epnum); +/** + * @} + */ + +#endif /* __USBD_MSC_BOT_H */ +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_msc_conf.h b/stm/lib/usbd_msc_conf.h new file mode 100644 index 000000000..2902f092f --- /dev/null +++ b/stm/lib/usbd_msc_conf.h @@ -0,0 +1,99 @@ +/** + ****************************************************************************** + * @file usbd_conf.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief USB Device configuration file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CONF__H__ +#define __USBD_CONF__H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" + +/** @defgroup USB_CONF_Exported_Defines + * @{ + */ +//#define USBD_CFG_MAX_NUM 1 +//#define USBD_ITF_MAX_NUM 1 + +//#define USBD_SELF_POWERED + +//#define USB_MAX_STR_DESC_SIZ 64 + +/* Class Layer Parameter */ + +#define MSC_IN_EP 0x81 +#define MSC_OUT_EP 0x01 +#ifdef USE_USB_OTG_HS +#ifdef USE_ULPI_PHY +#define MSC_MAX_PACKET 512 +#else +#define MSC_MAX_PACKET 64 +#endif +#else /*USE_USB_OTG_FS*/ +#define MSC_MAX_PACKET 64 +#endif + + +#define MSC_MEDIA_PACKET 4096 + +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + +#endif //__USBD_CONF__H__ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_msc_core.c b/stm/lib/usbd_msc_core.c new file mode 100644 index 000000000..da86d2721 --- /dev/null +++ b/stm/lib/usbd_msc_core.c @@ -0,0 +1,497 @@ +/** + ****************************************************************************** + * @file usbd_msc_core.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides all the MSC core functions. + * + * @verbatim + * + * =================================================================== + * MSC Class Description + * =================================================================== + * This module manages the MSC class V1.0 following the "Universal + * Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0 + * Sep. 31, 1999". + * This driver implements the following aspects of the specification: + * - Bulk-Only Transport protocol + * - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3)) + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_mem.h" +#include "usbd_msc_core.h" +#include "usbd_msc_bot.h" +#include "usbd_msc_conf.h" +#include "usbd_req.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_CORE + * @brief Mass storage core module + * @{ + */ + +/** @defgroup MSC_CORE_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_CORE_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_CORE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_CORE_Private_FunctionPrototypes + * @{ + */ +uint8_t USBD_MSC_Init (void *pdev, + uint8_t cfgidx); + +uint8_t USBD_MSC_DeInit (void *pdev, + uint8_t cfgidx); + +uint8_t USBD_MSC_Setup (void *pdev, + USB_SETUP_REQ *req); + +uint8_t USBD_MSC_DataIn (void *pdev, + uint8_t epnum); + + +uint8_t USBD_MSC_DataOut (void *pdev, + uint8_t epnum); + +uint8_t *USBD_MSC_GetCfgDesc (uint8_t speed, + uint16_t *length); + +#ifdef USB_OTG_HS_CORE +uint8_t *USBD_MSC_GetOtherCfgDesc (uint8_t speed, + uint16_t *length); +#endif + + +uint8_t USBD_MSC_CfgDesc[USB_MSC_CONFIG_DESC_SIZ]; + + + + +/** + * @} + */ + + +/** @defgroup MSC_CORE_Private_Variables + * @{ + */ + + +USBD_Class_cb_TypeDef USBD_MSC_cb = +{ + USBD_MSC_Init, + USBD_MSC_DeInit, + USBD_MSC_Setup, + NULL, /*EP0_TxSent*/ + NULL, /*EP0_RxReady*/ + USBD_MSC_DataIn, + USBD_MSC_DataOut, + NULL, /*SOF */ + NULL, + NULL, + USBD_MSC_GetCfgDesc, +#ifdef USB_OTG_HS_CORE + USBD_MSC_GetOtherCfgDesc, +#endif +}; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB Mass storage device Configuration Descriptor */ +/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ +__ALIGN_BEGIN uint8_t USBD_MSC_CfgDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_MSC_CONFIG_DESC_SIZ, + + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent*/ + 0x50, /* nInterfaceProtocol */ + 0x05, /* iInterface: */ + /******************** Mass Storage Endpoints ********************/ + 0x07, /*Endpoint descriptor length = 7*/ + 0x05, /*Endpoint descriptor type */ + MSC_IN_EP, /*Endpoint address (IN, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(MSC_MAX_PACKET), + HIBYTE(MSC_MAX_PACKET), + 0x00, /*Polling interval in milliseconds */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_OUT_EP, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + LOBYTE(MSC_MAX_PACKET), + HIBYTE(MSC_MAX_PACKET), + 0x00 /*Polling interval in milliseconds*/ +}; +#ifdef USB_OTG_HS_CORE + #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif + #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t USBD_MSC_OtherCfgDesc[USB_MSC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION, + USB_MSC_CONFIG_DESC_SIZ, + + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /******************** Mass Storage interface ********************/ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MSC Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent command set*/ + 0x50, /* nInterfaceProtocol */ + 0x05, /* iInterface: */ + /******************** Mass Storage Endpoints ********************/ + 0x07, /*Endpoint descriptor length = 7*/ + 0x05, /*Endpoint descriptor type */ + MSC_IN_EP, /*Endpoint address (IN, address 1) */ + 0x02, /*Bulk endpoint type */ + 0x40, + 0x00, + 0x00, /*Polling interval in milliseconds */ + + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + MSC_OUT_EP, /*Endpoint address (OUT, address 1) */ + 0x02, /*Bulk endpoint type */ + 0x40, + 0x00, + 0x00 /*Polling interval in milliseconds*/ +}; +#endif + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN static uint8_t USBD_MSC_MaxLun __ALIGN_END = 0; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN static uint8_t USBD_MSC_AltSet __ALIGN_END = 0; + +/** + * @} + */ + + +/** @defgroup MSC_CORE_Private_Functions + * @{ + */ + +/** +* @brief USBD_MSC_Init +* Initialize the mass storage configuration +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status +*/ +uint8_t USBD_MSC_Init (void *pdev, + uint8_t cfgidx) +{ + USBD_MSC_DeInit(pdev , cfgidx ); + + /* Open EP IN */ + DCD_EP_Open(pdev, + MSC_IN_EP, + MSC_EPIN_SIZE, + USB_OTG_EP_BULK); + + /* Open EP OUT */ + DCD_EP_Open(pdev, + MSC_OUT_EP, + MSC_EPOUT_SIZE, + USB_OTG_EP_BULK); + + /* Init the BOT layer */ + MSC_BOT_Init(pdev); + + return USBD_OK; +} + +/** +* @brief USBD_MSC_DeInit +* DeInitilaize the mass storage configuration +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status +*/ +uint8_t USBD_MSC_DeInit (void *pdev, + uint8_t cfgidx) +{ + /* Close MSC EPs */ + DCD_EP_Close (pdev , MSC_IN_EP); + DCD_EP_Close (pdev , MSC_OUT_EP); + + /* Un Init the BOT layer */ + MSC_BOT_DeInit(pdev); + return USBD_OK; +} +/** +* @brief USBD_MSC_Setup +* Handle the MSC specific requests +* @param pdev: device instance +* @param req: USB request +* @retval status +*/ +uint8_t USBD_MSC_Setup (void *pdev, USB_SETUP_REQ *req) +{ + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + + /* Class request */ + case USB_REQ_TYPE_CLASS : + switch (req->bRequest) + { + case BOT_GET_MAX_LUN : + + if((req->wValue == 0) && + (req->wLength == 1) && + ((req->bmRequest & 0x80) == 0x80)) + { + USBD_MSC_MaxLun = USBD_STORAGE_fops->GetMaxLun(); + if(USBD_MSC_MaxLun > 0) + { + USBD_CtlSendData (pdev, + &USBD_MSC_MaxLun, + 1); + } + else + { + USBD_CtlError(pdev , req); + return USBD_FAIL; + + } + } + else + { + USBD_CtlError(pdev , req); + return USBD_FAIL; + } + break; + + case BOT_RESET : + if((req->wValue == 0) && + (req->wLength == 0) && + ((req->bmRequest & 0x80) != 0x80)) + { + MSC_BOT_Reset(pdev); + } + else + { + USBD_CtlError(pdev , req); + return USBD_FAIL; + } + break; + + default: + USBD_CtlError(pdev , req); + return USBD_FAIL; + } + break; + /* Interface & Endpoint request */ + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_INTERFACE : + USBD_CtlSendData (pdev, + &USBD_MSC_AltSet, + 1); + break; + + case USB_REQ_SET_INTERFACE : + USBD_MSC_AltSet = (uint8_t)(req->wValue); + break; + + case USB_REQ_CLEAR_FEATURE: + + /* Flush the FIFO and Clear the stall status */ + DCD_EP_Flush(pdev, (uint8_t)req->wIndex); + + /* Re-activate the EP */ + DCD_EP_Close (pdev , (uint8_t)req->wIndex); + if((((uint8_t)req->wIndex) & 0x80) == 0x80) + { + DCD_EP_Open(pdev, + ((uint8_t)req->wIndex), + MSC_EPIN_SIZE, + USB_OTG_EP_BULK); + } + else + { + DCD_EP_Open(pdev, + ((uint8_t)req->wIndex), + MSC_EPOUT_SIZE, + USB_OTG_EP_BULK); + } + + /* Handle BOT error */ + MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); + break; + + } + break; + + default: + break; + } + return USBD_OK; +} + +/** +* @brief USBD_MSC_DataIn +* handle data IN Stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +uint8_t USBD_MSC_DataIn (void *pdev, + uint8_t epnum) +{ + MSC_BOT_DataIn(pdev , epnum); + return USBD_OK; +} + +/** +* @brief USBD_MSC_DataOut +* handle data OUT Stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +uint8_t USBD_MSC_DataOut (void *pdev, + uint8_t epnum) +{ + MSC_BOT_DataOut(pdev , epnum); + return USBD_OK; +} + +/** +* @brief USBD_MSC_GetCfgDesc +* return configuration descriptor +* @param speed : current device speed +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_MSC_GetCfgDesc (uint8_t speed, uint16_t *length) +{ + *length = sizeof (USBD_MSC_CfgDesc); + return USBD_MSC_CfgDesc; +} + +/** +* @brief USBD_MSC_GetOtherCfgDesc +* return other speed configuration descriptor +* @param speed : current device speed +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +#ifdef USB_OTG_HS_CORE +uint8_t *USBD_MSC_GetOtherCfgDesc (uint8_t speed, + uint16_t *length) +{ + *length = sizeof (USBD_MSC_OtherCfgDesc); + return USBD_MSC_OtherCfgDesc; +} +#endif +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_core.h b/stm/lib/usbd_msc_core.h new file mode 100644 index 000000000..1697e492c --- /dev/null +++ b/stm/lib/usbd_msc_core.h @@ -0,0 +1,77 @@ +/** + ****************************************************************************** + * @file usbd_msc_core.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header for the usbd_msc_core.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef _USB_MSC_CORE_H_ +#define _USB_MSC_CORE_H_ + +#include "usbd_ioreq.h" + +/** @addtogroup USBD_MSC_BOT + * @{ + */ + +/** @defgroup USBD_MSC + * @brief This file is the Header file for USBD_msc.c + * @{ + */ + + +/** @defgroup USBD_BOT_Exported_Defines + * @{ + */ + + +#define BOT_GET_MAX_LUN 0xFE +#define BOT_RESET 0xFF +#define USB_MSC_CONFIG_DESC_SIZ 32 + +#define MSC_EPIN_SIZE MSC_MAX_PACKET +#define MSC_EPOUT_SIZE MSC_MAX_PACKET + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Types + * @{ + */ + +extern USBD_Class_cb_TypeDef USBD_MSC_cb; +/** + * @} + */ + +/** + * @} + */ +#endif // _USB_MSC_CORE_H_ +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_data.c b/stm/lib/usbd_msc_data.c new file mode 100644 index 000000000..1dc7d22e7 --- /dev/null +++ b/stm/lib/usbd_msc_data.c @@ -0,0 +1,134 @@ +/** + ****************************************************************************** + * @file usbd_msc_data.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides all the vital inquiry pages and sense data. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_data.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_DATA + * @brief Mass storage info/data module + * @{ + */ + +/** @defgroup MSC_DATA_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Variables + * @{ + */ + + +/* USB Mass storage Page 0 Inquiry Data */ +const uint8_t MSC_Page00_Inquiry_Data[] = {//7 + 0x00, + 0x00, + 0x00, + (LENGTH_INQUIRY_PAGE00 - 4), + 0x00, + 0x80, + 0x83 +}; +/* USB Mass storage sense 6 Data */ +const uint8_t MSC_Mode_Sense6_data[] = { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; +/* USB Mass storage sense 10 Data */ +const uint8_t MSC_Mode_Sense10_data[] = { + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_DATA_Private_Functions + * @{ + */ + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_data.h b/stm/lib/usbd_msc_data.h new file mode 100644 index 000000000..7c0d13679 --- /dev/null +++ b/stm/lib/usbd_msc_data.h @@ -0,0 +1,105 @@ +/** + ****************************************************************************** + * @file usbd_msc_data.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header for the usbd_msc_data.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef _USBD_MSC_DATA_H_ +#define _USBD_MSC_DATA_H_ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" +//#include "usbd_conf.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_INFO + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_INFO_Exported_Defines + * @{ + */ +#define MODE_SENSE6_LEN 8 +#define MODE_SENSE10_LEN 8 +#define LENGTH_INQUIRY_PAGE00 7 +#define LENGTH_FORMAT_CAPACITIES 20 + +/** + * @} + */ + + +/** @defgroup USBD_INFO_Exported_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_INFO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_INFO_Exported_Variables + * @{ + */ +extern const uint8_t MSC_Page00_Inquiry_Data[]; +extern const uint8_t MSC_Mode_Sense6_data[]; +extern const uint8_t MSC_Mode_Sense10_data[] ; + +/** + * @} + */ + +/** @defgroup USBD_INFO_Exported_FunctionsPrototype + * @{ + */ + +/** + * @} + */ + +#endif /* _USBD_MSC_DATA_H_ */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_mem.h b/stm/lib/usbd_msc_mem.h new file mode 100644 index 000000000..888c79674 --- /dev/null +++ b/stm/lib/usbd_msc_mem.h @@ -0,0 +1,113 @@ +/** + ****************************************************************************** + * @file usbd_msc_mem.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header for the STORAGE DISK file file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __USBD_MEM_H +#define __USBD_MEM_H +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" +#include "usbd_def.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_MEM + * @brief header file for the storage disk file + * @{ + */ + +/** @defgroup USBD_MEM_Exported_Defines + * @{ + */ +#define USBD_STD_INQUIRY_LENGTH 36 +/** + * @} + */ + + +/** @defgroup USBD_MEM_Exported_TypesDefinitions + * @{ + */ + +typedef struct _USBD_STORAGE +{ + int8_t (* Init) (uint8_t lun); + int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint32_t *block_size); + int8_t (* IsReady) (uint8_t lun); + int8_t (* IsWriteProtected) (uint8_t lun); + int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t (* GetMaxLun)(void); + int8_t *pInquiry; + +}USBD_STORAGE_cb_TypeDef; +/** + * @} + */ + + + +/** @defgroup USBD_MEM_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_MEM_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_MEM_Exported_FunctionsPrototype + * @{ + */ +extern USBD_STORAGE_cb_TypeDef *USBD_STORAGE_fops; +/** + * @} + */ + +#endif /* __USBD_MEM_H */ +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_scsi.c b/stm/lib/usbd_msc_scsi.c new file mode 100644 index 000000000..c385d3ef6 --- /dev/null +++ b/stm/lib/usbd_msc_scsi.c @@ -0,0 +1,729 @@ +/** + ****************************************************************************** + * @file usbd_msc_scsi.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides all the USBD SCSI layer functions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_data.h" +#include "usbd_msc_conf.h" + + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_SCSI + * @brief Mass storage SCSI layer module + * @{ + */ + +/** @defgroup MSC_SCSI_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Variables + * @{ + */ + +SCSI_Sense_TypeDef SCSI_Sense [SENSE_LIST_DEEPTH]; +uint8_t SCSI_Sense_Head; +uint8_t SCSI_Sense_Tail; + +uint32_t SCSI_blk_size; +uint32_t SCSI_blk_nbr; + +uint32_t SCSI_blk_addr; +uint32_t SCSI_blk_len; + +USB_OTG_CORE_HANDLE *cdev; +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_FunctionPrototypes + * @{ + */ +static int8_t SCSI_TestUnitReady(uint8_t lun, uint8_t *params); +static int8_t SCSI_Inquiry(uint8_t lun, uint8_t *params); +static int8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t *params); +static int8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t *params); +static int8_t SCSI_RequestSense (uint8_t lun, uint8_t *params); +static int8_t SCSI_StartStopUnit(uint8_t lun, uint8_t *params); +static int8_t SCSI_ModeSense6 (uint8_t lun, uint8_t *params); +static int8_t SCSI_ModeSense10 (uint8_t lun, uint8_t *params); +static int8_t SCSI_Write10(uint8_t lun , uint8_t *params); +static int8_t SCSI_Read10(uint8_t lun , uint8_t *params); +static int8_t SCSI_Verify10(uint8_t lun, uint8_t *params); +static int8_t SCSI_CheckAddressRange (uint8_t lun , + uint32_t blk_offset , + uint16_t blk_nbr); +static int8_t SCSI_ProcessRead (uint8_t lun); + +static int8_t SCSI_ProcessWrite (uint8_t lun); +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Functions + * @{ + */ + + +/** +* @brief SCSI_ProcessCmd +* Process SCSI commands +* @param pdev: device instance +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +int8_t SCSI_ProcessCmd(USB_OTG_CORE_HANDLE *pdev, + uint8_t lun, + uint8_t *params) +{ + cdev = pdev; + + switch (params[0]) + { + case SCSI_TEST_UNIT_READY: + return SCSI_TestUnitReady(lun, params); + + case SCSI_REQUEST_SENSE: + return SCSI_RequestSense (lun, params); + case SCSI_INQUIRY: + return SCSI_Inquiry(lun, params); + + case SCSI_START_STOP_UNIT: + return SCSI_StartStopUnit(lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return SCSI_StartStopUnit(lun, params); + + case SCSI_MODE_SENSE6: + return SCSI_ModeSense6 (lun, params); + + case SCSI_MODE_SENSE10: + return SCSI_ModeSense10 (lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return SCSI_ReadFormatCapacity(lun, params); + + case SCSI_READ_CAPACITY10: + return SCSI_ReadCapacity10(lun, params); + + case SCSI_READ10: + return SCSI_Read10(lun, params); + + case SCSI_WRITE10: + return SCSI_Write10(lun, params); + + case SCSI_VERIFY10: + return SCSI_Verify10(lun, params); + + default: + SCSI_SenseCode(lun, + ILLEGAL_REQUEST, + INVALID_CDB); + return -1; + } +} + + +/** +* @brief SCSI_TestUnitReady +* Process SCSI Test Unit Ready Command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_TestUnitReady(uint8_t lun, uint8_t *params) +{ + + /* case 9 : Hi > D0 */ + if (MSC_BOT_cbw.dDataLength != 0) + { + SCSI_SenseCode(MSC_BOT_cbw.bLUN, + ILLEGAL_REQUEST, + INVALID_CDB); + return -1; + } + + if(USBD_STORAGE_fops->IsReady(lun) !=0 ) + { + SCSI_SenseCode(lun, + NOT_READY, + MEDIUM_NOT_PRESENT); + return -1; + } + MSC_BOT_DataLen = 0; + return 0; +} + +/** +* @brief SCSI_Inquiry +* Process Inquiry command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Inquiry(uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + if (params[1] & 0x01)/*Evpd is set*/ + { + pPage = (uint8_t *)MSC_Page00_Inquiry_Data; + len = LENGTH_INQUIRY_PAGE00; + } + else + { + + pPage = (uint8_t *)&USBD_STORAGE_fops->pInquiry[lun * USBD_STD_INQUIRY_LENGTH]; + len = pPage[4] + 5; + + if (params[4] <= len) + { + len = params[4]; + } + } + MSC_BOT_DataLen = len; + + while (len) + { + len--; + MSC_BOT_Data[len] = pPage[len]; + } + return 0; +} + +/** +* @brief SCSI_ReadCapacity10 +* Process Read Capacity 10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ReadCapacity10(uint8_t lun, uint8_t *params) +{ + + if(USBD_STORAGE_fops->GetCapacity(lun, &SCSI_blk_nbr, &SCSI_blk_size) != 0) + { + SCSI_SenseCode(lun, + NOT_READY, + MEDIUM_NOT_PRESENT); + return -1; + } + else + { + + MSC_BOT_Data[0] = (uint8_t)((SCSI_blk_nbr - 1) >> 24); // dpgeorge added paren + MSC_BOT_Data[1] = (uint8_t)((SCSI_blk_nbr - 1) >> 16); // dpgeorge added paren + MSC_BOT_Data[2] = (uint8_t)((SCSI_blk_nbr - 1) >> 8); // dpgeorge added paren + MSC_BOT_Data[3] = (uint8_t)(SCSI_blk_nbr - 1); + + MSC_BOT_Data[4] = (uint8_t)(SCSI_blk_size >> 24); + MSC_BOT_Data[5] = (uint8_t)(SCSI_blk_size >> 16); + MSC_BOT_Data[6] = (uint8_t)(SCSI_blk_size >> 8); + MSC_BOT_Data[7] = (uint8_t)(SCSI_blk_size); + + MSC_BOT_DataLen = 8; + return 0; + } +} +/** +* @brief SCSI_ReadFormatCapacity +* Process Read Format Capacity command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ReadFormatCapacity(uint8_t lun, uint8_t *params) +{ + + uint32_t blk_size; + uint32_t blk_nbr; + uint16_t i; + + for(i=0 ; i < 12 ; i++) + { + MSC_BOT_Data[i] = 0; + } + + if(USBD_STORAGE_fops->GetCapacity(lun, &blk_nbr, &blk_size) != 0) + { + SCSI_SenseCode(lun, + NOT_READY, + MEDIUM_NOT_PRESENT); + return -1; + } + else + { + MSC_BOT_Data[3] = 0x08; + MSC_BOT_Data[4] = (uint8_t)((blk_nbr - 1) >> 24); // dpgeorge added paren + MSC_BOT_Data[5] = (uint8_t)((blk_nbr - 1) >> 16); // dpgeorge added paren + MSC_BOT_Data[6] = (uint8_t)((blk_nbr - 1) >> 8); // dpgeorge added paren + MSC_BOT_Data[7] = (uint8_t)(blk_nbr - 1); + + MSC_BOT_Data[8] = 0x02; + MSC_BOT_Data[9] = (uint8_t)(blk_size >> 16); + MSC_BOT_Data[10] = (uint8_t)(blk_size >> 8); + MSC_BOT_Data[11] = (uint8_t)(blk_size); + + MSC_BOT_DataLen = 12; + return 0; + } +} +/** +* @brief SCSI_ModeSense6 +* Process Mode Sense6 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ModeSense6 (uint8_t lun, uint8_t *params) +{ + + uint16_t len = 8 ; + MSC_BOT_DataLen = len; + + while (len) + { + len--; + MSC_BOT_Data[len] = MSC_Mode_Sense6_data[len]; + } + return 0; +} + +/** +* @brief SCSI_ModeSense10 +* Process Mode Sense10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ModeSense10 (uint8_t lun, uint8_t *params) +{ + uint16_t len = 8; + + MSC_BOT_DataLen = len; + + while (len) + { + len--; + MSC_BOT_Data[len] = MSC_Mode_Sense10_data[len]; + } + return 0; +} + +/** +* @brief SCSI_RequestSense +* Process Request Sense command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_RequestSense (uint8_t lun, uint8_t *params) +{ + uint8_t i; + + for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++) + { + MSC_BOT_Data[i] = 0; + } + + MSC_BOT_Data[0] = 0x70; + MSC_BOT_Data[7] = REQUEST_SENSE_DATA_LEN - 6; + + if((SCSI_Sense_Head != SCSI_Sense_Tail)) { + + MSC_BOT_Data[2] = SCSI_Sense[SCSI_Sense_Head].Skey; + MSC_BOT_Data[12] = SCSI_Sense[SCSI_Sense_Head].w.b.ASCQ; + MSC_BOT_Data[13] = SCSI_Sense[SCSI_Sense_Head].w.b.ASC; + SCSI_Sense_Head++; + + if (SCSI_Sense_Head == SENSE_LIST_DEEPTH) + { + SCSI_Sense_Head = 0; + } + } + MSC_BOT_DataLen = REQUEST_SENSE_DATA_LEN; + + if (params[4] <= REQUEST_SENSE_DATA_LEN) + { + MSC_BOT_DataLen = params[4]; + } + return 0; +} + +/** +* @brief SCSI_SenseCode +* Load the last error code in the error list +* @param lun: Logical unit number +* @param sKey: Sense Key +* @param ASC: Additional Sense Key +* @retval none + +*/ +void SCSI_SenseCode(uint8_t lun, uint8_t sKey, uint8_t ASC) +{ + SCSI_Sense[SCSI_Sense_Tail].Skey = sKey; + SCSI_Sense[SCSI_Sense_Tail].w.ASC = ASC << 8; + SCSI_Sense_Tail++; + if (SCSI_Sense_Tail == SENSE_LIST_DEEPTH) + { + SCSI_Sense_Tail = 0; + } +} +/** +* @brief SCSI_StartStopUnit +* Process Start Stop Unit command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_StartStopUnit(uint8_t lun, uint8_t *params) +{ + MSC_BOT_DataLen = 0; + return 0; +} + +/** +* @brief SCSI_Read10 +* Process Read10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Read10(uint8_t lun , uint8_t *params) +{ + if(MSC_BOT_State == BOT_IDLE) /* Idle */ + { + + /* case 10 : Ho <> Di */ + + if ((MSC_BOT_cbw.bmFlags & 0x80) != 0x80) + { + SCSI_SenseCode(MSC_BOT_cbw.bLUN, + ILLEGAL_REQUEST, + INVALID_CDB); + return -1; + } + + if(USBD_STORAGE_fops->IsReady(lun) !=0 ) + { + SCSI_SenseCode(lun, + NOT_READY, + MEDIUM_NOT_PRESENT); + return -1; + } + + SCSI_blk_addr = (params[2] << 24) | \ + (params[3] << 16) | \ + (params[4] << 8) | \ + params[5]; + + SCSI_blk_len = (params[7] << 8) | \ + params[8]; + + + + if( SCSI_CheckAddressRange(lun, SCSI_blk_addr, SCSI_blk_len) < 0) + { + return -1; /* error */ + } + + MSC_BOT_State = BOT_DATA_IN; + SCSI_blk_addr *= SCSI_blk_size; + SCSI_blk_len *= SCSI_blk_size; + + /* cases 4,5 : Hi <> Dn */ + if (MSC_BOT_cbw.dDataLength != SCSI_blk_len) + { + SCSI_SenseCode(MSC_BOT_cbw.bLUN, + ILLEGAL_REQUEST, + INVALID_CDB); + return -1; + } + } + MSC_BOT_DataLen = MSC_MEDIA_PACKET; + + return SCSI_ProcessRead(lun); +} + +/** +* @brief SCSI_Write10 +* Process Write10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_Write10 (uint8_t lun , uint8_t *params) +{ + if (MSC_BOT_State == BOT_IDLE) /* Idle */ + { + + /* case 8 : Hi <> Do */ + + if ((MSC_BOT_cbw.bmFlags & 0x80) == 0x80) + { + SCSI_SenseCode(MSC_BOT_cbw.bLUN, + ILLEGAL_REQUEST, + INVALID_CDB); + return -1; + } + + /* Check whether Media is ready */ + if(USBD_STORAGE_fops->IsReady(lun) !=0 ) + { + SCSI_SenseCode(lun, + NOT_READY, + MEDIUM_NOT_PRESENT); + return -1; + } + + /* Check If media is write-protected */ + if(USBD_STORAGE_fops->IsWriteProtected(lun) !=0 ) + { + SCSI_SenseCode(lun, + NOT_READY, + WRITE_PROTECTED); + return -1; + } + + + SCSI_blk_addr = (params[2] << 24) | \ + (params[3] << 16) | \ + (params[4] << 8) | \ + params[5]; + SCSI_blk_len = (params[7] << 8) | \ + params[8]; + + /* check if LBA address is in the right range */ + if(SCSI_CheckAddressRange(lun, SCSI_blk_addr, SCSI_blk_len) < 0) + { + return -1; /* error */ + } + + SCSI_blk_addr *= SCSI_blk_size; + SCSI_blk_len *= SCSI_blk_size; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (MSC_BOT_cbw.dDataLength != SCSI_blk_len) + { + SCSI_SenseCode(MSC_BOT_cbw.bLUN, + ILLEGAL_REQUEST, + INVALID_CDB); + return -1; + } + + /* Prepare EP to receive first data packet */ + MSC_BOT_State = BOT_DATA_OUT; + DCD_EP_PrepareRx (cdev, + MSC_OUT_EP, + MSC_BOT_Data, + MIN (SCSI_blk_len, MSC_MEDIA_PACKET)); + } + else /* Write Process ongoing */ + { + return SCSI_ProcessWrite(lun); + } + return 0; +} + + +/** +* @brief SCSI_Verify10 +* Process Verify10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_Verify10(uint8_t lun , uint8_t *params){ + if ((params[1]& 0x02) == 0x02) + { + SCSI_SenseCode (lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + return -1; /* Error, Verify Mode Not supported*/ + } + + if(SCSI_CheckAddressRange(lun, SCSI_blk_addr, SCSI_blk_len) < 0) + { + return -1; /* error */ + } + MSC_BOT_DataLen = 0; + return 0; +} + +/** +* @brief SCSI_CheckAddressRange +* Check address range +* @param lun: Logical unit number +* @param blk_offset: first block address +* @param blk_nbr: number of block to be processed +* @retval status +*/ +static int8_t SCSI_CheckAddressRange (uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr) +{ + + if ((blk_offset + blk_nbr) > SCSI_blk_nbr ) + { + SCSI_SenseCode(lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + return -1; + } + return 0; +} + +/** +* @brief SCSI_ProcessRead +* Handle Read Process +* @param lun: Logical unit number +* @retval status +*/ +static int8_t SCSI_ProcessRead (uint8_t lun) +{ + uint32_t len; + + len = MIN(SCSI_blk_len , MSC_MEDIA_PACKET); + + if( USBD_STORAGE_fops->Read(lun , + MSC_BOT_Data, + SCSI_blk_addr / SCSI_blk_size, + len / SCSI_blk_size) < 0) + { + + SCSI_SenseCode(lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + return -1; + } + + + DCD_EP_Tx (cdev, + MSC_IN_EP, + MSC_BOT_Data, + len); + + + SCSI_blk_addr += len; + SCSI_blk_len -= len; + + /* case 6 : Hi = Di */ + MSC_BOT_csw.dDataResidue -= len; + + if (SCSI_blk_len == 0) + { + MSC_BOT_State = BOT_LAST_DATA_IN; + } + return 0; +} + +/** +* @brief SCSI_ProcessWrite +* Handle Write Process +* @param lun: Logical unit number +* @retval status +*/ + +static int8_t SCSI_ProcessWrite (uint8_t lun) +{ + uint32_t len; + + len = MIN(SCSI_blk_len , MSC_MEDIA_PACKET); + + if(USBD_STORAGE_fops->Write(lun , + MSC_BOT_Data, + SCSI_blk_addr / SCSI_blk_size, + len / SCSI_blk_size) < 0) + { + SCSI_SenseCode(lun, HARDWARE_ERROR, WRITE_FAULT); + return -1; + } + + + SCSI_blk_addr += len; + SCSI_blk_len -= len; + + /* case 12 : Ho = Do */ + MSC_BOT_csw.dDataResidue -= len; + + if (SCSI_blk_len == 0) + { + MSC_BOT_SendCSW (cdev, CSW_CMD_PASSED); + } + else + { + /* Prapare EP to Receive next packet */ + DCD_EP_PrepareRx (cdev, + MSC_OUT_EP, + MSC_BOT_Data, + MIN (SCSI_blk_len, MSC_MEDIA_PACKET)); + } + + return 0; +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_msc_scsi.h b/stm/lib/usbd_msc_scsi.h new file mode 100644 index 000000000..1b8e35af1 --- /dev/null +++ b/stm/lib/usbd_msc_scsi.h @@ -0,0 +1,195 @@ +/** + ****************************************************************************** + * @file usbd_msc_scsi.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header for the usbd_msc_scsi.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_SCSI + * @brief header file for the storage disk file + * @{ + */ + +/** @defgroup USBD_SCSI_Exported_Defines + * @{ + */ + +#define SENSE_LIST_DEEPTH 4 + +/* SCSI Commands */ +#define SCSI_FORMAT_UNIT 0x04 +#define SCSI_INQUIRY 0x12 +#define SCSI_MODE_SELECT6 0x15 +#define SCSI_MODE_SELECT10 0x55 +#define SCSI_MODE_SENSE6 0x1A +#define SCSI_MODE_SENSE10 0x5A +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E +#define SCSI_READ6 0x08 +#define SCSI_READ10 0x28 +#define SCSI_READ12 0xA8 +#define SCSI_READ16 0x88 + +#define SCSI_READ_CAPACITY10 0x25 +#define SCSI_READ_CAPACITY16 0x9E + +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_WRITE6 0x0A +#define SCSI_WRITE10 0x2A +#define SCSI_WRITE12 0xAA +#define SCSI_WRITE16 0x8A + +#define SCSI_VERIFY10 0x2F +#define SCSI_VERIFY12 0xAF +#define SCSI_VERIFY16 0x8F + +#define SCSI_SEND_DIAGNOSTIC 0x1D +#define SCSI_READ_FORMAT_CAPACITIES 0x23 + +#define NO_SENSE 0 +#define RECOVERED_ERROR 1 +#define NOT_READY 2 +#define MEDIUM_ERROR 3 +#define HARDWARE_ERROR 4 +#define ILLEGAL_REQUEST 5 +#define UNIT_ATTENTION 6 +#define DATA_PROTECT 7 +#define BLANK_CHECK 8 +#define VENDOR_SPECIFIC 9 +#define COPY_ABORTED 10 +#define ABORTED_COMMAND 11 +#define VOLUME_OVERFLOW 13 +#define MISCOMPARE 14 + + +#define INVALID_CDB 0x20 +#define INVALID_FIELED_IN_COMMAND 0x24 +#define PARAMETER_LIST_LENGTH_ERROR 0x1A +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26 +#define ADDRESS_OUT_OF_RANGE 0x21 +#define MEDIUM_NOT_PRESENT 0x3A +#define MEDIUM_HAVE_CHANGED 0x28 +#define WRITE_PROTECTED 0x27 +#define UNRECOVERED_READ_ERROR 0x11 +#define WRITE_FAULT 0x03 + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0C +#define READ_CAPACITY10_DATA_LEN 0x08 +#define MODE_SENSE10_DATA_LEN 0x08 +#define MODE_SENSE6_DATA_LEN 0x04 +#define REQUEST_SENSE_DATA_LEN 0x12 +#define STANDARD_INQUIRY_DATA_LEN 0x24 +#define BLKVFY 0x04 + +extern uint8_t Page00_Inquiry_Data[]; +extern uint8_t Standard_Inquiry_Data[]; +extern uint8_t Standard_Inquiry_Data2[]; +extern uint8_t Mode_Sense6_data[]; +extern uint8_t Mode_Sense10_data[]; +extern uint8_t Scsi_Sense_Data[]; +extern uint8_t ReadCapacity10_Data[]; +extern uint8_t ReadFormatCapacity_Data []; +/** + * @} + */ + + +/** @defgroup USBD_SCSI_Exported_TypesDefinitions + * @{ + */ + +typedef struct _SENSE_ITEM { + char Skey; + union { + struct _ASCs { + char ASC; + char ASCQ; + }b; + unsigned int ASC; + char *pData; + } w; +} SCSI_Sense_TypeDef; +/** + * @} + */ + +/** @defgroup USBD_SCSI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_SCSI_Exported_Variables + * @{ + */ +extern SCSI_Sense_TypeDef SCSI_Sense [SENSE_LIST_DEEPTH]; +extern uint8_t SCSI_Sense_Head; +extern uint8_t SCSI_Sense_Tail; + +/** + * @} + */ +/** @defgroup USBD_SCSI_Exported_FunctionsPrototype + * @{ + */ +int8_t SCSI_ProcessCmd(USB_OTG_CORE_HANDLE *pdev, + uint8_t lun, + uint8_t *cmd); + +void SCSI_SenseCode(uint8_t lun, + uint8_t sKey, + uint8_t ASC); + +/** + * @} + */ + +#endif /* __USBD_MSC_SCSI_H */ +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_req.c b/stm/lib/usbd_req.c new file mode 100644 index 000000000..f954bd9af --- /dev/null +++ b/stm/lib/usbd_req.c @@ -0,0 +1,868 @@ +/** + ****************************************************************************** + * @file usbd_req.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides the standard USB requests following chapter 9. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_req.h" +#include "usbd_ioreq.h" +#include "usbd_desc.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_REQ + * @brief USB standard requests module + * @{ + */ + +/** @defgroup USBD_REQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Variables + * @{ + */ +extern __IO USB_OTG_DCTL_TypeDef SET_TEST_MODE; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint32_t USBD_ep_status __ALIGN_END = 0; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint32_t USBD_default_cfg __ALIGN_END = 0; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint32_t USBD_cfg_status __ALIGN_END = 0; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ] __ALIGN_END ; +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_FunctionPrototypes + * @{ + */ +static void USBD_GetDescriptor(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +static void USBD_SetAddress(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +static void USBD_SetConfig(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +static void USBD_GetConfig(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +static void USBD_GetStatus(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +static void USBD_SetFeature(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +static void USBD_ClrFeature(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +static uint8_t USBD_GetLen(uint8_t *buf); +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Functions + * @{ + */ + + +/** +* @brief USBD_StdDevReq +* Handle standard usb device requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +USBD_Status USBD_StdDevReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) +{ + USBD_Status ret = USBD_OK; + + switch (req->bRequest) + { + case USB_REQ_GET_DESCRIPTOR: + + USBD_GetDescriptor (pdev, req) ; + break; + + case USB_REQ_SET_ADDRESS: + USBD_SetAddress(pdev, req); + break; + + case USB_REQ_SET_CONFIGURATION: + USBD_SetConfig (pdev , req); + break; + + case USB_REQ_GET_CONFIGURATION: + USBD_GetConfig (pdev , req); + break; + + case USB_REQ_GET_STATUS: + USBD_GetStatus (pdev , req); + break; + + + case USB_REQ_SET_FEATURE: + USBD_SetFeature (pdev , req); + break; + + case USB_REQ_CLEAR_FEATURE: + USBD_ClrFeature (pdev , req); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + + return ret; +} + +/** +* @brief USBD_StdItfReq +* Handle standard usb interface requests +* @param pdev: USB OTG device instance +* @param req: usb request +* @retval status +*/ +USBD_Status USBD_StdItfReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) +{ + USBD_Status ret = USBD_OK; + + switch (pdev->dev.device_status) + { + case USB_OTG_CONFIGURED: + + if (LOBYTE(req->wIndex) <= USBD_ITF_MAX_NUM) + { + pdev->dev.class_cb->Setup (pdev, req); + + if((req->wLength == 0)&& (ret == USBD_OK)) + { + USBD_CtlSendStatus(pdev); + } + } + else + { + USBD_CtlError(pdev , req); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + return ret; +} + +/** +* @brief USBD_StdEPReq +* Handle standard usb endpoint requests +* @param pdev: USB OTG device instance +* @param req: usb request +* @retval status +*/ +USBD_Status USBD_StdEPReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req) +{ + + uint8_t ep_addr; + USBD_Status ret = USBD_OK; + + ep_addr = LOBYTE(req->wIndex); + + switch (req->bRequest) + { + + case USB_REQ_SET_FEATURE : + + switch (pdev->dev.device_status) + { + case USB_OTG_ADDRESSED: + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + DCD_EP_Stall(pdev , ep_addr); + } + break; + + case USB_OTG_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + DCD_EP_Stall(pdev , ep_addr); + + } + } + pdev->dev.class_cb->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + case USB_REQ_CLEAR_FEATURE : + + switch (pdev->dev.device_status) + { + case USB_OTG_ADDRESSED: + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + DCD_EP_Stall(pdev , ep_addr); + } + break; + + case USB_OTG_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + DCD_EP_ClrStall(pdev , ep_addr); + pdev->dev.class_cb->Setup (pdev, req); + } + USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + case USB_REQ_GET_STATUS: + switch (pdev->dev.device_status) + { + case USB_OTG_ADDRESSED: + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + DCD_EP_Stall(pdev , ep_addr); + } + break; + + case USB_OTG_CONFIGURED: + + + if ((ep_addr & 0x80)== 0x80) + { + if(pdev->dev.in_ep[ep_addr & 0x7F].is_stall) + { + USBD_ep_status = 0x0001; + } + else + { + USBD_ep_status = 0x0000; + } + } + else if ((ep_addr & 0x80)== 0x00) + { + if(pdev->dev.out_ep[ep_addr].is_stall) + { + USBD_ep_status = 0x0001; + } + + else + { + USBD_ep_status = 0x0000; + } + } + USBD_CtlSendData (pdev, + (uint8_t *)&USBD_ep_status, + 2); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + default: + break; + } + return ret; +} +/** +* @brief USBD_GetDescriptor +* Handle Get Descriptor requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetDescriptor(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + uint16_t len; + uint8_t *pbuf; + + + switch (req->wValue >> 8) + { + case USB_DESC_TYPE_DEVICE: + pbuf = pdev->dev.usr_device->GetDeviceDescriptor(pdev->cfg.speed, &len); + if ((req->wLength == 64) ||( pdev->dev.device_status == USB_OTG_DEFAULT)) + { + len = 8; + } + break; + + case USB_DESC_TYPE_CONFIGURATION: + pbuf = (uint8_t *)pdev->dev.class_cb->GetConfigDescriptor(pdev->cfg.speed, &len); +#ifdef USB_OTG_HS_CORE + if((pdev->cfg.speed == USB_OTG_SPEED_FULL )&& + (pdev->cfg.phy_itface == USB_OTG_ULPI_PHY)) + { + pbuf = (uint8_t *)pdev->dev.class_cb->GetOtherConfigDescriptor(pdev->cfg.speed, &len); + } +#endif + pbuf[1] = USB_DESC_TYPE_CONFIGURATION; + pdev->dev.pConfig_descriptor = pbuf; + break; + + case USB_DESC_TYPE_STRING: + switch ((uint8_t)(req->wValue)) + { + case USBD_IDX_LANGID_STR: + pbuf = pdev->dev.usr_device->GetLangIDStrDescriptor(pdev->cfg.speed, &len); + break; + + case USBD_IDX_MFC_STR: + pbuf = pdev->dev.usr_device->GetManufacturerStrDescriptor(pdev->cfg.speed, &len); + break; + + case USBD_IDX_PRODUCT_STR: + pbuf = pdev->dev.usr_device->GetProductStrDescriptor(pdev->cfg.speed, &len); + break; + + case USBD_IDX_SERIAL_STR: + pbuf = pdev->dev.usr_device->GetSerialStrDescriptor(pdev->cfg.speed, &len); + break; + + case USBD_IDX_CONFIG_STR: + pbuf = pdev->dev.usr_device->GetConfigurationStrDescriptor(pdev->cfg.speed, &len); + break; + + case USBD_IDX_INTERFACE_STR: + pbuf = pdev->dev.usr_device->GetInterfaceStrDescriptor(pdev->cfg.speed, &len); + break; + + default: +#ifdef USB_SUPPORT_USER_STRING_DESC + pbuf = pdev->dev.class_cb->GetUsrStrDescriptor(pdev->cfg.speed, (req->wValue) , &len); + break; +#else + USBD_CtlError(pdev , req); + return; +#endif /* USBD_CtlError(pdev , req); */ + } + break; + case USB_DESC_TYPE_DEVICE_QUALIFIER: +#ifdef USB_OTG_HS_CORE + if(pdev->cfg.speed == USB_OTG_SPEED_HIGH ) + { + + pbuf = (uint8_t *)pdev->dev.class_cb->GetConfigDescriptor(pdev->cfg.speed, &len); + + USBD_DeviceQualifierDesc[4]= pbuf[14]; + USBD_DeviceQualifierDesc[5]= pbuf[15]; + USBD_DeviceQualifierDesc[6]= pbuf[16]; + + pbuf = USBD_DeviceQualifierDesc; + len = USB_LEN_DEV_QUALIFIER_DESC; + break; + } + else + { + USBD_CtlError(pdev , req); + return; + } +#else + USBD_CtlError(pdev , req); + return; +#endif + + case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: +#ifdef USB_OTG_HS_CORE + + if(pdev->cfg.speed == USB_OTG_SPEED_HIGH ) + { + pbuf = (uint8_t *)pdev->dev.class_cb->GetOtherConfigDescriptor(pdev->cfg.speed, &len); + pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; + break; + } + else + { + USBD_CtlError(pdev , req); + return; + } +#else + USBD_CtlError(pdev , req); + return; +#endif + + + default: + USBD_CtlError(pdev , req); + return; + } + + if((len != 0)&& (req->wLength != 0)) + { + + len = MIN(len , req->wLength); + + USBD_CtlSendData (pdev, + pbuf, + len); + } + +} + +/** +* @brief USBD_SetAddress +* Set device address +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetAddress(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + uint8_t dev_addr; + + if ((req->wIndex == 0) && (req->wLength == 0)) + { + dev_addr = (uint8_t)(req->wValue) & 0x7F; + + if (pdev->dev.device_status == USB_OTG_CONFIGURED) + { + USBD_CtlError(pdev , req); + } + else + { + pdev->dev.device_address = dev_addr; + DCD_EP_SetAddress(pdev, dev_addr); + USBD_CtlSendStatus(pdev); + + if (dev_addr != 0) + { + pdev->dev.device_status = USB_OTG_ADDRESSED; + } + else + { + pdev->dev.device_status = USB_OTG_DEFAULT; + } + } + } + else + { + USBD_CtlError(pdev , req); + } +} + +/** +* @brief USBD_SetConfig +* Handle Set device configuration request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetConfig(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + + static uint8_t cfgidx; + + cfgidx = (uint8_t)(req->wValue); + + if (cfgidx > USBD_CFG_MAX_NUM ) + { + USBD_CtlError(pdev , req); + } + else + { + switch (pdev->dev.device_status) + { + case USB_OTG_ADDRESSED: + if (cfgidx) + { + pdev->dev.device_config = cfgidx; + pdev->dev.device_status = USB_OTG_CONFIGURED; + USBD_SetCfg(pdev , cfgidx); + USBD_CtlSendStatus(pdev); + } + else + { + USBD_CtlSendStatus(pdev); + } + break; + + case USB_OTG_CONFIGURED: + if (cfgidx == 0) + { + pdev->dev.device_status = USB_OTG_ADDRESSED; + pdev->dev.device_config = cfgidx; + USBD_ClrCfg(pdev , cfgidx); + USBD_CtlSendStatus(pdev); + + } + else if (cfgidx != pdev->dev.device_config) + { + /* Clear old configuration */ + USBD_ClrCfg(pdev , pdev->dev.device_config); + + /* set new configuration */ + pdev->dev.device_config = cfgidx; + USBD_SetCfg(pdev , cfgidx); + USBD_CtlSendStatus(pdev); + } + else + { + USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + } +} + +/** +* @brief USBD_GetConfig +* Handle Get device configuration request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetConfig(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + + if (req->wLength != 1) + { + USBD_CtlError(pdev , req); + } + else + { + switch (pdev->dev.device_status ) + { + case USB_OTG_ADDRESSED: + + USBD_CtlSendData (pdev, + (uint8_t *)&USBD_default_cfg, + 1); + break; + + case USB_OTG_CONFIGURED: + + USBD_CtlSendData (pdev, + &pdev->dev.device_config, + 1); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + } +} + +/** +* @brief USBD_GetStatus +* Handle Get Status request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetStatus(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + + + switch (pdev->dev.device_status) + { + case USB_OTG_ADDRESSED: + case USB_OTG_CONFIGURED: + +#ifdef USBD_SELF_POWERED + USBD_cfg_status = USB_CONFIG_SELF_POWERED; +#else + USBD_cfg_status = 0x00; +#endif + + if (pdev->dev.DevRemoteWakeup) + { + USBD_cfg_status |= USB_CONFIG_REMOTE_WAKEUP; + } + + USBD_CtlSendData (pdev, + (uint8_t *)&USBD_cfg_status, + 2); + break; + + default : + USBD_CtlError(pdev , req); + break; + } +} + + +/** +* @brief USBD_SetFeature +* Handle Set device feature request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetFeature(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + + USB_OTG_DCTL_TypeDef dctl; + uint8_t test_mode = 0; + + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev.DevRemoteWakeup = 1; + pdev->dev.class_cb->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + } + + else if ((req->wValue == USB_FEATURE_TEST_MODE) && + ((req->wIndex & 0xFF) == 0)) + { + dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL); + + test_mode = req->wIndex >> 8; + switch (test_mode) + { + case 1: // TEST_J + dctl.b.tstctl = 1; + break; + + case 2: // TEST_K + dctl.b.tstctl = 2; + break; + + case 3: // TEST_SE0_NAK + dctl.b.tstctl = 3; + break; + + case 4: // TEST_PACKET + dctl.b.tstctl = 4; + break; + + case 5: // TEST_FORCE_ENABLE + dctl.b.tstctl = 5; + break; + } + SET_TEST_MODE = dctl; + pdev->dev.test_mode = 1; + USBD_CtlSendStatus(pdev); + } + +} + + +/** +* @brief USBD_ClrFeature +* Handle clear device feature request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_ClrFeature(USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + switch (pdev->dev.device_status) + { + case USB_OTG_ADDRESSED: + case USB_OTG_CONFIGURED: + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev.DevRemoteWakeup = 0; + pdev->dev.class_cb->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + } + break; + + default : + USBD_CtlError(pdev , req); + break; + } +} + +/** +* @brief USBD_ParseSetupRequest +* Copy buffer into setup structure +* @param pdev: device instance +* @param req: usb request +* @retval None +*/ + +void USBD_ParseSetupRequest( USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + req->bmRequest = *(uint8_t *) (pdev->dev.setup_packet); + req->bRequest = *(uint8_t *) (pdev->dev.setup_packet + 1); + req->wValue = SWAPBYTE (pdev->dev.setup_packet + 2); + req->wIndex = SWAPBYTE (pdev->dev.setup_packet + 4); + req->wLength = SWAPBYTE (pdev->dev.setup_packet + 6); + + pdev->dev.in_ep[0].ctl_data_len = req->wLength ; + pdev->dev.device_state = USB_OTG_EP0_SETUP; +} + +/** +* @brief USBD_CtlError +* Handle USB low level Error +* @param pdev: device instance +* @param req: usb request +* @retval None +*/ + +void USBD_CtlError( USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req) +{ + + DCD_EP_Stall(pdev , 0x80); + DCD_EP_Stall(pdev , 0); + USB_OTG_EP0_OutStart(pdev); +} + + +/** + * @brief USBD_GetString + * Convert Ascii string into unicode one + * @param desc : descriptor buffer + * @param unicode : Formatted string buffer (unicode) + * @param len : descriptor length + * @retval None + */ +void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len) +{ + uint8_t idx = 0; + + if (desc != NULL) + { + *len = USBD_GetLen(desc) * 2 + 2; + unicode[idx++] = *len; + unicode[idx++] = USB_DESC_TYPE_STRING; + + while (*desc != NULL) + { + unicode[idx++] = *desc++; + unicode[idx++] = 0x00; + } + } +} + +/** + * @brief USBD_GetLen + * return the string length + * @param buf : pointer to the ascii string buffer + * @retval string length + */ +static uint8_t USBD_GetLen(uint8_t *buf) +{ + uint8_t len = 0; + + while (*buf != NULL) + { + len++; + buf++; + } + + return len; +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_req.h b/stm/lib/usbd_req.h new file mode 100644 index 000000000..f88416df3 --- /dev/null +++ b/stm/lib/usbd_req.h @@ -0,0 +1,108 @@ +/** + ****************************************************************************** + * @file usbd_req.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief header file for the usbd_req.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __USB_REQUEST_H_ +#define __USB_REQUEST_H_ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_core.h" +#include "usbd_conf.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_REQ + * @brief header file for the usbd_ioreq.c file + * @{ + */ + +/** @defgroup USBD_REQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Exported_Types + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_REQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_Status USBD_StdDevReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req); +USBD_Status USBD_StdItfReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req); +USBD_Status USBD_StdEPReq (USB_OTG_CORE_HANDLE *pdev, USB_SETUP_REQ *req); +void USBD_ParseSetupRequest( USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +void USBD_CtlError( USB_OTG_CORE_HANDLE *pdev, + USB_SETUP_REQ *req); + +void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len); +/** + * @} + */ + +#endif /* __USB_REQUEST_H_ */ + +/** + * @} + */ + +/** +* @} +*/ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_storage_msd.c b/stm/lib/usbd_storage_msd.c new file mode 100644 index 000000000..1844ef9ad --- /dev/null +++ b/stm/lib/usbd_storage_msd.c @@ -0,0 +1,350 @@ +/** + ****************************************************************************** + * @file usbd_storage_msd.c + * @author MCD application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides the disk operations functions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_mem.h" +#include "usb_conf.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup STORAGE + * @brief media storage application module + * @{ + */ + +/** @defgroup STORAGE_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup STORAGE_Private_Defines + * @{ + */ + +#define STORAGE_LUN_NBR 1 +/** + * @} + */ + + +/** @defgroup STORAGE_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup STORAGE_Private_Variables + * @{ + */ +/* USB Mass storage Standard Inquiry Data */ +const int8_t STORAGE_Inquirydata[] = {//36 + + /* LUN 0 */ + 0x00, + 0x00, // make it 0x80 for a removable drive + 0x02, + 0x02, + (USBD_STD_INQUIRY_LENGTH - 5), + 0x00, + 0x00, + 0x00, + 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */ + 'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', /* Product : 16 Bytes */ + 'F', 'l', 'a', 's', 'h', ' ', ' ', ' ', + '1', '.', '0' ,'0', /* Version : 4 Bytes */ +}; + +/** + * @} + */ + + +/** @defgroup STORAGE_Private_FunctionPrototypes + * @{ + */ +int8_t STORAGE_Init (uint8_t lun); + +int8_t STORAGE_GetCapacity (uint8_t lun, + uint32_t *block_num, + uint32_t *block_size); + +int8_t STORAGE_IsReady (uint8_t lun); + +int8_t STORAGE_IsWriteProtected (uint8_t lun); + +int8_t STORAGE_Read (uint8_t lun, + uint8_t *buf, + uint32_t blk_addr, + uint16_t blk_len); + +int8_t STORAGE_Write (uint8_t lun, + uint8_t *buf, + uint32_t blk_addr, + uint16_t blk_len); + +int8_t STORAGE_GetMaxLun (void); + + +USBD_STORAGE_cb_TypeDef USBD_MICRO_SDIO_fops = +{ + STORAGE_Init, + STORAGE_GetCapacity, + STORAGE_IsReady, + STORAGE_IsWriteProtected, + STORAGE_Read, + STORAGE_Write, + STORAGE_GetMaxLun, + (int8_t *)STORAGE_Inquirydata, +}; + +USBD_STORAGE_cb_TypeDef *USBD_STORAGE_fops = &USBD_MICRO_SDIO_fops; +/* +#ifndef USE_STM3210C_EVAL +extern SD_CardInfo SDCardInfo; +#endif +*/ + +/** + * @} + */ + + +/** @defgroup STORAGE_Private_Functions + * @{ + */ + + +/** + * @brief Initialize the storage medium + * @param lun : logical unit number + * @retval Status + */ + +int8_t STORAGE_Init (uint8_t lun) +{ + /* +#ifndef USE_STM3210C_EVAL + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +#endif + if( SD_Init() != 0) + { + return (-1); + } + */ + + return (0); + +} + +/** + * @brief return medium capacity and block size + * @param lun : logical unit number + * @param block_num : number of physical block + * @param block_size : size of a physical block + * @retval Status + */ +int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint32_t *block_size) +{ +/* +#ifdef USE_STM3210C_EVAL + SD_CardInfo SDCardInfo; + + SD_GetCardInfo(&SDCardInfo); + +#else + if(SD_GetStatus() != 0 ) + { + return (-1); + } +#endif + */ + + + *block_size = 512; + //*block_num = SDCardInfo.CardCapacity / 512; + *block_num = 256 + 128; + + return (0); + +} + +/** + * @brief check whether the medium is ready + * @param lun : logical unit number + * @retval Status + */ +int8_t STORAGE_IsReady (uint8_t lun) +{ + + /* +#ifndef USE_STM3210C_EVAL + + static int8_t last_status = 0; + + if(last_status < 0) + { + SD_Init(); + last_status = 0; + } + + if(SD_GetStatus() != 0) + { + last_status = -1; + return (-1); + } +#else + if( SD_Init() != 0) + { + return (-1); + } +#endif +*/ + return (0); +} + +/** + * @brief check whether the medium is write-protected + * @param lun : logical unit number + * @retval Status + */ +int8_t STORAGE_IsWriteProtected (uint8_t lun) +{ + return 0; +} + +/** + * @brief Read data from the medium + * @param lun : logical unit number + * @param buf : Pointer to the buffer to save data + * @param blk_addr : address of 1st block to be read + * @param blk_len : nmber of blocks to be read + * @retval Status + */ +int disk_read ( + uint8_t pdrv, /* Physical drive nmuber (0..) */ + uint8_t *buff, /* Data buffer to store read data */ + uint32_t sector, /* Sector address (LBA) */ + uint32_t count /* Number of sectors to read (1..128) */ +); +int8_t STORAGE_Read (uint8_t lun, + uint8_t *buf, + uint32_t blk_addr, + uint16_t blk_len) +{ + + /* + if( SD_ReadMultiBlocks (buf, + blk_addr * 512, + 512, + blk_len) != 0) + { + return -1; + } +#ifndef USE_STM3210C_EVAL + SD_WaitReadOperation(); + while (SD_GetStatus() != SD_TRANSFER_OK); +#endif +*/ + disk_read(0, buf, blk_addr, blk_len); + return 0; +} +/** + * @brief Write data to the medium + * @param lun : logical unit number + * @param buf : Pointer to the buffer to write from + * @param blk_addr : address of 1st block to be written + * @param blk_len : nmber of blocks to be read + * @retval Status + */ +int disk_write ( + uint8_t pdrv, /* Physical drive nmuber (0..) */ + const uint8_t *buff, /* Data to be written */ + uint32_t sector, /* Sector address (LBA) */ + uint32_t count /* Number of sectors to write (1..128) */ +); +int8_t STORAGE_Write (uint8_t lun, + uint8_t *buf, + uint32_t blk_addr, + uint16_t blk_len) +{ + + /* + if( SD_WriteMultiBlocks (buf, + blk_addr * 512, + 512, + blk_len) != 0) + { + return -1; + } +#ifndef USE_STM3210C_EVAL + SD_WaitWriteOperation(); + while (SD_GetStatus() != SD_TRANSFER_OK); +#endif +*/ + disk_write(0, buf, blk_addr, blk_len); + return (0); +} + +/** + * @brief Return number of supported logical unit + * @param None + * @retval number of logical unit + */ + +int8_t STORAGE_GetMaxLun (void) +{ + return (STORAGE_LUN_NBR - 1); +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/lib/usbd_usr.c b/stm/lib/usbd_usr.c new file mode 100644 index 000000000..844a3ed7f --- /dev/null +++ b/stm/lib/usbd_usr.c @@ -0,0 +1,115 @@ +/** + ****************************************************************************** + * @file usbd_usr.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file includes the user application layer + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#include "usbd_usr.h" +#include "usbd_ioreq.h" +#include "std.h" + +USBD_Usr_cb_TypeDef USR_cb = { + USBD_USR_Init, + USBD_USR_DeviceReset, + USBD_USR_DeviceConfigured, + USBD_USR_DeviceSuspended, + USBD_USR_DeviceResumed, + USBD_USR_DeviceConnected, + USBD_USR_DeviceDisconnected, +}; + +/** +* @brief USBD_USR_Init +* Displays the message on LCD for host lib initialization +* @param None +* @retval None +*/ +void USBD_USR_Init() { + printf("USB OTG FS\n"); + printf("USB device start\n"); +} + +/** +* @brief USBD_USR_DeviceReset +* Displays the message on LCD on device Reset Event +* @param speed : device speed +* @retval None +*/ +void USBD_USR_DeviceReset(uint8_t speed) { + printf("USB reset %d\n", speed); +} + +/** +* @brief USBD_USR_DeviceConfigured +* Displays the message on LCD on device configuration Event +* @param None +* @retval Staus +*/ +void USBD_USR_DeviceConfigured() { + printf("USB dev config\n"); +} + +/** +* @brief USBD_USR_DeviceSuspended +* Displays the message on LCD on device suspend Event +* @param None +* @retval None +*/ +void USBD_USR_DeviceSuspended() { + printf("USB dev suspend\n"); +} + +/** +* @brief USBD_USR_DeviceResumed +* Displays the message on LCD on device resume Event +* @param None +* @retval None +*/ +void USBD_USR_DeviceResumed() { + printf("USB dev resume\n"); +} + + +/** +* @brief USBD_USR_DeviceConnected +* Displays the message on LCD on device connection Event +* @param None +* @retval Staus +*/ +void USBD_USR_DeviceConnected() { + printf("USB dev connect\n"); +} + + +/** +* @brief USBD_USR_DeviceDisonnected +* Displays the message on LCD on device disconnection Event +* @param None +* @retval Staus +*/ +void USBD_USR_DeviceDisconnected() { + printf("USB dev disconn\n"); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/lib/usbd_usr.h b/stm/lib/usbd_usr.h new file mode 100644 index 000000000..bd5ff3e2e --- /dev/null +++ b/stm/lib/usbd_usr.h @@ -0,0 +1,141 @@ +/** + ****************************************************************************** + * @file usbd_usr.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief Header file for usbd_usr.c + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_USR_H__ +#define __USBD_USR_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + + +/** @addtogroup USBD_USER + * @{ + */ + +/** @addtogroup USBD_MSC_DEMO_USER_CALLBACKS + * @{ + */ + +/** @defgroup USBD_USR + * @brief This file is the Header file for usbd_usr.c + * @{ + */ + + +/** @defgroup USBD_USR_Exported_Types + * @{ + */ + +extern USBD_Usr_cb_TypeDef USR_cb; +extern USBD_Usr_cb_TypeDef USR_FS_cb; +extern USBD_Usr_cb_TypeDef USR_HS_cb; + + + +/** + * @} + */ + + + +/** @defgroup USBD_USR_Exported_Defines + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_USR_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_USR_Exported_Variables + * @{ + */ + +void USBD_USR_Init(void); +void USBD_USR_DeviceReset (uint8_t speed); +void USBD_USR_DeviceConfigured (void); +void USBD_USR_DeviceSuspended(void); +void USBD_USR_DeviceResumed(void); + +void USBD_USR_DeviceConnected(void); +void USBD_USR_DeviceDisconnected(void); + +void USBD_USR_FS_Init(void); +void USBD_USR_FS_DeviceReset (uint8_t speed); +void USBD_USR_FS_DeviceConfigured (void); +void USBD_USR_FS_DeviceSuspended(void); +void USBD_USR_FS_DeviceResumed(void); + +void USBD_USR_FS_DeviceConnected(void); +void USBD_USR_FS_DeviceDisconnected(void); + +void USBD_USR_HS_Init(void); +void USBD_USR_HS_DeviceReset (uint8_t speed); +void USBD_USR_HS_DeviceConfigured (void); +void USBD_USR_HS_DeviceSuspended(void); +void USBD_USR_HS_DeviceResumed(void); + +void USBD_USR_HS_DeviceConnected(void); +void USBD_USR_HS_DeviceDisconnected(void); + +/** + * @} + */ + +/** @defgroup USBD_USR_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + +#endif /*__USBD_USR_H__*/ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + + diff --git a/stm/main.c b/stm/main.c new file mode 100644 index 000000000..2e7f2ec90 --- /dev/null +++ b/stm/main.c @@ -0,0 +1,829 @@ +#include +#include +#include "std.h" + +#include "font_petme128_8x8.h" + +void delay_ms(int ms); + +void impl02_c_version() { + int x = 0; + while (x < 400) { + int y = 0; + while (y < 400) { + volatile int z = 0; + while (z < 400) { + z = z + 1; + } + y = y + 1; + } + x = x + 1; + } +} + +void set_bits(__IO uint32_t *addr, uint32_t shift, uint32_t mask, uint32_t value) { + uint32_t x = *addr; + x &= ~(mask << shift); + x |= (value << shift); + *addr = x; +} + +void gpio_init() { + RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOAEN; +} + +#define PYB_LEDR_PORT (GPIOA) +#define PYB_LEDR1_PORT_NUM (8) +#define PYB_LEDR2_PORT_NUM (10) +#define PYB_LEDG_PORT (GPIOC) +#define PYB_LEDG1_PORT_NUM (4) +#define PYB_LEDG2_PORT_NUM (5) + +void gpio_pin_init(GPIO_TypeDef *gpio, uint32_t pin, uint32_t moder, uint32_t otyper, uint32_t ospeedr, uint32_t pupdr) { + set_bits(&gpio->MODER, 2 * pin, 3, moder); + set_bits(&gpio->OTYPER, pin, 1, otyper); + set_bits(&gpio->OSPEEDR, 2 * pin, 3, ospeedr); + set_bits(&gpio->PUPDR, 2 * pin, 3, pupdr); +} + +void gpio_pin_af(GPIO_TypeDef *gpio, uint32_t pin, uint32_t af) { + // set the AF bits for the given pin + // pins 0-7 use low word of AFR, pins 8-15 use high word + set_bits(&gpio->AFR[pin >> 3], 4 * (pin & 0x07), 0xf, af); +} + +void mma_init() { + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1 + gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); + gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */); + gpio_pin_af(GPIOB, 6, 4 /* AF 4 for I2C1 */); + gpio_pin_af(GPIOB, 7, 4 /* AF 4 for I2C1 */); + + // get clock speeds + RCC_ClocksTypeDef rcc_clocks; + RCC_GetClocksFreq(&rcc_clocks); + + // disable the I2C peripheral before we configure it + I2C1->CR1 &= ~I2C_CR1_PE; + + // program peripheral input clock + I2C1->CR2 = 4; // no interrupts; 4 MHz (hopefully!) (could go up to 42MHz) + + // configure clock control reg + uint32_t freq = rcc_clocks.PCLK1_Frequency / (100000 << 1); // want 100kHz, this is the formula for freq + I2C1->CCR = freq; // standard mode (speed), freq calculated as above + + // configure rise time reg + I2C1->TRISE = (rcc_clocks.PCLK1_Frequency / 1000000) + 1; // formula for trise, gives maximum rise time + + // enable the I2C peripheral + I2C1->CR1 |= I2C_CR1_PE; + + // set START bit in CR1 to generate a start cond! +} + +uint32_t i2c_get_sr() { + // must read SR1 first, then SR2, as the read can clear some flags + uint32_t sr1 = I2C1->SR1; + uint32_t sr2 = I2C1->SR2; + return (sr2 << 16) | sr1; +} + +void mma_restart(uint8_t addr, int write) { + // send start condition + I2C1->CR1 |= I2C_CR1_START; + + // wait for BUSY, MSL and SB --> Slave has acknowledged start condition + while ((i2c_get_sr() & 0x00030001) != 0x00030001) { + } + + if (write) { + // send address and write bit + I2C1->DR = (addr << 1) | 0; + // wait for BUSY, MSL, ADDR, TXE and TRA + while ((i2c_get_sr() & 0x00070082) != 0x00070082) { + } + } else { + // send address and read bit + I2C1->DR = (addr << 1) | 1; + // wait for BUSY, MSL and ADDR flags + while ((i2c_get_sr() & 0x00030002) != 0x00030002) { + } + } +} + +void mma_start(uint8_t addr, int write) { + // wait until I2C is not busy + while (I2C1->SR2 & I2C_SR2_BUSY) { + } + + // do rest of start + mma_restart(addr, write); +} + +void mma_send_byte(uint8_t data) { + // send byte + I2C1->DR = data; + // wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted) + int timeout = 1000000; + while ((i2c_get_sr() & 0x00070084) != 0x00070084) { + if (timeout-- <= 0) { + printf("mma_send_byte timed out!\n"); + break; + } + } +} + +uint8_t mma_read_ack() { + // enable ACK of received byte + I2C1->CR1 |= I2C_CR1_ACK; + // wait for BUSY, MSL and RXNE (byte received) + while ((i2c_get_sr() & 0x00030040) != 0x00030040) { + } + // read and return data + uint8_t data = I2C1->DR; + return data; +} + +uint8_t mma_read_nack() { + // disable ACK of received byte (to indicate end of receiving) + I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK); + // last byte should apparently also generate a stop condition + I2C1->CR1 |= I2C_CR1_STOP; + // wait for BUSY, MSL and RXNE (byte received) + while ((i2c_get_sr() & 0x00030040) != 0x00030040) { + } + // read and return data + uint8_t data = I2C1->DR; + return data; +} + +void mma_stop() { + // send stop condition + I2C1->CR1 |= I2C_CR1_STOP; +} + +void led_init() { + // set the output high (so LED is off) + PYB_LEDR_PORT->BSRRL = 1 << PYB_LEDR1_PORT_NUM; + PYB_LEDR_PORT->BSRRL = 1 << PYB_LEDR2_PORT_NUM; + PYB_LEDG_PORT->BSRRL = 1 << PYB_LEDG1_PORT_NUM; + PYB_LEDG_PORT->BSRRL = 1 << PYB_LEDG2_PORT_NUM; + // make it an open drain output + gpio_pin_init(PYB_LEDR_PORT, PYB_LEDR1_PORT_NUM, 1, 1, 0, 0); + gpio_pin_init(PYB_LEDR_PORT, PYB_LEDR2_PORT_NUM, 1, 1, 0, 0); + gpio_pin_init(PYB_LEDG_PORT, PYB_LEDG1_PORT_NUM, 1, 1, 0, 0); + gpio_pin_init(PYB_LEDG_PORT, PYB_LEDG2_PORT_NUM, 1, 1, 0, 0); +} + +static void led_state(uint32_t led_port, int s) { + if (s == 0) { + // LED off, output is high + if (led_port == PYB_LEDR1_PORT_NUM || led_port == PYB_LEDR2_PORT_NUM) { + PYB_LEDR_PORT->BSRRL = 1 << led_port; + } else { + PYB_LEDG_PORT->BSRRL = 1 << led_port; + } + } else { + // LED on, output is low + if (led_port == PYB_LEDR1_PORT_NUM || led_port == PYB_LEDR2_PORT_NUM) { + PYB_LEDR_PORT->BSRRH = 1 << led_port; + } else { + PYB_LEDG_PORT->BSRRH = 1 << led_port; + } + } +} + +#define PYB_USRSW_PORT (GPIOA) +#define PYB_USRSW_PORT_NUM (13) + +void sw_init() { + // make it an input with pull-up + gpio_pin_init(PYB_USRSW_PORT, PYB_USRSW_PORT_NUM, 0, 0, 0, 1); +} + +int sw_get() { + if (PYB_USRSW_PORT->IDR & (1 << PYB_USRSW_PORT_NUM)) { + // pulled high, so switch is not pressed + return 0; + } else { + // pulled low, so switch is pressed + return 1; + } +} + +#define PYB_LCD_PORT (GPIOA) +#define PYB_LCD_CS1_PIN (0) +#define PYB_LCD_RST_PIN (1) +#define PYB_LCD_A0_PIN (2) +#define PYB_LCD_SCL_PIN (3) +#define PYB_LCD_SI_PIN (4) + +static void lcd_comm_out(uint8_t i) { + delay_ms(0); + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_CS1_PIN; // CS=0; enable + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_A0_PIN; // A0=0; select instr reg + // send byte bigendian, latches on rising clock + for (uint32_t n = 0; n < 8; n++) { + delay_ms(0); + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SCL_PIN; // SCL=0 + if ((i & 0x80) == 0) { + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SI_PIN; // SI=0 + } else { + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SI_PIN; // SI=1 + } + i <<= 1; + delay_ms(0); + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SCL_PIN; // SCL=1 + } + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_CS1_PIN; // CS=1; disable + + /* + in Python, native types: + CS1_PIN(const) = 0 + n = int(0) + delay_ms(0) + PORT[word:BSRRH] = 1 << CS1_PIN + for n in range(0, 8): + delay_ms(0) + PORT[word:BSRRH] = 1 << SCL_PIN + if i & 0x80 == 0: + PORT[word:BSRRH] = 1 << SI_PIN + else: + PORT[word:BSRRL] = 1 << SI_PIN + i <<= 1 + delay_ms(0) + PORT[word:BSRRL] = 1 << SCL_PIN + */ +} + +static void lcd_data_out(uint8_t i) { + delay_ms(0); + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_CS1_PIN; // CS=0; enable + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_A0_PIN; // A0=1; select data reg + // send byte bigendian, latches on rising clock + for (uint32_t n = 0; n < 8; n++) { + delay_ms(0); + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SCL_PIN; // SCL=0 + if ((i & 0x80) == 0) { + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_SI_PIN; // SI=0 + } else { + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SI_PIN; // SI=1 + } + i <<= 1; + delay_ms(0); + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SCL_PIN; // SCL=1 + } + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_CS1_PIN; // CS=1; disable +} + +#define LCD_BUF_W (16) +#define LCD_BUF_H (4) +char lcd_buffer[LCD_BUF_W * LCD_BUF_H]; +int lcd_line; +int lcd_column; +int lcd_next_line; + +void lcd_print_strn(const char *str, unsigned int len) { + int redraw_min = lcd_line * LCD_BUF_W + lcd_column; + int redraw_max = redraw_min; + int did_new_line = 0; + for (; len > 0; len--, str++) { + // move to next line if needed + if (lcd_next_line) { + if (lcd_line + 1 < LCD_BUF_H) { + lcd_line += 1; + } else { + lcd_line = LCD_BUF_H - 1; + for (int i = 0; i < LCD_BUF_W * (LCD_BUF_H - 1); i++) { + lcd_buffer[i] = lcd_buffer[i + LCD_BUF_W]; + } + for (int i = 0; i < LCD_BUF_W; i++) { + lcd_buffer[LCD_BUF_W * (LCD_BUF_H - 1) + i] = ' '; + } + redraw_min = 0; + redraw_max = LCD_BUF_W * LCD_BUF_H; + } + lcd_next_line = 0; + lcd_column = 0; + did_new_line = 1; + } + if (*str == '\n') { + lcd_next_line = 1; + } else if (lcd_column >= LCD_BUF_W) { + lcd_next_line = 1; + str -= 1; + len += 1; + } else { + lcd_buffer[lcd_line * LCD_BUF_W + lcd_column] = *str; + lcd_column += 1; + int max = lcd_line * LCD_BUF_W + lcd_column; + if (max > redraw_max) { + redraw_max = max; + } + } + } + + int last_page = -1; + for (int i = redraw_min; i < redraw_max; i++) { + int page = i / LCD_BUF_W; + if (page != last_page) { + int offset = 8 * (i - (page * LCD_BUF_W)); + lcd_comm_out(0xb0 | page); // page address set + lcd_comm_out(0x10 | ((offset >> 4) & 0x0f)); // column address set upper + lcd_comm_out(0x00 | (offset & 0x0f)); // column address set lower + last_page = page; + } + int chr = lcd_buffer[i]; + if (chr < 32 || chr > 126) { + chr = 127; + } + const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8]; + for (int i = 0; i < 8; i++) { + lcd_data_out(chr_data[i]); + } + } + + if (did_new_line) { + delay_ms(200); + } +} + +static void lcd_init() { + // set the outputs high + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_CS1_PIN; + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_RST_PIN; + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_A0_PIN; + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SCL_PIN; + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_SI_PIN; + // make them push/pull outputs + gpio_pin_init(PYB_LCD_PORT, PYB_LCD_CS1_PIN, 1, 0, 0, 0); + gpio_pin_init(PYB_LCD_PORT, PYB_LCD_RST_PIN, 1, 0, 0, 0); + gpio_pin_init(PYB_LCD_PORT, PYB_LCD_A0_PIN, 1, 0, 0, 0); + gpio_pin_init(PYB_LCD_PORT, PYB_LCD_SCL_PIN, 1, 0, 0, 0); + gpio_pin_init(PYB_LCD_PORT, PYB_LCD_SI_PIN, 1, 0, 0, 0); + + // init the LCD + delay_ms(1); // wait a bit + PYB_LCD_PORT->BSRRH = 1 << PYB_LCD_RST_PIN; // RST=0; reset + delay_ms(1); // wait for reset; 2us min + PYB_LCD_PORT->BSRRL = 1 << PYB_LCD_RST_PIN; // RST=1; enable + delay_ms(1); // wait for reset; 2us min + lcd_comm_out(0xa0); // ADC select, normal + lcd_comm_out(0xc8); // common output mode select, reverse + lcd_comm_out(0xa2); // LCD bias set, 1/9 bias + lcd_comm_out(0x2f); // power control set, 0b111=(booster on, vreg on, vfollow on) + lcd_comm_out(0x21); // v0 voltage regulator internal resistor ratio set, 0b001=small + lcd_comm_out(0x81); // electronic volume mode set + lcd_comm_out(0x34); // electronic volume register set, 0b110100 + lcd_comm_out(0x40); // display start line set, 0 + lcd_comm_out(0xaf); // LCD display, on + + // clear display + for (int page = 0; page < 4; page++) { + lcd_comm_out(0xb0 | page); // page address set + lcd_comm_out(0x10); // column address set upper + lcd_comm_out(0x00); // column address set lower + for (int i = 0; i < 128; i++) { + lcd_data_out(0x00); + } + } + + for (int i = 0; i < LCD_BUF_H * LCD_BUF_W; i++) { + lcd_buffer[i] = ' '; + } + lcd_line = 0; + lcd_column = 0; + lcd_next_line = 0; +} + +void __fatal_error(const char *msg) { + lcd_print_strn("\nFATAL ERROR:\n", 14); + lcd_print_strn(msg, strlen(msg)); + + for (;;) { + led_state(PYB_LEDR1_PORT_NUM, 1); + led_state(PYB_LEDR2_PORT_NUM, 0); + delay_ms(150); + led_state(PYB_LEDR1_PORT_NUM, 0); + led_state(PYB_LEDR2_PORT_NUM, 1); + delay_ms(150); + } +} + +#include "misc.h" +#include "lexer.h" +#include "mpyconfig.h" +#include "parse.h" +#include "compile.h" +#include "runtime.h" + +/* +py_obj_t pyb_delay(py_obj_t count) { + delay_ms(rt_get_int(count)); + return py_const_none; +} + +py_obj_t pyb_led(py_obj_t state) { + led_state(PYB_LEDG1_PORT_NUM, rt_is_true(state)); + return state; +} + +py_obj_t pyb_sw() { + if (sw_get()) { + return py_const_true; + } else { + return py_const_false; + } +} +*/ + +#include "asmthumb.h" +typedef void (*fun_t)(); + +#include "ff.h" +FATFS fatfs0; + +int main() { + // should disable JTAG + + //qstr_init(); + //rt_init(); + + gpio_init(); + led_init(); + sw_init(); + lcd_init(); + + // print a message + printf(" micro py board\n"); + + // flash to indicate we are alive! + for (int i = 0; i < 2; i++) { + led_state(PYB_LEDR1_PORT_NUM, 1); + led_state(PYB_LEDR2_PORT_NUM, 0); + delay_ms(200); + led_state(PYB_LEDR1_PORT_NUM, 0); + led_state(PYB_LEDR2_PORT_NUM, 1); + delay_ms(200); + } + + led_state(PYB_LEDR1_PORT_NUM, 0); + led_state(PYB_LEDR2_PORT_NUM, 0); + led_state(PYB_LEDG1_PORT_NUM, 0); + led_state(PYB_LEDG2_PORT_NUM, 0); + + // get and print clock speeds + // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz + /* + { + RCC_ClocksTypeDef rcc_clocks; + RCC_GetClocksFreq(&rcc_clocks); + printf("S=%lu H=%lu P1=%lu P2=%lu\n", rcc_clocks.SYSCLK_Frequency, rcc_clocks.HCLK_Frequency, rcc_clocks.PCLK1_Frequency, rcc_clocks.PCLK2_Frequency); + delay_ms(1000); + } + */ + + /* + extern int _sidata; + extern int _sdata; + extern int _edata; + extern int _sbss; + extern int _ebss; + delay_ms(2000); + printf("_sidata=%04x\n", _sidata); + printf("_sdata=%04x\n", _sdata); + printf("_edata=%04x\n", _edata); + printf("_sbss=%04x\n", _sbss); + printf("_ebss=%04x\n", _ebss); + //printf("sizeof(int)=%d\n", sizeof(int)); // 4 + delay_ms(2000); + */ + + //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init + //delay_ms(1000); + + #if 0 + // Python! + if (0) { + //const char *pysrc = "def f():\n x=x+1\nprint(42)\n"; + const char *pysrc = + // impl01.py + /* + "x = 0\n" + "while x < 400:\n" + " y = 0\n" + " while y < 400:\n" + " z = 0\n" + " while z < 400:\n" + " z = z + 1\n" + " y = y + 1\n" + " x = x + 1\n"; + */ + // impl02.py + "#@micropython.native\n" + "def f():\n" + " x = 0\n" + " while x < 400:\n" + " y = 0\n" + " while y < 400:\n" + " z = 0\n" + " while z < 400:\n" + " z = z + 1\n" + " y = y + 1\n" + " x = x + 1\n" + "f()\n"; + /* + "print('in python!')\n" + "x = 0\n" + "while x < 4:\n" + " pyb_led(True)\n" + " pyb_delay(201)\n" + " pyb_led(False)\n" + " pyb_delay(201)\n" + " x = x + 1\n" + "print('press me!')\n" + "while True:\n" + " pyb_led(pyb_sw())\n"; + */ + /* + // impl16.py + "@micropython.asm_thumb\n" + "def delay(r0):\n" + " b(loop_entry)\n" + " label(loop1)\n" + " movw(r1, 55999)\n" + " label(loop2)\n" + " subs(r1, r1, 1)\n" + " cmp(r1, 0)\n" + " bgt(loop2)\n" + " subs(r0, r0, 1)\n" + " label(loop_entry)\n" + " cmp(r0, 0)\n" + " bgt(loop1)\n" + "print('in python!')\n" + "@micropython.native\n" + "def flash(n):\n" + " x = 0\n" + " while x < n:\n" + " pyb_led(True)\n" + " delay(249)\n" + " pyb_led(False)\n" + " delay(249)\n" + " x = x + 1\n" + "flash(20)\n"; + */ + + py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false); + + if (0) { + while (!py_lexer_is_kind(lex, PY_TOKEN_END)) { + py_token_show(py_lexer_cur(lex)); + py_lexer_to_next(lex); + delay_ms(1000); + } + } else { + // nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler + printf("lex; al=%u\n", m_get_total_bytes_allocated()); + delay_ms(1000); + py_parse_node_t pn = py_parse(lex, 0); + //printf("----------------\n"); + printf("pars;al=%u\n", m_get_total_bytes_allocated()); + delay_ms(1000); + //parse_node_show(pn, 0); + py_compile(pn); + printf("comp;al=%u\n", m_get_total_bytes_allocated()); + delay_ms(1000); + + if (1) { + // execute it! + + // add some functions to the python namespace + rt_store_name(qstr_from_str_static("pyb_delay"), rt_make_function_1(pyb_delay)); + rt_store_name(qstr_from_str_static("pyb_led"), rt_make_function_1(pyb_led)); + rt_store_name(qstr_from_str_static("pyb_sw"), rt_make_function_0(pyb_sw)); + + py_obj_t module_fun = rt_make_function_from_id(1); + + led_state(PYB_LEDG1_PORT_NUM, 1); + delay_ms(100); + led_state(PYB_LEDG1_PORT_NUM, 0); + py_obj_t ret = rt_call_function_0(module_fun); + led_state(PYB_LEDG1_PORT_NUM, 1); + delay_ms(100); + led_state(PYB_LEDG1_PORT_NUM, 0); + + printf("done! got: "); + py_obj_print(ret); + printf("\n"); + delay_ms(1000); + printf("nalloc=%u\n", m_get_total_bytes_allocated()); + delay_ms(1000); + } + } + } + #endif + + // benchmark C version of impl02.py + if (0) { + led_state(PYB_LEDG1_PORT_NUM, 1); + delay_ms(100); + led_state(PYB_LEDG1_PORT_NUM, 0); + impl02_c_version(); + led_state(PYB_LEDG1_PORT_NUM, 1); + delay_ms(100); + led_state(PYB_LEDG1_PORT_NUM, 0); + } + + // MMA testing + if (0) { + printf("1"); + mma_init(); + printf("2"); + mma_start(0x4c, 1); + printf("3"); + mma_send_byte(0); + printf("4"); + mma_stop(); + printf("5"); + mma_start(0x4c, 1); + printf("6"); + mma_send_byte(0); + printf("7"); + mma_restart(0x4c, 0); + for (int i = 0; i <= 0xa; i++) { + int data; + if (i == 0xa) { + data = mma_read_nack(); + } else { + data = mma_read_ack(); + } + printf(" %02x", data); + } + printf("\n"); + + mma_start(0x4c, 1); + mma_send_byte(7); // mode + mma_send_byte(1); // active mode + mma_stop(); + + for (;;) { + delay_ms(500); + + mma_start(0x4c, 1); + mma_send_byte(0); + mma_restart(0x4c, 0); + for (int i = 0; i <= 3; i++) { + int data; + if (i == 3) { + data = mma_read_nack(); + printf(" %02x\n", data); + } else { + data = mma_read_ack() & 0x3f; + if (data & 0x20) { + data |= 0xc0; + } + printf(" % 2d", data); + } + } + } + } + + // fatfs testing + if (1) { + FRESULT res = f_mount(&fatfs0, "0:", 1); + if (res == FR_OK) { + printf("mount success\n"); + } else if (res == FR_NO_FILESYSTEM) { + res = f_mkfs("0:", 0, 0); + if (res == FR_OK) { + printf("mkfs success\n"); + } else { + printf("mkfs fail %d\n", res); + } + } else { + printf("mount fail %d\n", res); + } + + // write a file + if (0) { + FIL fp; + f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS); + UINT n; + f_write(&fp, "# this is boot.py\n", 18, &n); + printf("wrote %d\n", n); + f_close(&fp); + } + + // read a file + if (1) { + FIL fp; + f_open(&fp, "0:/boot.py", FA_READ); + UINT n; + char buf[20]; + f_read(&fp, buf, 18, &n); + buf[n + 1] = 0; + printf("read %d\n%s", n, buf); + f_close(&fp); + } + + DWORD nclst; + FATFS *fatfs; + f_getfree("0:", &nclst, &fatfs); + printf("free=%d\n", nclst * fatfs->csize * 512); + + } + + // SD card testing + if (0) { + //sdio_init(); + } + + // USB VCP testing + if (0) { + //usb_vcp_init(); + } + + // USB MSC testing + if (1) { + void usb_msc_init(); + usb_msc_init(); + } + + int i = 0; + int n = 0; + + for (;;) { + delay_ms(10); + if (sw_get()) { + led_state(PYB_LEDR1_PORT_NUM, 1); + led_state(PYB_LEDG1_PORT_NUM, 0); + i = 1 - i; + if (i) { + printf(" angel %05x.\n", n); + //usb_vcp_send("hello!\r\n", 8); + } else { + printf(" mishka %4u.\n", n); + //usb_vcp_send("angel!\r\n", 8); + } + n += 1; + } else { + led_state(PYB_LEDR1_PORT_NUM, 0); + led_state(PYB_LEDG1_PORT_NUM, 1); + } + } + + return 0; +} + +/* +void testf() { + testf(1, 2, 3); + testf(1, 2, 3, 4); + testf(1, 2, 3, 4, 5); + testf(1, 2, 3, 4, 5, 6); + testf(1, 2, 3, 4, 5, 6, 7); +} + +int testg(int a, int b, int c, int d, int e) { + return a + b + c + d + testh(e); +} + +int testh(int x, byte *y) { + return x + (y[-2] << 2); +} +*/ + +/* +void print_int(int x, int y, int z, int zz) { + printf("I %x %x %x %x", x, y, z, zz); + byte* ptr = (byte*)z; + printf("\nP %02x %02x %02x %02x", ptr[-4], ptr[-3], ptr[-2], ptr[-1]); + for (;;) { + } +} +void print_int_0(int x) { printf("P0 %x", x); } +void print_int_1(int x) { printf("P1 %x", x); } +void print_int_2(int x) { printf("P2 %x", x); } +void print_int_3(int x) { printf("P3 %x", x); } +void print_int_4(int x) { printf("P4 %x", x); } + +typedef struct _b_t { + void (*m1)(void*, int); + void (*m2)(void*, int); +} b_t; +typedef struct _a_t { + b_t *b; +} a_t; +void b_m1(b_t*, int); +void b_m2(b_t*, int); +void f1(a_t *a) { + a->b->m1(a->b, 2); + a->b->m2(a->b, 4); + b_m1(a->b, 2); + b_m2(a->b, 4); +} +void b_m1(b_t *b, int x) { + b->m1(b, x); +} +*/ diff --git a/stm/malloc0.c b/stm/malloc0.c new file mode 100644 index 000000000..55c1ae804 --- /dev/null +++ b/stm/malloc0.c @@ -0,0 +1,38 @@ +#include +#include "std.h" + +static uint32_t mem = 0; + +void *malloc(size_t n) { + if (mem == 0) { + mem = 0x20008000; // need to use big ram block so we can execute code from it; start up a bit in case that's where bss is...? + } + void *ptr = (void*)mem; + mem = (mem + n + 3) & (~3); + if (mem > 0x20000000 + 0x18000) { + void __fatal_error(const char*); + __fatal_error("out of memory"); + } + return ptr; +} + +void free(void *ptr) { +} + +void *calloc(size_t sz, size_t n) { + char *ptr = malloc(sz * n); + for (int i = 0; i < sz * n; i++) { + ptr[i] = 0; + } + return ptr; +} + +void *realloc(void *ptr, size_t n) { + return malloc(n); +} + +void __assert_func() { + printf("\nASSERT FAIL!"); + for (;;) { + } +} diff --git a/stm/mpyconfig.h b/stm/mpyconfig.h new file mode 100644 index 000000000..b6179813d --- /dev/null +++ b/stm/mpyconfig.h @@ -0,0 +1,14 @@ +// options to control how Micro Python is built + +#define MICROPY_ENABLE_FLOAT (1) +#define MICROPY_EMIT_CPYTHON (0) +#define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_THUMB (1) +#define MICROPY_EMIT_INLINE_THUMB (1) + +// type definitions for the specific machine + +typedef int32_t machine_int_t; // must be pointer size +typedef uint32_t machine_uint_t; // must be pointer size +typedef void *machine_ptr_t; // must be of pointer size +typedef float machine_float_t; diff --git a/stm/printf.c b/stm/printf.c new file mode 100644 index 000000000..1cdb6a48f --- /dev/null +++ b/stm/printf.c @@ -0,0 +1,277 @@ +#include +#include "std.h" + +#define PF_FLAG_LEFT_ADJUST (0x01) +#define PF_FLAG_SHOW_SIGN (0x02) +#define PF_FLAG_SPACE_SIGN (0x04) +#define PF_FLAG_NO_TRAILZ (0x08) +#define PF_FLAG_ZERO_PAD (0x10) + +// tricky; we compute pad string by: pad_chars + (flags & PF_FLAG_ZERO_PAD) +#define PF_PAD_SIZE PF_FLAG_ZERO_PAD +static const char *pad_chars = " 0000000000000000"; + +typedef struct _pfenv_t { + void *data; + void (*print_strn)(void *, const char *str, unsigned int len); +} pfenv_t; + +static void print_str_dummy(void *data, const char *str, unsigned int len) { +} + +pfenv_t pfenv_dummy = {0, print_str_dummy}; + +static int pfenv_print_strn(pfenv_t *pfenv, const char *str, unsigned int len, int flags, int width) { + int pad = width - len; + if (pad > 0 && (flags & PF_FLAG_LEFT_ADJUST) == 0) { + while (pad > 0) { + int p = pad; + if (p > PF_PAD_SIZE) + p = PF_PAD_SIZE; + pfenv->print_strn(pfenv->data, pad_chars + (flags & PF_FLAG_ZERO_PAD), p); + pad -= p; + } + } + pfenv->print_strn(pfenv->data, str, len); + while (pad > 0) { + int p = pad; + if (p > PF_PAD_SIZE) + p = PF_PAD_SIZE; + pfenv->print_strn(pfenv->data, pad_chars, p); + pad -= p; + } + return len; +} + +// enough room for 32 signed number +#define INT_BUF_SIZE (12) + +static int pfenv_print_int(pfenv_t *pfenv, unsigned int x, int sgn, int base, int base_char, int flags, int width) { + char sign = 0; + if (sgn) { + if ((int)x < 0) { + sign = '-'; + x = -x; + } else if (flags & PF_FLAG_SHOW_SIGN) { + sign = '+'; + } else if (flags & PF_FLAG_SPACE_SIGN) { + sign = ' '; + } + } + + char buf[INT_BUF_SIZE]; + char *b = buf + INT_BUF_SIZE; + + if (x == 0) { + *(--b) = '0'; + } else { + do { + int c = x % base; + x /= base; + if (c >= 10) { + c += base_char - 10; + } else { + c += '0'; + } + *(--b) = c; + } while (b > buf && x != 0); + } + + if (b > buf && sign != 0) { + *(--b) = sign; + } + + return pfenv_print_strn(pfenv, b, buf + INT_BUF_SIZE - b, flags, width); +} + +void pfenv_prints(pfenv_t *pfenv, const char *str) { + pfenv->print_strn(pfenv->data, str, strlen(str)); +} + +int pfenv_printf(pfenv_t *pfenv, const char *fmt, va_list args) { + int chrs = 0; + for (;;) { + { + const char *f = fmt; + while (*f != '\0' && *f != '%') { + ++f; // XXX UTF8 advance char + } + if (f > fmt) { + pfenv->print_strn(pfenv->data, fmt, f - fmt); + chrs += f - fmt; + fmt = f; + } + } + + if (*fmt == '\0') { + break; + } + + // move past % character + ++fmt; + + // parse flags, if they exist + int flags = 0; + while (*fmt != '\0') { + if (*fmt == '-') flags |= PF_FLAG_LEFT_ADJUST; + else if (*fmt == '+') flags |= PF_FLAG_SHOW_SIGN; + else if (*fmt == ' ') flags |= PF_FLAG_SPACE_SIGN; + else if (*fmt == '!') flags |= PF_FLAG_NO_TRAILZ; + else if (*fmt == '0') flags |= PF_FLAG_ZERO_PAD; + else break; + ++fmt; + } + + // parse width, if it exists + int width = 0; + for (; '0' <= *fmt && *fmt <= '9'; ++fmt) { + width = width * 10 + *fmt - '0'; + } + + // parse precision, if it exists + int prec = -1; + if (*fmt == '.') { + ++fmt; + if (*fmt == '*') { + ++fmt; + prec = va_arg(args, int); + } else { + prec = 0; + for (; '0' <= *fmt && *fmt <= '9'; ++fmt) { + prec = prec * 10 + *fmt - '0'; + } + } + if (prec < 0) { + prec = 0; + } + } + + // parse long specifiers (current not used) + //bool long_arg = false; + if (*fmt == 'l') { + ++fmt; + //long_arg = true; + } + + if (*fmt == '\0') { + break; + } + + switch (*fmt) { + case 'b': + if (va_arg(args, int)) { + chrs += pfenv_print_strn(pfenv, "true", 4, flags, width); + } else { + chrs += pfenv_print_strn(pfenv, "false", 5, flags, width); + } + break; + case 'c': + { + char str = va_arg(args, int); + chrs += pfenv_print_strn(pfenv, &str, 1, flags, width); + break; + } + case 's': + { + const char *str = va_arg(args, const char*); + if (str) { + if (prec < 0) { + prec = strlen(str); + } + chrs += pfenv_print_strn(pfenv, str, prec, flags, width); + } else { + chrs += pfenv_print_strn(pfenv, "(null)", 6, flags, width); + } + break; + } + case 'u': + chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 10, 'a', flags, width); + break; + case 'd': + chrs += pfenv_print_int(pfenv, va_arg(args, int), 1, 10, 'a', flags, width); + break; + case 'x': + case 'p': // ? + chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'a', flags, width); + break; + case 'X': + case 'P': // ? + chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, width); + break; + default: + pfenv->print_strn(pfenv->data, fmt, 1); + chrs += 1; + break; + } + ++fmt; + } + return chrs; +} + +void lcd_print_strn(const char *str, unsigned int len); + +void xxx(void *data, const char *str, unsigned int len) { + lcd_print_strn(str, len); +} + +pfenv_t pfenv_stdout = {0, xxx}; + +int printf(const char *fmt, ...) { + //pfenv_t pfenv; + //pfenv.data = 0; + //pfenv.print_strn = xxx; + va_list args; + va_start(args, fmt); + return pfenv_printf(&pfenv_stdout, fmt, args); +} + +// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a') +int putchar(int c) { + char chr = c; + xxx(0, &chr, 1); + return chr; +} + +// need this because gcc optimises printf("string\n") -> puts("string") +int puts(const char *s) { + xxx(0, s, strlen(s)); + char chr = '\n'; + xxx(0, &chr, 1); + return 1; +} + +typedef struct _strn_pfenv_t { + char *cur; + size_t remain; +} strn_pfenv_t; + +void strn_print_strn(void *data, const char *str, unsigned int len) { + strn_pfenv_t *strn_pfenv = data; + if (len > strn_pfenv->remain) { + len = strn_pfenv->remain; + } + memcpy(strn_pfenv->cur, str, len); + strn_pfenv->cur += len; + strn_pfenv->remain -= len; +} + +int snprintf(char *str, size_t size, const char *fmt, ...) { + strn_pfenv_t strn_pfenv; + strn_pfenv.cur = str; + strn_pfenv.remain = size; + pfenv_t pfenv; + pfenv.data = &strn_pfenv; + pfenv.print_strn = strn_print_strn; + va_list args; + va_start(args, fmt); + int len = pfenv_printf(&pfenv, fmt, args); + // add terminating null byte + if (size > 0) { + if (strn_pfenv.remain == 0) { + strn_pfenv.cur[-1] = 0; + } else { + strn_pfenv.cur[0] = 0; + } + } + return len; +} diff --git a/stm/startup_stm32f40xx.s b/stm/startup_stm32f40xx.s new file mode 100644 index 000000000..194ebac35 --- /dev/null +++ b/stm/startup_stm32f40xx.s @@ -0,0 +1,515 @@ +/** + ****************************************************************************** + * @file startup_stm32f40xx.s + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief STM32F40xx/41xx Devices vector table for RIDE7 toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Configure the clock system and the external SRAM mounted on + * STM324xG-EVAL board to be used as data memory (optional, + * to be enabled by user) + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FSMC_IRQHandler /* FSMC */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_IRQHandler /* DCMI */ + .word CRYP_IRQHandler /* CRYP crypto */ + .word HASH_RNG_IRQHandler /* Hash and Rng */ + .word FPU_IRQHandler /* FPU */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FSMC_IRQHandler + .thumb_set FSMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_IRQHandler + .thumb_set DCMI_IRQHandler,Default_Handler + + .weak CRYP_IRQHandler + .thumb_set CRYP_IRQHandler,Default_Handler + + .weak HASH_RNG_IRQHandler + .thumb_set HASH_RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/std.h b/stm/std.h new file mode 100644 index 000000000..4b370ef28 --- /dev/null +++ b/stm/std.h @@ -0,0 +1,21 @@ +typedef unsigned int size_t; + +void __assert_func(); + +void *malloc(size_t n); +void free(void *ptr); +void *calloc(size_t sz, size_t n); +void *realloc(void *ptr, size_t n); + +void *memcpy(void *dest, const void *src, size_t n); +void *memset(void *s, int c, size_t n); + +int strlen(const char *str); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +char *strndup(const char *s, size_t n); +char *strcpy(char *dest, const char *src); +char *strcat(char *dest, const char *src); + +int printf(const char *fmt, ...); +int snprintf(char *str, size_t size, const char *fmt, ...); diff --git a/stm/stm32f405.ld b/stm/stm32f405.ld new file mode 100644 index 000000000..bab247457 --- /dev/null +++ b/stm/stm32f405.ld @@ -0,0 +1,118 @@ +/* + GNU linker script for STM32F405 +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x100000 /* 1 MiB */ + RAM_CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 0x010000 /* 64 KiB */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x020000 /* 128 KiB */ +} + +/* define stack size and heap size here */ +stack_size = 2048; +heap_size = 0x4000; /* 16KiB */ + +/* define beginning and ending of stack */ +_stack_start = ORIGIN(RAM) + LENGTH(RAM); +_stack_end = _stack_start - stack_size; +_estack = _stack_end; + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + /* *(.glue_7) */ /* glue arm to thumb code */ + /* *(.glue_7t) */ /* glue thumb to arm code */ + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >FLASH + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* Used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + . = ALIGN(4); + .heap : + { + _heap_start = .; + . = . + heap_size; + } > RAM + + . = ALIGN(4); + . = _stack_end; + .stack : + { + . = . + stack_size; + } > RAM + + /* Remove information from the standard libraries */ + /* + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + */ + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/stm/stm32fxxx_it.c b/stm/stm32fxxx_it.c new file mode 100644 index 000000000..a9a9e0247 --- /dev/null +++ b/stm/stm32fxxx_it.c @@ -0,0 +1,255 @@ +/** + ****************************************************************************** + * @file stm32fxxx_it.c + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief Main Interrupt Service Routines. + * This file provides all exceptions handler and peripherals interrupt + * service routine. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32fxxx_it.h" +#include "stm32f4xx_exti.h" +#include "usb_core.h" +//#include "usbd_core.h" + +//#include "usbd_cdc_core.h" + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +extern USB_OTG_CORE_HANDLE USB_OTG_dev; + +/* Private function prototypes -----------------------------------------------*/ +extern uint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev); + +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED +extern uint32_t USBD_OTG_EP1IN_ISR_Handler (USB_OTG_CORE_HANDLE *pdev); +extern uint32_t USBD_OTG_EP1OUT_ISR_Handler (USB_OTG_CORE_HANDLE *pdev); +#endif + +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************/ +/* Cortex-M Processor Exceptions Handlers */ +/******************************************************************************/ + +/** + * @brief This function handles NMI exception. + * @param None + * @retval None + */ +void NMI_Handler(void) +{ +} + +/** + * @brief This function handles Hard Fault exception. + * @param None + * @retval None + */ +void HardFault_Handler(void) +{ + /* Go to infinite loop when Hard Fault exception occurs */ + while (1) + { + } +} + +/** + * @brief This function handles Memory Manage exception. + * @param None + * @retval None + */ +void MemManage_Handler(void) +{ + /* Go to infinite loop when Memory Manage exception occurs */ + while (1) + { + } +} + +/** + * @brief This function handles Bus Fault exception. + * @param None + * @retval None + */ +void BusFault_Handler(void) +{ + /* Go to infinite loop when Bus Fault exception occurs */ + while (1) + { + } +} + +/** + * @brief This function handles Usage Fault exception. + * @param None + * @retval None + */ +void UsageFault_Handler(void) +{ + /* Go to infinite loop when Usage Fault exception occurs */ + while (1) + { + } +} + +/** + * @brief This function handles SVCall exception. + * @param None + * @retval None + */ +void SVC_Handler(void) +{ +} + +/** + * @brief This function handles Debug Monitor exception. + * @param None + * @retval None + */ +void DebugMon_Handler(void) +{ +} + +/** + * @brief This function handles PendSVC exception. + * @param None + * @retval None + */ +void PendSV_Handler(void) +{ +} + +/** + * @brief This function handles SysTick Handler. + * @param None + * @retval None + */ +void SysTick_Handler(void) +{ +} + +/** + * @brief This function handles EXTI15_10_IRQ Handler. + * @param None + * @retval None + */ +#ifdef USE_USB_OTG_FS +void OTG_FS_WKUP_IRQHandler(void) +{ + if(USB_OTG_dev.cfg.low_power) + { + *(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ; + SystemInit(); + USB_OTG_UngateClock(&USB_OTG_dev); + } + EXTI_ClearITPendingBit(EXTI_Line18); +} +#endif + +/** + * @brief This function handles EXTI15_10_IRQ Handler. + * @param None + * @retval None + */ +#ifdef USE_USB_OTG_HS +void OTG_HS_WKUP_IRQHandler(void) +{ + if(USB_OTG_dev.cfg.low_power) + { + *(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ; + SystemInit(); + USB_OTG_UngateClock(&USB_OTG_dev); + } + EXTI_ClearITPendingBit(EXTI_Line20); +} +#endif + +/** + * @brief This function handles OTG_HS Handler. + * @param None + * @retval None + */ +#ifdef USE_USB_OTG_HS +void OTG_HS_IRQHandler(void) +#else +void OTG_FS_IRQHandler(void) +#endif +{ + USBD_OTG_ISR_Handler (&USB_OTG_dev); +} + +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED +/** + * @brief This function handles EP1_IN Handler. + * @param None + * @retval None + */ +void OTG_HS_EP1_IN_IRQHandler(void) +{ + USBD_OTG_EP1IN_ISR_Handler (&USB_OTG_dev); +} + +/** + * @brief This function handles EP1_OUT Handler. + * @param None + * @retval None + */ +void OTG_HS_EP1_OUT_IRQHandler(void) +{ + USBD_OTG_EP1OUT_ISR_Handler (&USB_OTG_dev); +} +#endif + +/** + * @brief This function handles SDIO global interrupt request. + * @param None + * @retval None + */ +void SDIO_IRQHandler(void) +{ + /* Process All SDIO Interrupt Sources */ + //SD_ProcessIRQSrc(); +} + +/******************************************************************************/ +/* STM32Fxxx Peripherals Interrupt Handlers */ +/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ +/* available peripheral interrupt handler's name please refer to the startup */ +/* file (startup_stm32fxxx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles PPP interrupt request. + * @param None + * @retval None + */ +/*void PPP_IRQHandler(void) +{ +}*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/stm32fxxx_it.h b/stm/stm32fxxx_it.h new file mode 100644 index 000000000..230b1ac7b --- /dev/null +++ b/stm/stm32fxxx_it.h @@ -0,0 +1,60 @@ +/** + ****************************************************************************** + * @file stm32fxxx_it.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32Fxxx_IT_H +#define __STM32Fxxx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32Fxxx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/string0.c b/stm/string0.c new file mode 100644 index 000000000..6e2c252ea --- /dev/null +++ b/stm/string0.c @@ -0,0 +1,95 @@ +#include +#include "std.h" + +void *memcpy(void *dest, const void *src, size_t n) { + // TODO align and copy 32 bits at a time + uint8_t *d = dest; + const uint8_t *s = src; + for (; n > 0; n--) { + *d++ = *s++; + } + return dest; +} + +void *memset(void *s, int c, size_t n) { + uint8_t *s2 = s; + for (; n > 0; n--) { + *s2++ = c; + } + return s; +} + +int strlen(const char *str) { + int len = 0; + for (const char *s = str; *s; s++) { + len += 1; + } + return len; +} + +int strcmp(const char *s1, const char *s2) { + while (*s1 && *s2) { + char c1 = *s1++; // XXX UTF8 get char, next char + char c2 = *s2++; // XXX UTF8 get char, next char + if (c1 < c2) return -1; + else if (c1 > c2) return 1; + } + if (*s2) return -1; + else if (*s1) return 1; + else return 0; +} + +int strncmp(const char *s1, const char *s2, size_t n) { + while (*s1 && *s2 && n > 0) { + char c1 = *s1++; // XXX UTF8 get char, next char + char c2 = *s2++; // XXX UTF8 get char, next char + n--; + if (c1 < c2) return -1; + else if (c1 > c2) return 1; + } + if (n == 0) return 0; + else if (*s2) return -1; + else if (*s1) return 1; + else return 0; +} + +char *strndup(const char *s, size_t n) { + size_t len = strlen(s); + if (n > len) { + n = len; + } + char *s2 = malloc(n + 1); + memcpy(s2, s, n); + s2[n] = '\0'; + return s2; +} + +char *strcpy(char *dest, const char *src) { + char *d = dest; + while (*src) { + *d++ = *src++; + } + *d = '\0'; + return dest; +} + +// needed because gcc optimises strcpy + strcat to this +char *stpcpy(char *dest, const char *src) { + while (*src) { + *dest++ = *src++; + } + *dest = '\0'; + return dest; +} + +char *strcat(char *dest, const char *src) { + char *d = dest; + while (*d) { + d++; + } + while (*src) { + *d++ = *src++; + } + *d = '\0'; + return dest; +} diff --git a/stm/system_stm32f4xx.c b/stm/system_stm32f4xx.c new file mode 100644 index 000000000..7d13dbe8e --- /dev/null +++ b/stm/system_stm32f4xx.c @@ -0,0 +1,561 @@ +/** + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @version V1.1.0 + * @date 11-January-2013 + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * This file contains the system clock configuration for STM32F4xx devices, + * and is generated by the clock configuration tool + * stm32f4xx_Clock_Configuration_V1.1.0.xls + * + * 1. This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier + * and Divider factors, AHB/APBx prescalers and Flash settings), + * depending on the configuration made in the clock xls tool. + * This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * 2. After each device reset the HSI (16 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to + * configure the system clock before to branch to main program. + * + * 3. If the system clock source selected by user fails to startup, the SystemInit() + * function will do nothing and HSI still used as system clock source. User can + * add some code to deal with this issue inside the SetSysClock() function. + * + * 4. The default value of HSE crystal is set to 25MHz, refer to "HSE_VALUE" define + * in "stm32f4xx.h" file. When HSE is used as system clock source, directly or + * through PLL, and you are using different crystal you have to adapt the HSE + * value to your own configuration. + * + * 5. This file configures the system clock as follows: + *============================================================================= + *============================================================================= + * Supported STM32F40xx/41xx/427x/437x devices + *----------------------------------------------------------------------------- + * System Clock source | PLL (HSE) + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 4 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 2 + *----------------------------------------------------------------------------- + * HSE Frequency(Hz) | 8000000 changed dpgeorge + *----------------------------------------------------------------------------- + * PLL_M | 8 changed dpgeorge + *----------------------------------------------------------------------------- + * PLL_N | 336 + *----------------------------------------------------------------------------- + * PLL_P | 2 + *----------------------------------------------------------------------------- + * PLL_Q | 7 + *----------------------------------------------------------------------------- + * PLLI2S_N | NA + *----------------------------------------------------------------------------- + * PLLI2S_R | NA + *----------------------------------------------------------------------------- + * I2S input clock | NA + *----------------------------------------------------------------------------- + * VDD(V) | 3.3 + *----------------------------------------------------------------------------- + * Main regulator output voltage | Scale1 mode + *----------------------------------------------------------------------------- + * Flash Latency(WS) | 5 + *----------------------------------------------------------------------------- + * Prefetch Buffer | ON + *----------------------------------------------------------------------------- + * Instruction cache | ON + *----------------------------------------------------------------------------- + * Data cache | ON + *----------------------------------------------------------------------------- + * Require 48MHz for USB OTG FS, | Disabled + * SDIO and RNG clock | + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2013 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ + +#include "stm32f4xx.h" + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ +/*!< Uncomment the following line if you need to use external SRAM mounted + on STM324xG_EVAL/STM324x7I_EVAL boards as data memory */ +/* #define DATA_IN_ExtSRAM */ + +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ + +/************************* PLL Parameters *************************************/ +/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ +#define PLL_M 8 +#define PLL_N 336 + +/* SYSCLK = PLL_VCO / PLL_P */ +#define PLL_P 2 + +/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ +#define PLL_Q 7 + +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Variables + * @{ + */ + + uint32_t SystemCoreClock = 168000000; + + __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes + * @{ + */ + +static void SetSysClock(void); +#ifdef DATA_IN_ExtSRAM + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Set HSION bit */ + RCC->CR |= (uint32_t)0x00000001; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000; + + /* Reset HSEON, CSSON and PLLON bits */ + RCC->CR &= (uint32_t)0xFEF6FFFF; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x24003010; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Disable all interrupts */ + RCC->CIR = 0x00000000; + +#ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM */ + + /* Configure the System clock source, PLL Multiplier and Divider factors, + AHB/APBx prescalers and Flash settings ----------------------------------*/ + SetSysClock(); + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @brief Configures the System clock source, PLL Multiplier and Divider factors, + * AHB/APBx prescalers and Flash settings + * @Note This function should be called only once the RCC clock configuration + * is reset to the default reset state (done in SystemInit() function). + * @param None + * @retval None + */ +static void SetSysClock(void) +{ +/******************************************************************************/ +/* PLL (clocked by HSE) used as System clock source */ +/******************************************************************************/ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* Enable HSE */ + RCC->CR |= ((uint32_t)RCC_CR_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CR & RCC_CR_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CR & RCC_CR_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */ + RCC->APB1ENR |= RCC_APB1ENR_PWREN; + PWR->CR |= PWR_CR_VOS; + + /* HCLK = SYSCLK / 1*/ + RCC->CFGR |= RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK / 2*/ + RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; + + /* PCLK1 = HCLK / 4*/ + RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; + + /* Configure the main PLL */ + RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | + (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); + + /* Enable the main PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till the main PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ + FLASH->ACR = FLASH_ACR_PRFTEN |FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; + + /* Select the main PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= RCC_CFGR_SW_PLL; + + /* Wait till the main PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); + { + } + } + else + { /* If HSE fails to start-up, the application will have wrong clock + configuration. User can add here some code to deal with this error */ + } + +} + +/** + * @brief Setup the external memory controller. Called in startup_stm32f4xx.s + * before jump to __main + * @param None + * @retval None + */ +#ifdef DATA_IN_ExtSRAM +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external SRAM mounted on STM324xG_EVAL/STM324x7I boards + * This SRAM will be used as program data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ +/*-- GPIOs Configuration -----------------------------------------------------*/ +/* + +-------------------+--------------------+------------------+------------------+ + + SRAM pins assignment + + +-------------------+--------------------+------------------+------------------+ + | PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 | + | PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 | + | PD4 <-> FSMC_NOE | PE2 <-> FSMC_A23 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 | + | PD5 <-> FSMC_NWE | PE3 <-> FSMC_A19 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 | + | PD8 <-> FSMC_D13 | PE4 <-> FSMC_A20 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 | + | PD9 <-> FSMC_D14 | PE5 <-> FSMC_A21 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 | + | PD10 <-> FSMC_D15 | PE6 <-> FSMC_A22 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | + | PD11 <-> FSMC_A16 | PE7 <-> FSMC_D4 | PF13 <-> FSMC_A7 |------------------+ + | PD12 <-> FSMC_A17 | PE8 <-> FSMC_D5 | PF14 <-> FSMC_A8 | + | PD13 <-> FSMC_A18 | PE9 <-> FSMC_D6 | PF15 <-> FSMC_A9 | + | PD14 <-> FSMC_D0 | PE10 <-> FSMC_D7 |------------------+ + | PD15 <-> FSMC_D1 | PE11 <-> FSMC_D8 | + +-------------------| PE12 <-> FSMC_D9 | + | PE13 <-> FSMC_D10 | + | PE14 <-> FSMC_D11 | + | PE15 <-> FSMC_D12 | + +--------------------+ +*/ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR |= 0x00000078; + + /* Connect PDx pins to FSMC Alternate function */ + GPIOD->AFR[0] = 0x00cc00cc; + GPIOD->AFR[1] = 0xcccccccc; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xaaaa0a0a; + /* Configure PDx pins speed to 100 MHz */ + GPIOD->OSPEEDR = 0xffff0f0f; + /* Configure PDx pins Output type to push-pull */ + GPIOD->OTYPER = 0x00000000; + /* No pull-up, pull-down for PDx pins */ + GPIOD->PUPDR = 0x00000000; + + /* Connect PEx pins to FSMC Alternate function */ + GPIOE->AFR[0] = 0xcccccccc; + GPIOE->AFR[1] = 0xcccccccc; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xaaaaaaaa; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xffffffff; + /* Configure PEx pins Output type to push-pull */ + GPIOE->OTYPER = 0x00000000; + /* No pull-up, pull-down for PEx pins */ + GPIOE->PUPDR = 0x00000000; + + /* Connect PFx pins to FSMC Alternate function */ + GPIOF->AFR[0] = 0x00cccccc; + GPIOF->AFR[1] = 0xcccc0000; + /* Configure PFx pins in Alternate function mode */ + GPIOF->MODER = 0xaa000aaa; + /* Configure PFx pins speed to 100 MHz */ + GPIOF->OSPEEDR = 0xff000fff; + /* Configure PFx pins Output type to push-pull */ + GPIOF->OTYPER = 0x00000000; + /* No pull-up, pull-down for PFx pins */ + GPIOF->PUPDR = 0x00000000; + + /* Connect PGx pins to FSMC Alternate function */ + GPIOG->AFR[0] = 0x00cccccc; + GPIOG->AFR[1] = 0x000000c0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00080aaa; + /* Configure PGx pins speed to 100 MHz */ + GPIOG->OSPEEDR = 0x000c0fff; + /* Configure PGx pins Output type to push-pull */ + GPIOG->OTYPER = 0x00000000; + /* No pull-up, pull-down for PGx pins */ + GPIOG->PUPDR = 0x00000000; + +/*-- FSMC Configuration ------------------------------------------------------*/ + /* Enable the FSMC interface clock */ + RCC->AHB3ENR |= 0x00000001; + + /* Configure and enable Bank1_SRAM2 */ + FSMC_Bank1->BTCR[2] = 0x00001011; + FSMC_Bank1->BTCR[3] = 0x00000201; + FSMC_Bank1E->BWTR[2] = 0x0fffffff; +/* + Bank1_SRAM2 is configured as follow: + + p.FSMC_AddressSetupTime = 1; + p.FSMC_AddressHoldTime = 0; + p.FSMC_DataSetupTime = 2; + p.FSMC_BusTurnAroundDuration = 0; + p.FSMC_CLKDivision = 0; + p.FSMC_DataLatency = 0; + p.FSMC_AccessMode = FSMC_AccessMode_A; + + FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2; + FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; + FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; + FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; + FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; + FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; + FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; + FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; + FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; + FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; + FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p; + FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; +*/ +} +#endif /* DATA_IN_ExtSRAM */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/stm/usb.c b/stm/usb.c new file mode 100644 index 000000000..2987b45cc --- /dev/null +++ b/stm/usb.c @@ -0,0 +1,20 @@ +#include "usbd_cdc_core.h" +#include "usbd_msc_core.h" +#include "usbd_usr.h" +#include "usbd_desc.h" + +//extern CDC_IF_Prop_TypeDef APP_FOPS; + +USB_OTG_CORE_HANDLE USB_OTG_dev; + +void usb_vcp_init() { + //USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb); +} + +void usb_vcp_send(const char* str, int len) { + //APP_FOPS.pIf_DataTx(str, len); +} + +void usb_msc_init() { + USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_MSC_cb, &USR_cb); +}