├── Makefile ├── README.md ├── diskio.c ├── diskio.h ├── fdc_command_table.S ├── fdc_result_table.S ├── ff.c ├── ff.h ├── ffconf.h ├── integer.h ├── interrupt.S ├── main.c ├── main.h ├── misc_handlers.c ├── poller.S ├── roms └── README.md ├── startup_stm32f4xx.s ├── stm32_flash.ld ├── stm32f4_discovery.c ├── stm32f4_discovery.h ├── stm32f4_discovery_sdio_sd.c ├── stm32f4_discovery_sdio_sd.h ├── stm32f4xx_conf.h ├── stm32fxxx_it.c ├── stm32fxxx_it.h ├── system_stm32f4xx.c └── transfer.sh /Makefile: -------------------------------------------------------------------------------- 1 | # example disassemble 2 | # arm-none-eabi-objdump -dS stm32f4-rom-emulator.elf >asm.out 3 | 4 | # Put your stlink folder here so make burn will work. 5 | STLINK=~/stlink.git 6 | 7 | #SRCS=main.c system_stm32f4xx.c stm32f4xx_it.c 8 | #SRCS=main.c system_stm32f4xx.c working-stm32f4xx_it.c 9 | 10 | # 11 | # 12 | SRCS=diskio.c ff.c main.c stm32f4_discovery.c stm32f4_discovery_sdio_sd.c system_stm32f4xx.c misc_handlers.c 13 | 14 | # Library modules 15 | SRCS += stm32f4xx_syscfg.c misc.c stm32f4xx_gpio.c stm32f4xx_rcc.c stm32f4xx_usart.c stm32f4xx_sdio.c stm32f4xx_dma.c stm32f4xx_exti.c stm32f4xx_pwr.c 16 | #SRCS += stm32f4xx_tim.c 17 | #SRCS += stm32f4_discovery.c 18 | 19 | # Binaries will be generated with this name (.elf, .bin, .hex, etc) 20 | PROJ_NAME=amstradcpc-rom-emulator 21 | 22 | ####################################################################################### 23 | 24 | #STM_COMMON=../../.. 25 | # You need libs somewhere! 26 | STM_COMMON=../STM32F4-Discovery_FW_V1.1.0 27 | 28 | CC=arm-none-eabi-gcc 29 | OBJCOPY=arm-none-eabi-objcopy 30 | 31 | CFLAGS = -g -O2 -Wall -Tstm32_flash.ld 32 | CFLAGS += -DUSE_STDPERIPH_DRIVER 33 | CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork 34 | CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 35 | CFLAGS += -I. 36 | #CFLAGS += --specs=nosys.specs 37 | CFLAGS += -specs=nano.specs -specs=rdimon.specs -lc -lrdimon 38 | 39 | 40 | #CFLAGS += -DFDC_CMD_LOGGING 41 | #CFLAGS += -DFDC_STATUS_LOGGING 42 | #CFLAGS += -DFDC_READDATA_LOGGING 43 | #CFLAGS += -DFDC_LOGGING 44 | #CFLAGS += -DENABLE_SEMIHOSTING 45 | #CFLAGS += -DENABLE_SEMIHOSTING_SEEK 46 | #CFLAGS += -DENABLE_SEMIHOSTING_CHANGE_DISK 47 | #CFLAGS += -DENABLE_SEMIHOSTING_SECTOR_TABLE 48 | #CFLAGS += -DENABLE_SEMIHOSTING_DISK_INFO 49 | #CFLAGS += -DENABLE_SEMIHOSTING_SAVE_TRACK 50 | #CFLAGS += -DDBGIO 51 | #CFLAGS += -DDEBUG_MAIN 52 | #CFLAGS += -DDEBUG_ROMEN 53 | #CFLAGS += -DDEBUG_IORQ 54 | #CFLAGS += -DDEBUG_EXTI1 55 | #CFLAGS += -DDEBUG_EXTI4 56 | #CFLAGS += -DDEBUG_SPURIOUS_EVENT_MREQ 57 | #CFLAGS += -DDISABLE_ALL_BUT_SHOW_MAIN_THREAD_ACTIVITY 58 | 59 | # Include files from STM libraries 60 | CFLAGS += -I$(STM_COMMON)/Utilities/STM32F4-Discovery 61 | CFLAGS += -I$(STM_COMMON)/Libraries/CMSIS/Include 62 | CFLAGS += -I$(STM_COMMON)/Libraries/CMSIS/ST/STM32F4xx/Include 63 | CFLAGS += -I$(STM_COMMON)/Libraries/STM32F4xx_StdPeriph_Driver/inc 64 | 65 | 66 | # add startup file to build 67 | SRCS += startup_stm32f4xx.s 68 | # You need to end asm files in capital S to get them to see preprocessor directives 69 | SRCS += interrupt.S 70 | 71 | OBJS = $(SRCS:.c=.o) 72 | 73 | vpath %.c $(STM_COMMON)/Libraries/STM32F4xx_StdPeriph_Driver/src $(STM_COMMON)/Utilities/STM32F4-Discovery 74 | 75 | .PHONY: proj 76 | 77 | all: proj 78 | 79 | proj: $(PROJ_NAME).elf 80 | 81 | $(PROJ_NAME).elf: $(SRCS) 82 | $(CC) $(CFLAGS) $^ -o $@ 83 | $(OBJCOPY) -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex 84 | $(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin 85 | 86 | clean: 87 | rm -f *.o 88 | rm -f $(PROJ_NAME).elf 89 | rm -f $(PROJ_NAME).hex 90 | rm -f $(PROJ_NAME).bin 91 | 92 | 93 | # Flash the STM32F4 94 | #burn: proj 95 | # $(STLINK)/st-flash write $(PROJ_NAME).bin 0x8000000 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | amstradcpc-rom-emulator 2 | --------------------------------- 3 | kernel at kernelcrash dot com 4 | 5 | UPDATE: 20180613 - Now uses interrupts and should load whole disks track by 6 | track. More technical details on kernelcrash.com 7 | 8 | Sort of a proof of concept for using a cheap STM32F407 board directly attached to an Amstrad to emulate 9 | a few 'hardware components' 10 | 11 | - Can emulate a few ROMS. They appear as normal Amstrad 'external ROMs' 12 | - Can load floppy DSK image files from an SD card attached to the STM32F407 13 | - Simulates the NEC upd765 Floppy controller, so you think you are loading from a normal floppy drive 14 | - As it simulates the upd765, this is really just for a CPC464, unless you want to remove the upd765 15 | from your 6128 (and you might need to remove the AMSDOS rom too). 16 | 17 | Overview 18 | ======== 19 | 20 | - Get a cheap STM32F407 board off ebay/aliexpress/taobao. Look for STM32F407VGT6 or STM32F407VET6 for 21 | the cheaper boards. Also look for 2.54mm pin spacing. You can wire in an SD card adapter, or just 22 | get a board that has one already. So long as its wired in the standard way to use SDIO for 23 | a STM32F4 microcontroller, it should work. 24 | - Get a 50 pin edge connector and somehow just wire it directly in; 25 | 26 | - PD15 - PD8 - connect to D7 to D0 on Amstrad 27 | - PE15 - PE0 - connect to A15 to A0 on Amstrad 28 | - PC0 - Amstrad /WR 29 | - PC1 - Amstrad /IORQ 30 | - PC2 - Amstrad /ROMEN 31 | - PC3 - Amstrad ROMDIS 32 | - PC4 - Amstrad /MREQ 33 | 34 | - PA0 is a debug output for hooking up to a logic analyser to check timings, but is not connected 35 | normally 36 | 37 | - As mentioned, most STM32F4 boards with an SD card adapter are wired the same way. The important 38 | pins are: 39 | ``` 40 | /CS - PC11 41 | MOSI - PD2 42 | SCK - PC12 43 | 44 | MISO - PC8 45 | ``` 46 | - GND - Amstrad GND 47 | - +5V - Amstrad +5V 48 | 49 | - Get some ROMS. It can be reconfigured to have more than two roms, but to keep things simple, it 50 | will load two roms. One at ROM 6 , the other at ROM 7. The fact that it loads ROM 7, means you can't 51 | use this with a 6128 at the moment, as supposedly you cannot disable ROM 7 on a 6128. The other 52 | fact is ; that it emulates the upd765 floppy controller chip also means its limited to the CPC 464. 53 | 54 | I put the Maxam assembler as ROM 6 and either AMSDOS or Parados as ROM 7. ROM 7 has to be a Disk OS 55 | ROM. ROM 6 can be anything, but Maxam is quite handy for being able to type |HELP 56 | 57 | Just make sure you have two .incbin lines uncommented in the poller.S file referencing your roms. eg 58 | ``` 59 | rom_base: 60 | //.incbin "roms/Moon_Buggy.rom" 61 | .incbin "roms/maxam15.rom" 62 | .incbin "roms/parados12.rom" 63 | //.incbin "roms/AMSDOS_0.7.ROM" 64 | ``` 65 | The first .incbin line becomes ROM 6, the 2nd one becomes ROM 7 66 | 67 | - compile the code. I am using the STM32F4 Discovery std periph libraries from ST. The DSP one 68 | will probably work as well, so long as you update the STM_COMMON reference in the Makefile. 69 | I generally do this; 70 | ``` 71 | export PATH=/usr/local/gcc-arm-none-eabi-7-2017-q4-major/bin:$PATH 72 | make 73 | ``` 74 | You will end up with an elf and bin file. There is a transfer.sh file to help you use dfu-util 75 | to flash it to your board. You will need to set your BOOT0/1 jumpers appropriately first. 76 | 77 | - Format a micro SD card with FAT32. Make one partition (preferably under 4GB) at the start of the SD 78 | card. I just juse linux mkfs.vfat and its fine. 79 | 80 | - Get some Amstrad CPC DSK files and put them in the root of the SD card using this naming scheme 81 | ``` 82 | CPC000.DSK 83 | CPC001.DSK 84 | CPC002.DSK 85 | ``` 86 | Yep, I know its pretty ugly. This is 'proof of concept' territory. 87 | The older 'polling_version' branch could only load the first 96K of a disk. The current interrupt 88 | driven version can load whole disks track by track. 89 | 90 | Just try out some different games and see if they work. 91 | 92 | Using it 93 | ======== 94 | 95 | If you have say MAXAM and ParaDOS as the ROMs, then you should see 'MAXAM' and 'ParaDOS' in the 96 | Amstrad main screen when you power on. If you don't get the banners, check your wiring, try reseating 97 | the edge connector. 98 | 99 | Assuming you have your SD card plugged in and you have put at least one DSK file on it called CPC000.DSK, 100 | try doing this 101 | ``` 102 | |A 103 | CAT 104 | ``` 105 | If it's all working, you'll get a listing of whatever is on the CPC000.DSK image. 106 | 107 | If its a game, you generally see one file. You can generally use the one filename to load and run it. 108 | For example: 109 | ``` 110 | RUN "ELITE64E" 111 | ``` 112 | Now, if you want to change to using CPC001.DSK , or CPC002.DSK, do this 113 | ``` 114 | OUT &FB7E,1 115 | ``` 116 | Basically, write the DSK image number you want to FB7E. If you want CPC008.DSK, then ; 117 | ``` 118 | OUT &FB7E,8 119 | ``` 120 | You generally don't have to power off/on the Amstrad. Just do the usual to check the contents of A: 121 | have changed 122 | ``` 123 | |A 124 | CAT 125 | ``` 126 | For the informed, FB7E is usually used for reading data and status info from the upd765 floppy chip, 127 | but if you write to it, my code picks up the write and swaps to a new disk image. 128 | 129 | The DSK id (ie 0,1,2,3 etc) is stored in the 'backup SRAM' in the STM32F407, so if your board has a 130 | battery attached, then it should remember what image was last selected each time the board is 131 | powered on. If you don't have a battery, it will probably reset to id 0 (ie. CPC000.DSK). It is 132 | probably not very hard to either attach a battery or a large capacitor to VBAT . If you don't have 133 | a battery and you are sick of it resetting to CPC000.DSK after every power off/on, try powering the 134 | STM32F4 board from a USB cable (make sure +5V from the Amstrad is no longer connected to the STM32F4 135 | board). 136 | 137 | Note, if you are just trying to access ROMS, I'd suggest having MAXAM as one of the ROMS you load 138 | so you can type 139 | ``` 140 | |HELP 141 | ``` 142 | to list out the ROMS and their number, then you can do something like 143 | ``` 144 | |HELP,7 145 | ``` 146 | to show info on using ROM 7 etc. 147 | 148 | 149 | What doesn't work? 150 | ================== 151 | 152 | I haven't tested this greatly. If you are trying to read something with a lot of copy protection, then 153 | give up. I have only implemented 'some' of the functions of the upd765. There is a lot missing. I have 154 | pretty much only implemented the 'read data' function (which reads sectors), and a bunch of related 155 | functions. I have not implemented read track. There is write support ('WRITE DATA'), but I have not 156 | tested it greatly. 157 | 158 | But a lot of games do load. Just try stuff. 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* This is a stub disk I/O module that acts as front end of the existing */ 5 | /* disk I/O modules and attach it to FatFs module with common interface. */ 6 | /*-----------------------------------------------------------------------*/ 7 | 8 | #include "diskio.h" 9 | 10 | #include // memcpy 11 | 12 | #include "stm32f4xx.h" 13 | #include "stm32f4_discovery_sdio_sd.h" 14 | 15 | #define BLOCK_SIZE 512 /* Block Size in Bytes */ 16 | 17 | /*-----------------------------------------------------------------------*/ 18 | /* Inidialize a Drive */ 19 | 20 | DSTATUS disk_initialize ( 21 | BYTE drv /* Physical drive nmuber (0..) */ 22 | ) 23 | { 24 | DSTATUS stat = 0; 25 | 26 | #ifdef DBGIO 27 | printf("disk_initialize %d\n", drv); 28 | #endif 29 | 30 | /* Supports only single drive */ 31 | if (drv) 32 | { 33 | stat |= STA_NOINIT; 34 | } 35 | 36 | /*-------------------------- SD Init ----------------------------- */ 37 | if (SD_Init() !=SD_OK) 38 | { 39 | #ifdef DBGIO 40 | puts("Initialization Fail"); 41 | #endif 42 | stat |= STA_NOINIT; 43 | } 44 | 45 | return(stat); 46 | } 47 | 48 | 49 | 50 | /*-----------------------------------------------------------------------*/ 51 | /* Return Disk Status */ 52 | 53 | DSTATUS disk_status ( 54 | BYTE drv /* Physical drive nmuber (0..) */ 55 | ) 56 | { 57 | DSTATUS stat = 0; 58 | 59 | if (SD_Detect() != SD_PRESENT) 60 | stat |= STA_NODISK; 61 | 62 | // STA_NOTINIT - Subsystem not initailized 63 | // STA_PROTECTED - Write protected, MMC/SD switch if available 64 | 65 | return(stat); 66 | } 67 | 68 | 69 | 70 | /*-----------------------------------------------------------------------*/ 71 | /* Read Sector(s) */ 72 | 73 | DRESULT disk_read ( 74 | BYTE drv, /* Physical drive nmuber (0..) */ 75 | BYTE *buff, /* Data buffer to store read data */ 76 | DWORD sector, /* Sector address (LBA) */ 77 | BYTE count /* Number of sectors to read (1..255) */ 78 | ) 79 | { 80 | SD_Error Status; 81 | 82 | #ifdef DBGIO 83 | printf("disk_read %d %p %10d %d\n",drv,buff,sector,count); 84 | #endif 85 | 86 | if (SD_Detect() != SD_PRESENT) 87 | return(RES_NOTRDY); 88 | 89 | if ((DWORD)buff & 3) // DMA Alignment failure, do single up to aligned buffer 90 | { 91 | DRESULT res = RES_OK; 92 | DWORD scratch[BLOCK_SIZE / 4]; // Alignment assured, you'll need a sufficiently big stack 93 | 94 | while(count--) 95 | { 96 | res = disk_read(drv, (void *)scratch, sector++, 1); 97 | 98 | if (res != RES_OK) 99 | break; 100 | 101 | memcpy(buff, scratch, BLOCK_SIZE); 102 | 103 | buff += BLOCK_SIZE; 104 | } 105 | 106 | return(res); 107 | } 108 | 109 | Status = SD_ReadMultiBlocksFIXED(buff, sector, BLOCK_SIZE, count); // 4GB Compliant 110 | 111 | if (Status == SD_OK) 112 | { 113 | SDTransferState State; 114 | 115 | Status = SD_WaitReadOperation(); // Check if the Transfer is finished 116 | 117 | while((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL) 118 | 119 | if ((State == SD_TRANSFER_ERROR) || (Status != SD_OK)) 120 | return(RES_ERROR); 121 | else 122 | return(RES_OK); 123 | } 124 | else 125 | return(RES_ERROR); 126 | } 127 | 128 | /*-----------------------------------------------------------------------*/ 129 | /* Write Sector(s) */ 130 | 131 | #if _READONLY == 0 132 | DRESULT disk_write ( 133 | BYTE drv, /* Physical drive nmuber (0..) */ 134 | const BYTE *buff, /* Data to be written */ 135 | DWORD sector, /* Sector address (LBA) */ 136 | BYTE count /* Number of sectors to write (1..255) */ 137 | ) 138 | { 139 | SD_Error Status; 140 | 141 | #ifdef DBGIO 142 | printf("disk_write %d %p %10d %d\n",drv,buff,sector,count); 143 | #endif 144 | 145 | if (SD_Detect() != SD_PRESENT) 146 | return(RES_NOTRDY); 147 | 148 | if ((DWORD)buff & 3) // DMA Alignment failure, do single up to aligned buffer 149 | { 150 | DRESULT res = RES_OK; 151 | DWORD scratch[BLOCK_SIZE / 4]; // Alignment assured, you'll need a sufficiently big stack 152 | 153 | while(count--) 154 | { 155 | memcpy(scratch, buff, BLOCK_SIZE); 156 | 157 | res = disk_write(drv, (void *)scratch, sector++, 1); 158 | 159 | if (res != RES_OK) 160 | break; 161 | 162 | buff += BLOCK_SIZE; 163 | } 164 | 165 | return(res); 166 | } 167 | 168 | Status = SD_WriteMultiBlocksFIXED((uint8_t *)buff, sector, BLOCK_SIZE, count); // 4GB Compliant 169 | 170 | if (Status == SD_OK) 171 | { 172 | SDTransferState State; 173 | 174 | Status = SD_WaitWriteOperation(); // Check if the Transfer is finished 175 | 176 | while((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL) 177 | 178 | if ((State == SD_TRANSFER_ERROR) || (Status != SD_OK)) 179 | return(RES_ERROR); 180 | else 181 | return(RES_OK); 182 | } 183 | else 184 | return(RES_ERROR); 185 | } 186 | #endif /* _READONLY */ 187 | 188 | 189 | 190 | 191 | /*-----------------------------------------------------------------------*/ 192 | /* Miscellaneous Functions */ 193 | 194 | DRESULT disk_ioctl ( 195 | BYTE drv, /* Physical drive nmuber (0..) */ 196 | BYTE ctrl, /* Control code */ 197 | void *buff /* Buffer to send/receive control data */ 198 | ) 199 | { 200 | return RES_OK; 201 | } 202 | 203 | /*-----------------------------------------------------------------------*/ 204 | /* Get current time */ 205 | /*-----------------------------------------------------------------------*/ 206 | DWORD get_fattime(void){ 207 | return 0; 208 | } 209 | -------------------------------------------------------------------------------- /diskio.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------- 2 | / Low level disk interface modlue include file 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO 6 | 7 | #define _READONLY 0 /* 1: Remove write functions */ 8 | #define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */ 9 | 10 | #include "integer.h" 11 | 12 | 13 | /* Status of Disk Functions */ 14 | typedef BYTE DSTATUS; 15 | 16 | /* Results of Disk Functions */ 17 | typedef enum { 18 | RES_OK = 0, /* 0: Successful */ 19 | RES_ERROR, /* 1: R/W Error */ 20 | RES_WRPRT, /* 2: Write Protected */ 21 | RES_NOTRDY, /* 3: Not Ready */ 22 | RES_PARERR /* 4: Invalid Parameter */ 23 | } DRESULT; 24 | 25 | 26 | /*---------------------------------------*/ 27 | /* Prototypes for disk control functions */ 28 | 29 | int assign_drives (int, int); 30 | DSTATUS disk_initialize (BYTE); 31 | DSTATUS disk_status (BYTE); 32 | DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); 33 | #if _READONLY == 0 34 | DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); 35 | #endif 36 | DRESULT disk_ioctl (BYTE, BYTE, void*); 37 | 38 | 39 | 40 | /* Disk Status Bits (DSTATUS) */ 41 | 42 | #define STA_NOINIT 0x01 /* Drive not initialized */ 43 | #define STA_NODISK 0x02 /* No medium in the drive */ 44 | #define STA_PROTECT 0x04 /* Write protected */ 45 | 46 | 47 | /* Command code for disk_ioctrl fucntion */ 48 | 49 | /* Generic command (defined for FatFs) */ 50 | #define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ 51 | #define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ 52 | #define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ 53 | #define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ 54 | #define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ 55 | 56 | /* Generic command */ 57 | #define CTRL_POWER 5 /* Get/Set power status */ 58 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 59 | #define CTRL_EJECT 7 /* Eject media */ 60 | 61 | /* MMC/SDC specific ioctl command */ 62 | #define MMC_GET_TYPE 10 /* Get card type */ 63 | #define MMC_GET_CSD 11 /* Get CSD */ 64 | #define MMC_GET_CID 12 /* Get CID */ 65 | #define MMC_GET_OCR 13 /* Get OCR */ 66 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 67 | 68 | /* ATA/CF specific ioctl command */ 69 | #define ATA_GET_REV 20 /* Get F/W revision */ 70 | #define ATA_GET_MODEL 21 /* Get model name */ 71 | #define ATA_GET_SN 22 /* Get serial number */ 72 | 73 | /* NAND specific ioctl command */ 74 | #define NAND_FORMAT 30 /* Create physical format */ 75 | 76 | 77 | #define _DISKIO 78 | #endif 79 | -------------------------------------------------------------------------------- /fdc_command_table.S: -------------------------------------------------------------------------------- 1 | cmd_branchtable: 2 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x00 */ 3 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x01 */ 4 | .short ((cmd_0x02 - cmd_branchtable)/2) /* 0x02 */ 5 | .short ((cmd_0x03 - cmd_branchtable)/2) /* 0x03 */ 6 | .short ((cmd_0x04 - cmd_branchtable)/2) /* 0x04 */ 7 | .short ((cmd_0x05 - cmd_branchtable)/2) /* 0x05 */ 8 | .short ((cmd_0x06 - cmd_branchtable)/2) /* 0x06 */ 9 | .short ((cmd_0x07 - cmd_branchtable)/2) /* 0x07 */ 10 | .short ((cmd_0x08 - cmd_branchtable)/2) /* 0x08 */ 11 | .short ((cmd_0x09 - cmd_branchtable)/2) /* 0x09 */ 12 | .short ((cmd_0x0a - cmd_branchtable)/2) /* 0x0a */ 13 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x0b */ 14 | .short ((cmd_0x0c - cmd_branchtable)/2) /* 0x0c */ 15 | .short ((cmd_0x0d - cmd_branchtable)/2) /* 0x0d */ 16 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x0e */ 17 | .short ((cmd_0x0f - cmd_branchtable)/2) /* 0x0f */ 18 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x10 */ 19 | .short ((cmd_0x11 - cmd_branchtable)/2) /* 0x11 */ 20 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x12 */ 21 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x13 */ 22 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x14 */ 23 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x15 */ 24 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x16 */ 25 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x17 */ 26 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x18 */ 27 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x19 */ 28 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x1a */ 29 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x1b */ 30 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x1c */ 31 | .short ((cmd_0x1d - cmd_branchtable)/2) /* 0x1d */ 32 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x1e */ 33 | .short ((cmd_unused - cmd_branchtable)/2) /* 0x1f */ 34 | -------------------------------------------------------------------------------- /fdc_result_table.S: -------------------------------------------------------------------------------- 1 | result_branchtable: 2 | .short ((result_unused - result_branchtable)/2) /* 0x00 */ 3 | .short ((result_unused - result_branchtable)/2) /* 0x01 */ 4 | .short ((result_0x02 - result_branchtable)/2) /* 0x02 */ 5 | .short ((result_0x03 - result_branchtable)/2) /* 0x03 */ 6 | .short ((result_0x04 - result_branchtable)/2) /* 0x04 */ 7 | .short ((result_0x05 - result_branchtable)/2) /* 0x05 */ 8 | .short ((result_0x06 - result_branchtable)/2) /* 0x06 */ 9 | .short ((result_0x07 - result_branchtable)/2) /* 0x07 */ 10 | .short ((result_0x08 - result_branchtable)/2) /* 0x08 */ 11 | .short ((result_0x09 - result_branchtable)/2) /* 0x09 */ 12 | .short ((result_0x0a - result_branchtable)/2) /* 0x0a */ 13 | .short ((result_unused - result_branchtable)/2) /* 0x0b */ 14 | .short ((result_0x0c - result_branchtable)/2) /* 0x0c */ 15 | .short ((result_0x0d - result_branchtable)/2) /* 0x0d */ 16 | .short ((result_unused - result_branchtable)/2) /* 0x0e */ 17 | .short ((result_0x0f - result_branchtable)/2) /* 0x0f */ 18 | .short ((result_unused - result_branchtable)/2) /* 0x10 */ 19 | .short ((result_0x11 - result_branchtable)/2) /* 0x11 */ 20 | .short ((result_unused - result_branchtable)/2) /* 0x12 */ 21 | .short ((result_unused - result_branchtable)/2) /* 0x13 */ 22 | .short ((result_unused - result_branchtable)/2) /* 0x14 */ 23 | .short ((result_unused - result_branchtable)/2) /* 0x15 */ 24 | .short ((result_unused - result_branchtable)/2) /* 0x16 */ 25 | .short ((result_unused - result_branchtable)/2) /* 0x17 */ 26 | .short ((result_unused - result_branchtable)/2) /* 0x18 */ 27 | .short ((result_unused - result_branchtable)/2) /* 0x19 */ 28 | .short ((result_unused - result_branchtable)/2) /* 0x1a */ 29 | .short ((result_unused - result_branchtable)/2) /* 0x1b */ 30 | .short ((result_unused - result_branchtable)/2) /* 0x1c */ 31 | .short ((result_0x1d - result_branchtable)/2) /* 0x1d */ 32 | .short ((result_unused - result_branchtable)/2) /* 0x1e */ 33 | .short ((result_unused - result_branchtable)/2) /* 0x1f */ 34 | -------------------------------------------------------------------------------- /ff.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------/ 2 | / FatFs - Generic FAT Filesystem module R0.13b / 3 | /-----------------------------------------------------------------------------/ 4 | / 5 | / Copyright (C) 2018, ChaN, all right reserved. 6 | / 7 | / FatFs module is an open source software. Redistribution and use of FatFs in 8 | / source and binary forms, with or without modification, are permitted provided 9 | / that the following condition is met: 10 | 11 | / 1. Redistributions of source code must retain the above copyright notice, 12 | / this condition and the following disclaimer. 13 | / 14 | / This software is provided by the copyright holder and contributors "AS IS" 15 | / and any warranties related to this software are DISCLAIMED. 16 | / The copyright owner or contributors be NOT LIABLE for any damages caused 17 | / by use of this software. 18 | / 19 | /----------------------------------------------------------------------------*/ 20 | 21 | 22 | #ifndef FF_DEFINED 23 | #define FF_DEFINED 63463 /* Revision ID */ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #include "integer.h" /* Basic integer types */ 30 | #include "ffconf.h" /* FatFs configuration options */ 31 | 32 | #if FF_DEFINED != FFCONF_DEF 33 | #error Wrong configuration file (ffconf.h). 34 | #endif 35 | 36 | 37 | 38 | /* Definitions of volume management */ 39 | 40 | #if FF_MULTI_PARTITION /* Multiple partition configuration */ 41 | typedef struct { 42 | BYTE pd; /* Physical drive number */ 43 | BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ 44 | } PARTITION; 45 | extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ 46 | #endif 47 | 48 | #if FF_STR_VOLUME_ID 49 | #ifndef FF_VOLUME_STRS 50 | extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ 51 | #endif 52 | #endif 53 | 54 | 55 | 56 | /* Type of path name strings on FatFs API */ 57 | 58 | #ifndef _INC_TCHAR 59 | #define _INC_TCHAR 60 | 61 | #if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ 62 | typedef WCHAR TCHAR; 63 | #define _T(x) L ## x 64 | #define _TEXT(x) L ## x 65 | #elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ 66 | typedef char TCHAR; 67 | #define _T(x) u8 ## x 68 | #define _TEXT(x) u8 ## x 69 | #elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ 70 | typedef DWORD TCHAR; 71 | #define _T(x) U ## x 72 | #define _TEXT(x) U ## x 73 | #elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) 74 | #error Wrong FF_LFN_UNICODE setting 75 | #else /* ANSI/OEM code in SBCS/DBCS */ 76 | typedef char TCHAR; 77 | #define _T(x) x 78 | #define _TEXT(x) x 79 | #endif 80 | 81 | #endif 82 | 83 | 84 | 85 | /* Type of file size variables */ 86 | 87 | #if FF_FS_EXFAT 88 | typedef QWORD FSIZE_t; 89 | #else 90 | typedef DWORD FSIZE_t; 91 | #endif 92 | 93 | 94 | 95 | /* Filesystem object structure (FATFS) */ 96 | 97 | typedef struct { 98 | BYTE fs_type; /* Filesystem type (0:N/A) */ 99 | BYTE pdrv; /* Physical drive number */ 100 | BYTE n_fats; /* Number of FATs (1 or 2) */ 101 | BYTE wflag; /* win[] flag (b0:dirty) */ 102 | BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ 103 | WORD id; /* Volume mount ID */ 104 | WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ 105 | WORD csize; /* Cluster size [sectors] */ 106 | #if FF_MAX_SS != FF_MIN_SS 107 | WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ 108 | #endif 109 | #if FF_USE_LFN 110 | WCHAR* lfnbuf; /* LFN working buffer */ 111 | #endif 112 | #if FF_FS_EXFAT 113 | BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ 114 | #endif 115 | #if FF_FS_REENTRANT 116 | FF_SYNC_t sobj; /* Identifier of sync object */ 117 | #endif 118 | #if !FF_FS_READONLY 119 | DWORD last_clst; /* Last allocated cluster */ 120 | DWORD free_clst; /* Number of free clusters */ 121 | #endif 122 | #if FF_FS_RPATH 123 | DWORD cdir; /* Current directory start cluster (0:root) */ 124 | #if FF_FS_EXFAT 125 | DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ 126 | DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ 127 | DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ 128 | #endif 129 | #endif 130 | DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ 131 | DWORD fsize; /* Size of an FAT [sectors] */ 132 | DWORD volbase; /* Volume base sector */ 133 | DWORD fatbase; /* FAT base sector */ 134 | DWORD dirbase; /* Root directory base sector/cluster */ 135 | DWORD database; /* Data base sector */ 136 | DWORD winsect; /* Current sector appearing in the win[] */ 137 | BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ 138 | } FATFS; 139 | 140 | 141 | 142 | /* Object ID and allocation information (FFOBJID) */ 143 | 144 | typedef struct { 145 | FATFS* fs; /* Pointer to the hosting volume of this object */ 146 | WORD id; /* Hosting volume mount ID */ 147 | BYTE attr; /* Object attribute */ 148 | BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */ 149 | DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ 150 | FSIZE_t objsize; /* Object size (valid when sclust != 0) */ 151 | #if FF_FS_EXFAT 152 | DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ 153 | DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ 154 | DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ 155 | DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ 156 | DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ 157 | #endif 158 | #if FF_FS_LOCK 159 | UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ 160 | #endif 161 | } FFOBJID; 162 | 163 | 164 | 165 | /* File object structure (FIL) */ 166 | 167 | typedef struct { 168 | FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ 169 | BYTE flag; /* File status flags */ 170 | BYTE err; /* Abort flag (error code) */ 171 | FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ 172 | DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ 173 | DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ 174 | #if !FF_FS_READONLY 175 | DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ 176 | BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ 177 | #endif 178 | #if FF_USE_FASTSEEK 179 | DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ 180 | #endif 181 | #if !FF_FS_TINY 182 | BYTE buf[FF_MAX_SS]; /* File private data read/write window */ 183 | #endif 184 | } FIL; 185 | 186 | 187 | 188 | /* Directory object structure (DIR) */ 189 | 190 | typedef struct { 191 | FFOBJID obj; /* Object identifier */ 192 | DWORD dptr; /* Current read/write offset */ 193 | DWORD clust; /* Current cluster */ 194 | DWORD sect; /* Current sector (0:Read operation has terminated) */ 195 | BYTE* dir; /* Pointer to the directory item in the win[] */ 196 | BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ 197 | #if FF_USE_LFN 198 | DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ 199 | #endif 200 | #if FF_USE_FIND 201 | const TCHAR* pat; /* Pointer to the name matching pattern */ 202 | #endif 203 | } DIR; 204 | 205 | 206 | 207 | /* File information structure (FILINFO) */ 208 | 209 | typedef struct { 210 | FSIZE_t fsize; /* File size */ 211 | WORD fdate; /* Modified date */ 212 | WORD ftime; /* Modified time */ 213 | BYTE fattrib; /* File attribute */ 214 | #if FF_USE_LFN 215 | TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */ 216 | TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ 217 | #else 218 | TCHAR fname[12 + 1]; /* File name */ 219 | #endif 220 | } FILINFO; 221 | 222 | 223 | 224 | /* File function return code (FRESULT) */ 225 | 226 | typedef enum { 227 | FR_OK = 0, /* (0) Succeeded */ 228 | FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ 229 | FR_INT_ERR, /* (2) Assertion failed */ 230 | FR_NOT_READY, /* (3) The physical drive cannot work */ 231 | FR_NO_FILE, /* (4) Could not find the file */ 232 | FR_NO_PATH, /* (5) Could not find the path */ 233 | FR_INVALID_NAME, /* (6) The path name format is invalid */ 234 | FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ 235 | FR_EXIST, /* (8) Access denied due to prohibited access */ 236 | FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ 237 | FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ 238 | FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ 239 | FR_NOT_ENABLED, /* (12) The volume has no work area */ 240 | FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ 241 | FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ 242 | FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ 243 | FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ 244 | FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ 245 | FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ 246 | FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ 247 | } FRESULT; 248 | 249 | 250 | 251 | /*--------------------------------------------------------------*/ 252 | /* FatFs module application interface */ 253 | 254 | FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ 255 | FRESULT f_close (FIL* fp); /* Close an open file object */ 256 | FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ 257 | FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ 258 | FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ 259 | FRESULT f_truncate (FIL* fp); /* Truncate the file */ 260 | FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ 261 | FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ 262 | FRESULT f_closedir (DIR* dp); /* Close an open directory */ 263 | FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ 264 | FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ 265 | FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ 266 | FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ 267 | FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ 268 | FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ 269 | FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ 270 | FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ 271 | FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ 272 | FRESULT f_chdir (const TCHAR* path); /* Change current directory */ 273 | FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ 274 | FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ 275 | FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ 276 | FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ 277 | FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ 278 | FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ 279 | FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ 280 | FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ 281 | FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ 282 | FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ 283 | FRESULT f_setcp (WORD cp); /* Set current code page */ 284 | int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ 285 | int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ 286 | int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ 287 | TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ 288 | 289 | #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) 290 | #define f_error(fp) ((fp)->err) 291 | #define f_tell(fp) ((fp)->fptr) 292 | #define f_size(fp) ((fp)->obj.objsize) 293 | #define f_rewind(fp) f_lseek((fp), 0) 294 | #define f_rewinddir(dp) f_readdir((dp), 0) 295 | #define f_rmdir(path) f_unlink(path) 296 | #define f_unmount(path) f_mount(0, path, 0) 297 | 298 | #ifndef EOF 299 | #define EOF (-1) 300 | #endif 301 | 302 | 303 | 304 | 305 | /*--------------------------------------------------------------*/ 306 | /* Additional user defined functions */ 307 | 308 | /* RTC function */ 309 | #if !FF_FS_READONLY && !FF_FS_NORTC 310 | DWORD get_fattime (void); 311 | #endif 312 | 313 | /* LFN support functions */ 314 | #if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ 315 | WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ 316 | WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ 317 | DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ 318 | #endif 319 | #if FF_USE_LFN == 3 /* Dynamic memory allocation */ 320 | void* ff_memalloc (UINT msize); /* Allocate memory block */ 321 | void ff_memfree (void* mblock); /* Free memory block */ 322 | #endif 323 | 324 | /* Sync functions */ 325 | #if FF_FS_REENTRANT 326 | int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ 327 | int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ 328 | void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ 329 | int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ 330 | #endif 331 | 332 | 333 | 334 | 335 | /*--------------------------------------------------------------*/ 336 | /* Flags and offset address */ 337 | 338 | 339 | /* File access mode and open method flags (3rd argument of f_open) */ 340 | #define FA_READ 0x01 341 | #define FA_WRITE 0x02 342 | #define FA_OPEN_EXISTING 0x00 343 | #define FA_CREATE_NEW 0x04 344 | #define FA_CREATE_ALWAYS 0x08 345 | #define FA_OPEN_ALWAYS 0x10 346 | #define FA_OPEN_APPEND 0x30 347 | 348 | /* Fast seek controls (2nd argument of f_lseek) */ 349 | #define CREATE_LINKMAP ((FSIZE_t)0 - 1) 350 | 351 | /* Format options (2nd argument of f_mkfs) */ 352 | #define FM_FAT 0x01 353 | #define FM_FAT32 0x02 354 | #define FM_EXFAT 0x04 355 | #define FM_ANY 0x07 356 | #define FM_SFD 0x08 357 | 358 | /* Filesystem type (FATFS.fs_type) */ 359 | #define FS_FAT12 1 360 | #define FS_FAT16 2 361 | #define FS_FAT32 3 362 | #define FS_EXFAT 4 363 | 364 | /* File attribute bits for directory entry (FILINFO.fattrib) */ 365 | #define AM_RDO 0x01 /* Read only */ 366 | #define AM_HID 0x02 /* Hidden */ 367 | #define AM_SYS 0x04 /* System */ 368 | #define AM_DIR 0x10 /* Directory */ 369 | #define AM_ARC 0x20 /* Archive */ 370 | 371 | 372 | #ifdef __cplusplus 373 | } 374 | #endif 375 | 376 | #endif /* FF_DEFINED */ 377 | -------------------------------------------------------------------------------- /ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - Configuration file 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define FFCONF_DEF 63463 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Function Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define FF_FS_READONLY 0 12 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 13 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 14 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 15 | / and optional writing functions as well. */ 16 | 17 | 18 | #define FF_FS_MINIMIZE 0 19 | /* This option defines minimization level to remove some basic API functions. 20 | / 21 | / 0: Basic functions are fully enabled. 22 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() 23 | / are removed. 24 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 25 | / 3: f_lseek() function is removed in addition to 2. */ 26 | 27 | 28 | #define FF_USE_STRFUNC 1 29 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). 30 | / 31 | / 0: Disable string functions. 32 | / 1: Enable without LF-CRLF conversion. 33 | / 2: Enable with LF-CRLF conversion. */ 34 | 35 | 36 | #define FF_USE_FIND 0 37 | /* This option switches filtered directory read functions, f_findfirst() and 38 | / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ 39 | 40 | 41 | #define FF_USE_MKFS 0 42 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 43 | 44 | 45 | #define FF_USE_FASTSEEK 0 46 | /* This option switches fast seek function. (0:Disable or 1:Enable) */ 47 | 48 | 49 | #define FF_USE_EXPAND 0 50 | /* This option switches f_expand function. (0:Disable or 1:Enable) */ 51 | 52 | 53 | #define FF_USE_CHMOD 0 54 | /* This option switches attribute manipulation functions, f_chmod() and f_utime(). 55 | / (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ 56 | 57 | 58 | #define FF_USE_LABEL 0 59 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 60 | / (0:Disable or 1:Enable) */ 61 | 62 | 63 | #define FF_USE_FORWARD 0 64 | /* This option switches f_forward() function. (0:Disable or 1:Enable) */ 65 | 66 | 67 | /*---------------------------------------------------------------------------/ 68 | / Locale and Namespace Configurations 69 | /---------------------------------------------------------------------------*/ 70 | 71 | #define FF_CODE_PAGE 932 72 | /* This option specifies the OEM code page to be used on the target system. 73 | / Incorrect code page setting can cause a file open failure. 74 | / 75 | / 437 - U.S. 76 | / 720 - Arabic 77 | / 737 - Greek 78 | / 771 - KBL 79 | / 775 - Baltic 80 | / 850 - Latin 1 81 | / 852 - Latin 2 82 | / 855 - Cyrillic 83 | / 857 - Turkish 84 | / 860 - Portuguese 85 | / 861 - Icelandic 86 | / 862 - Hebrew 87 | / 863 - Canadian French 88 | / 864 - Arabic 89 | / 865 - Nordic 90 | / 866 - Russian 91 | / 869 - Greek 2 92 | / 932 - Japanese (DBCS) 93 | / 936 - Simplified Chinese (DBCS) 94 | / 949 - Korean (DBCS) 95 | / 950 - Traditional Chinese (DBCS) 96 | / 0 - Include all code pages above and configured by f_setcp() 97 | */ 98 | 99 | 100 | #define FF_USE_LFN 0 101 | #define FF_MAX_LFN 255 102 | /* The FF_USE_LFN switches the support for LFN (long file name). 103 | / 104 | / 0: Disable LFN. FF_MAX_LFN has no effect. 105 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 106 | / 2: Enable LFN with dynamic working buffer on the STACK. 107 | / 3: Enable LFN with dynamic working buffer on the HEAP. 108 | / 109 | / To enable the LFN, ffunicode.c needs to be added to the project. The LFN function 110 | / requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and 111 | / additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. 112 | / The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can 113 | / be in range of 12 to 255. It is recommended to be set 255 to fully support LFN 114 | / specification. 115 | / When use stack for the working buffer, take care on stack overflow. When use heap 116 | / memory for the working buffer, memory management functions, ff_memalloc() and 117 | / ff_memfree() in ffsystem.c, need to be added to the project. */ 118 | 119 | 120 | #define FF_LFN_UNICODE 0 121 | /* This option switches the character encoding on the API when LFN is enabled. 122 | / 123 | / 0: ANSI/OEM in current CP (TCHAR = char) 124 | / 1: Unicode in UTF-16 (TCHAR = WCHAR) 125 | / 2: Unicode in UTF-8 (TCHAR = char) 126 | / 3: Unicode in UTF-32 (TCHAR = DWORD) 127 | / 128 | / Also behavior of string I/O functions will be affected by this option. 129 | / When LFN is not enabled, this option has no effect. */ 130 | 131 | 132 | #define FF_LFN_BUF 255 133 | #define FF_SFN_BUF 12 134 | /* This set of options defines size of file name members in the FILINFO structure 135 | / which is used to read out directory items. These values should be suffcient for 136 | / the file names to read. The maximum possible length of the read file name depends 137 | / on character encoding. When LFN is not enabled, these options have no effect. */ 138 | 139 | 140 | #define FF_STRF_ENCODE 3 141 | /* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), 142 | / f_putc(), f_puts and f_printf() convert the character encoding in it. 143 | / This option selects assumption of character encoding ON THE FILE to be 144 | / read/written via those functions. 145 | / 146 | / 0: ANSI/OEM in current CP 147 | / 1: Unicode in UTF-16LE 148 | / 2: Unicode in UTF-16BE 149 | / 3: Unicode in UTF-8 150 | */ 151 | 152 | 153 | #define FF_FS_RPATH 0 154 | /* This option configures support for relative path. 155 | / 156 | / 0: Disable relative path and remove related functions. 157 | / 1: Enable relative path. f_chdir() and f_chdrive() are available. 158 | / 2: f_getcwd() function is available in addition to 1. 159 | */ 160 | 161 | 162 | /*---------------------------------------------------------------------------/ 163 | / Drive/Volume Configurations 164 | /---------------------------------------------------------------------------*/ 165 | 166 | #define FF_VOLUMES 1 167 | /* Number of volumes (logical drives) to be used. (1-10) */ 168 | 169 | 170 | #define FF_STR_VOLUME_ID 0 171 | #define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" 172 | /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. 173 | / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive 174 | / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each 175 | / logical drives. Number of items must not be less than FF_VOLUMES. Valid 176 | / characters for the volume ID strings are A-Z, a-z and 0-9, however, they are 177 | / compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is 178 | / not defined, a user defined volume string table needs to be defined as: 179 | / 180 | / const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... 181 | */ 182 | 183 | 184 | #define FF_MULTI_PARTITION 0 185 | /* This option switches support for multiple volumes on the physical drive. 186 | / By default (0), each logical drive number is bound to the same physical drive 187 | / number and only an FAT volume found on the physical drive will be mounted. 188 | / When this function is enabled (1), each logical drive number can be bound to 189 | / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() 190 | / funciton will be available. */ 191 | 192 | 193 | #define FF_MIN_SS 512 194 | #define FF_MAX_SS 512 195 | /* This set of options configures the range of sector size to be supported. (512, 196 | / 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and 197 | / harddisk. But a larger value may be required for on-board flash memory and some 198 | / type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured 199 | / for variable sector size mode and disk_ioctl() function needs to implement 200 | / GET_SECTOR_SIZE command. */ 201 | 202 | 203 | #define FF_USE_TRIM 0 204 | /* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) 205 | / To enable Trim function, also CTRL_TRIM command should be implemented to the 206 | / disk_ioctl() function. */ 207 | 208 | 209 | #define FF_FS_NOFSINFO 0 210 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 211 | / option, and f_getfree() function at first time after volume mount will force 212 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 213 | / 214 | / bit0=0: Use free cluster count in the FSINFO if available. 215 | / bit0=1: Do not trust free cluster count in the FSINFO. 216 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 217 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 218 | */ 219 | 220 | 221 | 222 | /*---------------------------------------------------------------------------/ 223 | / System Configurations 224 | /---------------------------------------------------------------------------*/ 225 | 226 | #define FF_FS_TINY 0 227 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 228 | / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. 229 | / Instead of private sector buffer eliminated from the file object, common sector 230 | / buffer in the filesystem object (FATFS) is used for the file data transfer. */ 231 | 232 | 233 | #define FF_FS_EXFAT 0 234 | /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) 235 | / To enable exFAT, also LFN needs to be enabled. 236 | / Note that enabling exFAT discards ANSI C (C89) compatibility. */ 237 | 238 | 239 | #define FF_FS_NORTC 0 240 | #define FF_NORTC_MON 1 241 | #define FF_NORTC_MDAY 1 242 | #define FF_NORTC_YEAR 2018 243 | /* The option FF_FS_NORTC switches timestamp functiton. If the system does not have 244 | / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable 245 | / the timestamp function. Every object modified by FatFs will have a fixed timestamp 246 | / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. 247 | / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be 248 | / added to the project to read current time form real-time clock. FF_NORTC_MON, 249 | / FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. 250 | / These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ 251 | 252 | 253 | #define FF_FS_LOCK 0 254 | /* The option FF_FS_LOCK switches file lock function to control duplicated file open 255 | / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY 256 | / is 1. 257 | / 258 | / 0: Disable file lock function. To avoid volume corruption, application program 259 | / should avoid illegal open, remove and rename to the open objects. 260 | / >0: Enable file lock function. The value defines how many files/sub-directories 261 | / can be opened simultaneously under file lock control. Note that the file 262 | / lock control is independent of re-entrancy. */ 263 | 264 | 265 | #define FF_FS_REENTRANT 0 266 | #define FF_FS_TIMEOUT 1000 267 | #define FF_SYNC_t HANDLE 268 | /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs 269 | / module itself. Note that regardless of this option, file access to different 270 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 271 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 272 | / to the same volume is under control of this function. 273 | / 274 | / 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. 275 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 276 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 277 | / function, must be added to the project. Samples are available in 278 | / option/syscall.c. 279 | / 280 | / The FF_FS_TIMEOUT defines timeout period in unit of time tick. 281 | / The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 282 | / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be 283 | / included somewhere in the scope of ff.h. */ 284 | 285 | /* #include // O/S definitions */ 286 | 287 | 288 | 289 | /*--- End of configuration options ---*/ 290 | -------------------------------------------------------------------------------- /integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef _INTEGER 6 | #define _INTEGER 7 | 8 | #ifdef _WIN32 /* FatFs development platform */ 9 | 10 | #include 11 | #include 12 | 13 | #else /* Embedded platform */ 14 | 15 | /* These types must be 16-bit, 32-bit or larger integer */ 16 | typedef int INT; 17 | typedef unsigned int UINT; 18 | 19 | /* These types must be 8-bit integer */ 20 | typedef char CHAR; 21 | typedef unsigned char UCHAR; 22 | typedef unsigned char BYTE; 23 | 24 | /* These types must be 16-bit integer */ 25 | typedef short SHORT; 26 | typedef unsigned short USHORT; 27 | typedef unsigned short WORD; 28 | typedef unsigned short WCHAR; 29 | 30 | /* These types must be 32-bit integer */ 31 | typedef long LONG; 32 | typedef unsigned long ULONG; 33 | typedef unsigned long DWORD; 34 | 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "main.h" 4 | #include "stm32f4_discovery.h" 5 | #include "stm32f4xx.h" 6 | #include "stm32f4_discovery_sdio_sd.h" 7 | 8 | #include "ff.h" 9 | #include "diskio.h" 10 | 11 | GPIO_InitTypeDef GPIO_InitStructure; 12 | 13 | extern uint32_t *romdis; 14 | 15 | extern volatile uint8_t *rom_base; 16 | extern volatile uint8_t *disk_image; 17 | extern volatile uint8_t *disk_select_port; 18 | extern volatile uint8_t *disk_select_port_complement; 19 | 20 | // Must be volatile to prevent optimiser doing stuff 21 | extern volatile uint32_t main_thread_command; 22 | extern volatile uint32_t main_thread_data; 23 | 24 | extern volatile uint32_t fdc_track; 25 | extern volatile uint32_t fdc_prev_track; 26 | extern volatile uint32_t fdc_write_flush_count; 27 | 28 | extern volatile uint8_t *track_buffer; 29 | extern volatile uint8_t *disk_info_buffer; 30 | 31 | extern volatile uint32_t *sector_ptrs; 32 | 33 | extern volatile uint8_t *fdc_log_ptr; 34 | 35 | #ifdef ENABLE_SEMIHOSTING 36 | extern void initialise_monitor_handles(void); /*rtt*/ 37 | #endif 38 | 39 | FRESULT res; 40 | FILINFO fno; 41 | DIR dir; 42 | FATFS fs32; 43 | char* path; 44 | UINT BytesRead; 45 | 46 | #if _USE_LFN 47 | static char lfn[_MAX_LFN + 1]; 48 | fno.lfname = lfn; 49 | fno.lfsize = sizeof lfn; 50 | #endif 51 | 52 | void delay_ms(const uint16_t ms) 53 | { 54 | uint32_t i = ms * 27778; 55 | while (i-- > 0) { 56 | __asm volatile ("nop"); 57 | } 58 | } 59 | 60 | void blink_pa6_pa7(void) { 61 | while(1) { 62 | GPIOA->ODR = 0x0040; 63 | delay_ms(500); 64 | GPIOA->ODR = 0x0080; 65 | delay_ms(500); 66 | } 67 | } 68 | 69 | enum sysclk_freq { 70 | SYSCLK_42_MHZ=0, 71 | SYSCLK_84_MHZ, 72 | SYSCLK_168_MHZ, 73 | SYSCLK_200_MHZ, 74 | SYSCLK_240_MHZ, 75 | }; 76 | 77 | void rcc_set_frequency(enum sysclk_freq freq) 78 | { 79 | int freqs[] = {42, 84, 168, 200, 240}; 80 | 81 | /* USB freqs: 42MHz, 42Mhz, 48MHz, 50MHz, 48MHz */ 82 | int pll_div[] = {2, 4, 7, 10, 10}; 83 | 84 | /* PLL_VCO = (HSE_VALUE / PLL_M) * PLL_N */ 85 | /* SYSCLK = PLL_VCO / PLL_P */ 86 | /* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ 87 | uint32_t PLL_P = 2; 88 | uint32_t PLL_N = freqs[freq] * 2; 89 | uint32_t PLL_M = (HSE_VALUE/1000000); 90 | uint32_t PLL_Q = pll_div[freq]; 91 | 92 | RCC_DeInit(); 93 | 94 | /* Enable HSE osscilator */ 95 | RCC_HSEConfig(RCC_HSE_ON); 96 | 97 | if (RCC_WaitForHSEStartUp() == ERROR) { 98 | return; 99 | } 100 | 101 | /* Configure PLL clock M, N, P, and Q dividers */ 102 | RCC_PLLConfig(RCC_PLLSource_HSE, PLL_M, PLL_N, PLL_P, PLL_Q); 103 | 104 | /* Enable PLL clock */ 105 | RCC_PLLCmd(ENABLE); 106 | 107 | /* Wait until PLL clock is stable */ 108 | while ((RCC->CR & RCC_CR_PLLRDY) == 0); 109 | 110 | /* Set PLL_CLK as system clock source SYSCLK */ 111 | RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 112 | 113 | /* Set AHB clock divider */ 114 | RCC_HCLKConfig(RCC_SYSCLK_Div1); 115 | 116 | //FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; 117 | 118 | /* Set APBx clock dividers */ 119 | switch (freq) { 120 | /* Max freq APB1: 42MHz APB2: 84MHz */ 121 | case SYSCLK_42_MHZ: 122 | RCC_PCLK1Config(RCC_HCLK_Div1); /* 42MHz */ 123 | RCC_PCLK2Config(RCC_HCLK_Div1); /* 42MHz */ 124 | break; 125 | case SYSCLK_84_MHZ: 126 | RCC_PCLK1Config(RCC_HCLK_Div2); /* 42MHz */ 127 | RCC_PCLK2Config(RCC_HCLK_Div1); /* 84MHz */ 128 | break; 129 | case SYSCLK_168_MHZ: 130 | RCC_PCLK1Config(RCC_HCLK_Div4); /* 42MHz */ 131 | RCC_PCLK2Config(RCC_HCLK_Div2); /* 84MHz */ 132 | break; 133 | case SYSCLK_200_MHZ: 134 | RCC_PCLK1Config(RCC_HCLK_Div4); /* 50MHz */ 135 | RCC_PCLK2Config(RCC_HCLK_Div2); /* 100MHz */ 136 | break; 137 | case SYSCLK_240_MHZ: 138 | RCC_PCLK1Config(RCC_HCLK_Div4); /* 60MHz */ 139 | RCC_PCLK2Config(RCC_HCLK_Div2); /* 120MHz */ 140 | break; 141 | } 142 | 143 | /* Update SystemCoreClock variable */ 144 | SystemCoreClockUpdate(); 145 | } 146 | 147 | void SD_NVIC_Configuration(void) 148 | { 149 | NVIC_InitTypeDef NVIC_InitStructure; 150 | 151 | /* Configure the NVIC Preemption Priority Bits */ 152 | //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 153 | //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 154 | 155 | NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn; 156 | //NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 157 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // This must be a lower priority (ie. higher number) than the _MREQ and _IORQ interrupts 158 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 159 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 160 | NVIC_Init(&NVIC_InitStructure); 161 | } 162 | 163 | void SDIO_IRQHandler(void) 164 | { 165 | /* Process All SDIO Interrupt Sources */ 166 | SD_ProcessIRQSrc(); 167 | } 168 | 169 | // _IORQ interrupt 170 | void config_PC1_int(void) { 171 | EXTI_InitTypeDef EXTI_InitStruct; 172 | NVIC_InitTypeDef NVIC_InitStruct; 173 | 174 | /* Enable clock for SYSCFG */ 175 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 176 | 177 | /* Tell system that you will use PC2 for EXTI_Line2 */ 178 | SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource1); 179 | 180 | /* PC2 is connected to EXTI_Line2 */ 181 | EXTI_InitStruct.EXTI_Line = EXTI_Line1; 182 | /* Enable interrupt */ 183 | EXTI_InitStruct.EXTI_LineCmd = ENABLE; 184 | /* Interrupt mode */ 185 | EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; 186 | /* Triggers on rising and falling edge */ 187 | //EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; 188 | EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; 189 | /* Add to EXTI */ 190 | EXTI_Init(&EXTI_InitStruct); 191 | 192 | /* Add IRQ vector to NVIC */ 193 | /* PC0 is connected to EXTI_Line0, which has EXTI1_IRQn vector */ 194 | NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn; 195 | /* Set priority */ 196 | NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00; 197 | /* Set sub priority */ 198 | NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00; 199 | /* Enable interrupt */ 200 | NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; 201 | /* Add to NVIC */ 202 | NVIC_Init(&NVIC_InitStruct); 203 | } 204 | 205 | 206 | 207 | void config_PC4_int(void) { 208 | EXTI_InitTypeDef EXTI_InitStruct; 209 | NVIC_InitTypeDef NVIC_InitStruct; 210 | 211 | /* Enable clock for SYSCFG */ 212 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 213 | 214 | SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource4); 215 | 216 | /* PC2 is connected to EXTI_Line2 */ 217 | EXTI_InitStruct.EXTI_Line = EXTI_Line4; 218 | /* Enable interrupt */ 219 | EXTI_InitStruct.EXTI_LineCmd = ENABLE; 220 | /* Interrupt mode */ 221 | EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; 222 | /* Triggers on rising and falling edge */ 223 | EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; 224 | //EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; 225 | /* Add to EXTI */ 226 | EXTI_Init(&EXTI_InitStruct); 227 | 228 | /* Add IRQ vector to NVIC */ 229 | /* PC0 is connected to EXTI_Line0, which has EXTI4_IRQn vector */ 230 | NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn; 231 | /* Set priority */ 232 | NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; 233 | /* Set sub priority */ 234 | NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00; 235 | /* Enable interrupt */ 236 | NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; 237 | /* Add to NVIC */ 238 | NVIC_Init(&NVIC_InitStruct); 239 | } 240 | 241 | 242 | /* Input Signals GPIO pins on ROMEN -> PC2, IORQ -> PC1, WR -> PC0 */ 243 | /* Output Signals GPIO pins on ROMDIS -> PC3. need to make it open collector with a pullup */ 244 | /* SD card uses PC10, PC11, PC12 out and PC8 in */ 245 | void config_gpio_portc(void) { 246 | GPIO_InitTypeDef GPIO_InitStructure; 247 | /* GPIOC Periph clock enable */ 248 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 249 | 250 | /* Configure GPIO Settings */ 251 | //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |GPIO_Pin_4 |GPIO_Pin_8 ; 252 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |GPIO_Pin_4 ; 253 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 254 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 255 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 256 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 257 | GPIO_Init(GPIOC, &GPIO_InitStructure); 258 | 259 | //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3| GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12; 260 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; 261 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; 262 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 263 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 264 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 265 | GPIO_Init(GPIOC, &GPIO_InitStructure); 266 | GPIOC->ODR = 0x0000; 267 | } 268 | 269 | /* Input/Output data GPIO pins on PD{8..15}. Also PD2 is used fo MOSI on the STM32F407VET6 board I have */ 270 | void config_gpio_data(void) { 271 | GPIO_InitTypeDef GPIO_InitStructure; 272 | /* GPIOD Periph clock enable */ 273 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); 274 | 275 | /* Configure GPIO Settings */ 276 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | 277 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 278 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 279 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 280 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 281 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 282 | //GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; 283 | GPIO_Init(GPIOD, &GPIO_InitStructure); 284 | 285 | //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 ; 286 | //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; 287 | //GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 288 | //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 289 | //GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 290 | //GPIO_Init(GPIOD, &GPIO_InitStructure); 291 | } 292 | 293 | /* Input Address GPIO pins on PE{0..15} */ 294 | void config_gpio_addr(void) { 295 | GPIO_InitTypeDef GPIO_InitStructure; 296 | /* GPIOE Periph clock enable */ 297 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); 298 | 299 | /* Configure GPIO Settings */ 300 | GPIO_InitStructure.GPIO_Pin = 301 | GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | 302 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | 303 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | 304 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 305 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 306 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 307 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 308 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; 309 | GPIO_Init(GPIOE, &GPIO_InitStructure); 310 | } 311 | 312 | /* Debug GPIO pins on PA0 */ 313 | void config_gpio_dbg(void) { 314 | GPIO_InitTypeDef GPIO_InitStructure; 315 | /* GPIOA Periph clock enable */ 316 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 317 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,DISABLE); 318 | 319 | 320 | /* Configure GPIO Settings */ 321 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_6 | GPIO_Pin_7; 322 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; 323 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 324 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 325 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 326 | GPIO_Init(GPIOA, &GPIO_InitStructure); 327 | } 328 | 329 | 330 | void config_backup_sram(void) { 331 | 332 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); 333 | PWR_BackupAccessCmd(ENABLE); 334 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE); 335 | PWR_BackupRegulatorCmd(ENABLE); 336 | } 337 | 338 | 339 | FRESULT load_disk_info(FIL *fil,char *fname, uint8_t *buffer) { 340 | UINT BytesRead; 341 | FRESULT res; 342 | 343 | #ifdef ENABLE_SEMIHOSTING_DISK_INFO 344 | printf("BEFORE fopen of %s\n",fname); 345 | #endif 346 | res = f_open(fil, fname, FA_READ); 347 | 348 | if (res == FR_OK) { 349 | res = f_read(fil, buffer, 256, &BytesRead); 350 | #ifdef ENABLE_SEMIHOSTING_DISK_INFO 351 | printf("AFTER f_read. Bytes read %d\n",BytesRead); 352 | #endif 353 | } 354 | return res; 355 | } 356 | 357 | FRESULT load_track(FIL *fil, uint32_t track_number, uint8_t *track, uint8_t *disk_info) { 358 | UINT BytesRead; 359 | FRESULT res; 360 | 361 | uint32_t offset=0x100; 362 | uint32_t track_size; 363 | int i; 364 | 365 | if ((disk_info[0]=='E') && (disk_info[1]=='X')) { 366 | // Must be EXTENDED CPC DSK 367 | #ifdef ENABLE_SEMIHOSTING_LOAD_TRACK 368 | if (track_number == 0x14) { 369 | printf("EXTENDED DISK\n"); 370 | } 371 | #endif 372 | for (i=0;i MAX_TRACK_SIZE)? MAX_TRACK_SIZE:track_size; 388 | if (res == FR_OK) { 389 | res = f_read(fil, track, track_size, &BytesRead); 390 | #ifdef ENABLE_SEMIHOSTING_LOAD_TRACK 391 | printf("AFTER f_read %04x to %08x , res = %d, BytesRead = %d\n",size_of_track, track, res,BytesRead); 392 | #endif 393 | } 394 | return res; 395 | } 396 | 397 | FRESULT save_track(FIL *fil, uint32_t track_number, uint8_t *track, uint8_t *disk_info) { 398 | UINT BytesWritten; 399 | FRESULT res; 400 | 401 | uint32_t offset=0x100; 402 | uint32_t track_size; 403 | int i; 404 | 405 | if ((disk_info[0]=='E') && (disk_info[1]=='X')) { 406 | // Must be EXTENDED CPC DSK 407 | for (i=0;i MAX_TRACK_SIZE)? MAX_TRACK_SIZE:track_size; 418 | if (res == FR_OK) { 419 | res = f_write(fil, track, track_size, &BytesWritten); 420 | #ifdef ENABLE_SEMIHOSTING_SAVE_TRACK 421 | printf("AFTER f_write %04x to %08x , res = %d, BytesWritten = %d\n",track_size, track, res,BytesWritten); 422 | #endif 423 | } 424 | return res; 425 | } 426 | 427 | 428 | 429 | 430 | // b needs to point to a buffer at least 12 chars long 431 | void compose_disk_name(char *b, uint8_t num) { 432 | char src[]= "CPCxxx.DSK"; 433 | 434 | uint8_t t; 435 | uint8_t x = num; 436 | char *p,*q; 437 | p = src; 438 | q = b; 439 | while (*p) { 440 | if (*p != 'x') { 441 | *q++ = *p++; 442 | } else { 443 | for (int y=2;y>=0;y--) { 444 | t = x%10; 445 | q[y] = t + '0'; 446 | x =x/10; 447 | } 448 | q+=3; p+=3; 449 | } 450 | } 451 | *q=0; 452 | } 453 | 454 | 455 | void build_sector_pointer_table(uint32_t *sector_table, uint8_t * track, uint8_t *disk_info) { 456 | uint8_t rec,sectors; 457 | uint8_t *ptr; // make it to an 8 bit array to make the pointer arithmetic easier 458 | #ifdef ENABLE_SEMIHOSTING_SECTOR_TABLE 459 | printf("build_sector_pointer_table sector_table=%08X,track=%08X, disk_info=%08X\n",sector_table, track, disk_info); 460 | #endif 461 | sectors = track[0x15]; 462 | ptr = track + 0x100; 463 | //printf("sectors in track = %d\n",sectors); 464 | for (int s=0; sAPB2ENR |= 0 | RCC_APB2ENR_SYSCFGEN ; 489 | SYSCFG->CMPCR |= SYSCFG_CMPCR_CMP_PD; // enable compensation cell 490 | while ((SYSCFG->CMPCR & SYSCFG_CMPCR_READY) == 0); // wait until ready 491 | 492 | //__disable_irq(); 493 | 494 | // Enable CCMRAM clock 495 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CCMDATARAMEN, ENABLE); 496 | 497 | config_backup_sram(); 498 | 499 | /* PD{8..15} and PD2 for SD card MOSI*/ 500 | config_gpio_data(); 501 | /* PE{0..15} */ 502 | config_gpio_addr(); 503 | /* PC{0..2} and PC8 and PC{10..12} */ 504 | config_gpio_portc(); 505 | 506 | config_gpio_dbg(); 507 | 508 | NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 509 | 510 | SysTick->CTRL = 0; 511 | config_PC1_int(); 512 | config_PC4_int(); 513 | 514 | SD_NVIC_Configuration(); 515 | 516 | uint32_t *p; 517 | p = (uint32_t *) &romdis; 518 | *p = 0x0000; 519 | 520 | //__enable_irq(); 521 | 522 | 523 | memset(&fs32, 0, sizeof(FATFS)); 524 | res = f_mount(&fs32, "",0); 525 | //res = f_mount(0, &fs32); 526 | if (res != FR_OK) { 527 | blink_pa6_pa7(); 528 | } 529 | 530 | 531 | 532 | if ((*disk_select_port ^ *disk_select_port_complement) != 0xff) { 533 | // Default to CPC000.DSK if cannot find old config in RAM 534 | *disk_select_port = 0x00; 535 | *disk_select_port_complement = 0xff; 536 | } 537 | // Do not use sprintf here 538 | compose_disk_name(diskfname, *disk_select_port); 539 | 540 | uint8_t *disk_info_buffer_ptr = (uint8_t *) &disk_info_buffer; 541 | 542 | // load first 256 bytes of disk 543 | if (load_disk_info(&fil,diskfname, disk_info_buffer_ptr) != FR_OK) { 544 | // First try to reset the disk_select_port back to zero 545 | *disk_select_port = 0x00; 546 | *disk_select_port_complement = 0xff; 547 | compose_disk_name(diskfname, *disk_select_port); 548 | if (load_disk_info(&fil,diskfname, disk_info_buffer_ptr) != FR_OK) { 549 | blink_pa6_pa7(); 550 | } 551 | } 552 | 553 | 554 | #ifdef ENABLE_SEMIHOSTING_DISK_INFO 555 | printf("after load_disk_info. First four letters are %c%c%c%c\n",disk_info_buffer_ptr[0],disk_info_buffer_ptr[1],disk_info_buffer_ptr[2],disk_info_buffer_ptr[3]); 556 | printf ("main_thread_command addr = %08x\n",&main_thread_command); 557 | #endif 558 | 559 | 560 | 561 | #ifdef DISABLE_ALL_BUT_SHOW_MAIN_THREAD_ACTIVITY 562 | while(1) { 563 | GPIOA->ODR = 1; 564 | asm volatile ("nop"); 565 | GPIOA->ODR = 0; 566 | asm volatile ("nop"); 567 | } 568 | #endif 569 | 570 | while(1) { 571 | if (fdc_write_flush_count) { 572 | //GPIOA->ODR = 1; 573 | //asm volatile ("nop"); 574 | //GPIOA->ODR = 0; 575 | // there must have been a write 576 | fdc_write_flush_count--; 577 | if (fdc_write_flush_count == 0) { 578 | //GPIOA->ODR = 1; 579 | f_close(&fil); // fclose the last dsk 580 | res = f_open(&fil, diskfname, FA_WRITE); 581 | save_track(&fil, fdc_track, (uint8_t *) &track_buffer, disk_info_buffer_ptr); 582 | f_close(&fil); 583 | res = f_open(&fil, diskfname, FA_READ); 584 | } 585 | } 586 | if (!(main_thread_command & 0xc0000000) && (main_thread_command & 0xff)) { 587 | switch (main_thread_command) { 588 | case (MAIN_THREAD_SEEK_COMMAND): { 589 | // SEEK 590 | main_thread_command |= 0x40000000; 591 | // check if there is a pending write 592 | if (fdc_write_flush_count) { 593 | //*fdc_log_ptr++ = 0xff; 594 | //*fdc_log_ptr++ = 0xfe; 595 | //GPIOA->ODR = 0; 596 | f_close(&fil); // fclose the last dsk 597 | res = f_open(&fil, diskfname, FA_WRITE); 598 | 599 | save_track(&fil, fdc_prev_track, (uint8_t *) &track_buffer, disk_info_buffer_ptr); 600 | fdc_write_flush_count=0; // kill the countdown 601 | f_close(&fil); 602 | res = f_open(&fil, diskfname, FA_READ); 603 | //GPIOA->ODR = 1; 604 | 605 | } 606 | // 607 | // There is not much point in failing if load_track fails 608 | // 2nd arg below is actually the cylinder to seek to 609 | 610 | //*fdc_log_ptr++ = 0xef; 611 | //*fdc_log_ptr++ = 0xee; 612 | load_track(&fil, main_thread_data, (uint8_t *) &track_buffer, disk_info_buffer_ptr); 613 | build_sector_pointer_table((uint32_t *)§or_ptrs, (uint8_t *) &track_buffer,disk_info_buffer_ptr); 614 | main_thread_command |= 0xc0000000; 615 | 616 | break; 617 | } 618 | case (MAIN_THREAD_CHANGE_DISK_COMMAND): { 619 | // CHANGE DISK 620 | main_thread_command |= 0x40000000; // somewhat pointless 621 | f_close(&fil); // fclose the last dsk 622 | compose_disk_name(diskfname, *disk_select_port); 623 | #ifdef ENABLE_SEMIHOSTING_CHANGE_DISK 624 | printf(" new disk %s, track %d, addr %08X\n",diskfname,fdc_track,&track_buffer); 625 | #endif 626 | if (load_disk_info(&fil,diskfname, disk_info_buffer_ptr) != FR_OK) { 627 | #ifdef ENABLE_SEMIHOSTING_CHANGE_DISK 628 | printf(" failed loading that disk. Try disk 0 instead\n"); 629 | #endif 630 | // First try to reset the disk_select_port back to zero 631 | *disk_select_port = 0x00; 632 | *disk_select_port_complement = 0xff; 633 | compose_disk_name(diskfname, *disk_select_port); 634 | if (load_disk_info(&fil,diskfname, disk_info_buffer_ptr) != FR_OK) { 635 | blink_pa6_pa7(); 636 | } 637 | } 638 | // reload the current track 639 | load_track(&fil, fdc_track, (uint8_t *) &track_buffer, disk_info_buffer_ptr); 640 | build_sector_pointer_table((uint32_t *)§or_ptrs, (uint8_t *) &track_buffer,disk_info_buffer_ptr); 641 | 642 | main_thread_command = 0x00000000; 643 | 644 | break; 645 | } 646 | } 647 | } 648 | } 649 | } 650 | 651 | -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAIN_H 2 | #define __MAIN_H 3 | #define MAX_TRACK_SIZE 0x1700 4 | #define MAX_SECTORS_PER_TRACK 27 5 | #define MAIN_THREAD_SEEK_COMMAND 1 6 | #define MAIN_THREAD_CHANGE_DISK_COMMAND 2 7 | #define DISK_FLUSH_COUNT 1000000 // how many times through the main thread loop before we autoflush to disk 8 | #endif 9 | 10 | -------------------------------------------------------------------------------- /misc_handlers.c: -------------------------------------------------------------------------------- 1 | /* None of these handlers should fire. This is mainly here for debugging */ 2 | 3 | #include "stm32f4xx.h" 4 | #include "stm32f4_discovery_sdio_sd.h" 5 | 6 | 7 | void NMI_Handler(void); 8 | void HardFault_Handler(void); 9 | void MemManage_Handler(void); 10 | void BusFault_Handler(void); 11 | void UsageFault_Handler(void); 12 | void SVC_Handler(void); 13 | void DebugMon_Handler(void); 14 | void PendSV_Handler(void); 15 | void SysTick_Handler(void); 16 | 17 | 18 | uint32_t magic; 19 | 20 | void NMI_Handler(void) 21 | { 22 | magic = 0x12345678; 23 | while(1); 24 | } 25 | 26 | void HardFault_Handler(void) 27 | { 28 | magic = 0x56785678; 29 | while(1); 30 | } 31 | 32 | void MemManage_Handler(void) 33 | { 34 | magic = 0x11223344; 35 | while(1); 36 | } 37 | 38 | void BusFault_Handler(void) 39 | { 40 | magic = 0x66556655; 41 | while(1); 42 | } 43 | 44 | void UsageFault_Handler(void) 45 | { 46 | magic = 0x99aa99aa; 47 | while(1); 48 | } 49 | 50 | void SVC_Handler(void) 51 | { 52 | magic = 0x11cc11cc; 53 | while(1); 54 | } 55 | 56 | void DebugMon_Handler(void) 57 | { 58 | magic = 0xffeeffee; 59 | while(1); 60 | } 61 | 62 | void PendSV_Handler(void) 63 | { 64 | magic = 0x11881188; 65 | while(1); 66 | } 67 | 68 | void SysTick_Handler(void) 69 | { 70 | magic = 0x77557755; 71 | while(1); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /poller.S: -------------------------------------------------------------------------------- 1 | 2 | // Note to self. Dont use r10 and r11 3 | 4 | .syntax unified 5 | .cpu cortex-m4 6 | .fpu softvfp 7 | .thumb 8 | 9 | .global rom_base 10 | .global dsk_base 11 | .global special_port 12 | .global special_port_complement 13 | 14 | .section .rodata 15 | // Can put up to two 16K roms here which will get mapped to rom 6 and 7. Since it maps 7 its 16 | // really just for a CPC 464 17 | 18 | rom_base: 19 | // be careful if you add roms and later delete them. The old ones might be still in the STM32 flash 20 | //.incbin "roms/Moon_Buggy.rom" 21 | .incbin "roms/maxam15.rom" 22 | .incbin "roms/parados12.rom" 23 | //.incbin "roms/AMSDOS_0.7.ROM" 24 | 25 | 26 | .section .data 27 | special_port: 28 | .word 0x40024000 29 | special_port_complement: 30 | .word 0x40024001 31 | 32 | fdc_log_ptr: 33 | .word 0x20000100 34 | 35 | fdc_result_phase_index: 36 | .word 0x0000 37 | fdc_result_buffer: 38 | .byte 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 39 | fdc_read_data_bytes_left: 40 | .word 0x0000 41 | fdc_read_data_ptr: 42 | .word 0x0000 43 | 44 | 45 | .section .bss 46 | fdc_track: 47 | .word 0x0000 // track number 48 | fdc_track_base: 49 | .word 0x00000000 50 | //phases 51 | .equ CMD_PHASE,0 52 | .equ EXEC_PHASE,1 53 | .equ RESULT_PHASE,2 54 | fdc_phase: 55 | .word CMD_PHASE 56 | 57 | fdc_current_command: 58 | .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 59 | fdc_current_bytes_left: 60 | .word 0x00 61 | fdc_command_phase_index: 62 | .word 0x00 63 | dsk_offset: 64 | .word 0x0000 65 | dsk_base: 66 | .lcomm disk_image, 0x18000 // 96K worth. Could probably make it a little bigger easily 67 | //rom1_base: 68 | // .skip 16384 69 | 70 | 71 | .equ PERIPH_BASE , 0x40000000 72 | .equ PERIPH_BASE_APB1, (PERIPH_BASE + 0x00000) 73 | .equ PERIPH_BASE_APB2, (PERIPH_BASE + 0x10000) 74 | .equ PERIPH_BASE_AHB1, (PERIPH_BASE + 0x20000) 75 | .equ PERIPH_BASE_AHB2, 0x50000000 76 | .equ PERIPH_BASE_AHB3, 0x60000000 77 | 78 | .equ GPIOA_BASE, (PERIPH_BASE_AHB1 + 0x0000) 79 | .equ GPIOB_BASE, (PERIPH_BASE_AHB1 + 0x0400) 80 | .equ GPIOC_BASE, (PERIPH_BASE_AHB1 + 0x0800) 81 | .equ GPIOD_BASE, (PERIPH_BASE_AHB1 + 0x0C00) 82 | .equ GPIOE_BASE, (PERIPH_BASE_AHB1 + 0x1000) 83 | .equ GPIOF_BASE, (PERIPH_BASE_AHB1 + 0x1400) 84 | .equ GPIOG_BASE, (PERIPH_BASE_AHB1 + 0x1800) 85 | .equ GPIOH_BASE, (PERIPH_BASE_AHB1 + 0x1C00) 86 | .equ GPIOI_BASE, (PERIPH_BASE_AHB1 + 0x2000) 87 | 88 | .equ C_TO_D_OFFSET, (GPIOD_BASE - GPIOC_BASE) 89 | .equ C_TO_E_OFFSET, (GPIOE_BASE - GPIOC_BASE) 90 | 91 | .equ GPIOA_MODER , GPIOA_BASE + 0x00 92 | .equ GPIOA_OTYPER , GPIOA_BASE + 0x04 93 | .equ GPIOA_OSPEEDR , GPIOA_BASE + 0x08 94 | .equ GPIOA_PUPDR , GPIOA_BASE + 0x0C 95 | .equ GPIOA_IDR , GPIOA_BASE + 0x10 96 | .equ GPIOA_ODR , GPIOA_BASE + 0x14 97 | .equ GPIOA_BSRR , GPIOA_BASE + 0x18 98 | .equ GPIOA_LCKR , GPIOA_BASE + 0x1C 99 | .equ GPIOA_AFRL , GPIOA_BASE + 0x20 100 | .equ GPIOA_AFRH , GPIOA_BASE + 0x24 101 | 102 | .equ GPIOB_MODER , GPIOB_BASE + 0x00 103 | .equ GPIOB_OTYPER , GPIOB_BASE + 0x04 104 | .equ GPIOB_OSPEEDR , GPIOB_BASE + 0x08 105 | .equ GPIOB_PUPDR , GPIOB_BASE + 0x0C 106 | .equ GPIOB_IDR , GPIOB_BASE + 0x10 107 | .equ GPIOB_ODR , GPIOB_BASE + 0x14 108 | .equ GPIOB_BSRR , GPIOB_BASE + 0x18 109 | .equ GPIOB_LCKR , GPIOB_BASE + 0x1C 110 | .equ GPIOB_AFRL , GPIOB_BASE + 0x20 111 | .equ GPIOB_AFRH , GPIOB_BASE + 0x24 112 | 113 | .equ GPIOC_MODER , GPIOC_BASE + 0x00 114 | .equ GPIOC_OTYPER , GPIOC_BASE + 0x04 115 | .equ GPIOC_OSPEEDR , GPIOC_BASE + 0x08 116 | .equ GPIOC_PUPDR , GPIOC_BASE + 0x0C 117 | .equ GPIOC_IDR , GPIOC_BASE + 0x10 118 | .equ GPIOC_ODR , GPIOC_BASE + 0x14 119 | .equ GPIOC_BSRR , GPIOC_BASE + 0x18 120 | .equ GPIOC_LCKR , GPIOC_BASE + 0x1C 121 | .equ GPIOC_AFRL , GPIOC_BASE + 0x20 122 | .equ GPIOC_AFRH , GPIOC_BASE + 0x24 123 | 124 | .equ GPIOD_MODER , GPIOD_BASE + 0x00 125 | .equ GPIOD_OTYPER , GPIOD_BASE + 0x04 126 | .equ GPIOD_OSPEEDR , GPIOD_BASE + 0x08 127 | .equ GPIOD_PUPDR , GPIOD_BASE + 0x0C 128 | .equ GPIOD_IDR , GPIOD_BASE + 0x10 129 | .equ GPIOD_ODR , GPIOD_BASE + 0x14 130 | .equ GPIOD_BSRR , GPIOD_BASE + 0x18 131 | .equ GPIOD_LCKR , GPIOD_BASE + 0x1C 132 | .equ GPIOD_AFRL , GPIOD_BASE + 0x20 133 | .equ GPIOD_AFRH , GPIOD_BASE + 0x24 134 | 135 | .equ GPIOE_MODER , GPIOE_BASE + 0x00 136 | .equ GPIOE_OTYPER , GPIOE_BASE + 0x04 137 | .equ GPIOE_OSPEEDR , GPIOE_BASE + 0x08 138 | .equ GPIOE_PUPDR , GPIOE_BASE + 0x0C 139 | .equ GPIOE_IDR , GPIOE_BASE + 0x10 140 | .equ GPIOE_ODR , GPIOE_BASE + 0x14 141 | .equ GPIOE_BSRR , GPIOE_BASE + 0x18 142 | .equ GPIOE_LCKR , GPIOE_BASE + 0x1C 143 | .equ GPIOE_AFRL , GPIOE_BASE + 0x20 144 | .equ GPIOE_AFRH , GPIOE_BASE + 0x24 145 | 146 | .equ MODER , 0x00 147 | .equ OTYPER , 0x04 148 | .equ OSPEEDR , 0x08 149 | .equ IDR , 0x10 150 | .equ ODR , 0x14 151 | 152 | .equ ROMDIS_HIGH , 0x0008 153 | 154 | .equ SCB_AIRCR , 0xE000ED0C 155 | 156 | 157 | #define DATA_OUT_MODE 0x55550010 158 | #define DATA_IN_MODE 0x00000010 159 | 160 | reg_gpioa_odr .req r0 161 | reg_gpioc_base .req r1 162 | reg_rom_base .req r2 163 | reg_gpiod_base .req r3 // data in 164 | // r4,r5, r6 scratch 165 | reg_rom_bank .req r7 // rom bank register 166 | reg_pd2_state .req r8 167 | reg_databus_out_mode .req r9 // MODER setting for D15-D8 out and D2 out 168 | 169 | reg_gpioe_base .req r10 170 | 171 | // I tried using .data here, but it runs slower than flash on the F4. I think this is due to the ART accelerator 172 | .section .text 173 | .weak asm_poller 174 | .type asm_poller, %function 175 | 176 | 177 | asm_poller: 178 | // disable all interrupts. We never come out of this. if we did we would use 'cpsie i' 179 | cpsid i 180 | 181 | // Use as many registers as we can 182 | ldr reg_gpioa_odr,=GPIOA_ODR 183 | ldr reg_gpioc_base,=GPIOC_BASE 184 | ldr reg_gpiod_base,=GPIOD_BASE 185 | ldr reg_gpioe_base,=GPIOE_BASE 186 | // r5 is scratch 187 | // r6 is scratch 188 | // r7 is the rom_bank register 189 | ldr reg_rom_base,=rom_base 190 | ldr reg_databus_out_mode,=DATA_OUT_MODE 191 | //ldr reg_databus_in_mode,=DATA_IN_MODE 192 | movs reg_pd2_state,#0 193 | movs r6,#0 194 | str r6,[reg_gpioa_odr] 195 | 196 | /* Input Signals GPIO pins on _ROMEN -> PC2, _IORQ -> PC1, _WR -> PC0 */ 197 | /* Output Signals GPIO pins on ROMDIS -> PC3 */ 198 | /* SD card uses PC10, PC11, PC12 and PC8 and PD2*/ 199 | 200 | // Look for both _ROMEN low and _IORQ low 201 | negative_edge_loop: 202 | ldr r5,[reg_gpioe_base,IDR] // GPIOE->IDR get the addres BEFORE we test __ROMEN. It should be valid 'just before' __ROMEN goes low. NB: top halfword should be 0x0000 203 | ldr r6,[reg_gpioc_base,IDR] // get the portc control pins 204 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 205 | #ifdef DEBUG_MAIN 206 | IT CC 207 | strcc r6,[reg_gpioa_odr] // probbaly zero in bit 0 208 | #endif 209 | bcc.n negative_edge_romen 210 | bpl.n negative_edge_iorq 211 | ldr r5,[reg_gpioe_base,IDR] // GPIOE->IDR get the addres BEFORE we test __ROMEN. It should be valid 'just before' __ROMEN goes low. NB: top halfword should be 0x0000 212 | ldr r6,[reg_gpioc_base,IDR] // get the portc control pins 213 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 214 | #ifdef DEBUG_MAIN 215 | IT CC 216 | strcc r6,[reg_gpioa_odr] // debug output 217 | #endif 218 | bcc.n negative_edge_romen 219 | bpl.n negative_edge_iorq 220 | ldr r5,[reg_gpioe_base,IDR] // GPIOE->IDR get the addres BEFORE we test __ROMEN. It should be valid 'just before' __ROMEN goes low. NB: top halfword should be 0x0000 221 | ldr r6,[reg_gpioc_base,IDR] // get the portc control pins 222 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 223 | #ifdef DEBUG_MAIN 224 | IT CC 225 | strcc r6,[reg_gpioa_odr] // debug output 226 | #endif 227 | bcc.n negative_edge_romen 228 | bpl.n negative_edge_iorq 229 | ldr r5,[reg_gpioe_base,#0x10] // GPIOE->IDR get the addres BEFORE we test __ROMEN. It should be valid 'just before' __ROMEN goes low. NB: top halfword should be 0x0000 230 | ldr r6,[reg_gpioc_base,#0x10] // get the portc control pins 231 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 232 | #ifdef DEBUG_MAIN 233 | IT CC 234 | strcc r6,[reg_gpioa_odr] // debug output 235 | #endif 236 | bcc.n negative_edge_romen 237 | bpl.n negative_edge_iorq 238 | ldr r5,[reg_gpioe_base,#0x10] // GPIOE->IDR get the addres BEFORE we test __ROMEN. It should be valid 'just before' __ROMEN goes low. NB: top halfword should be 0x0000 239 | ldr r6,[reg_gpioc_base,#0x10] // get the portc control pins 240 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 241 | #ifdef DEBUG_MAIN 242 | IT CC 243 | strcc r6,[reg_gpioa_odr] // debug output 244 | #endif 245 | bcc.n negative_edge_romen 246 | bpl.n negative_edge_iorq 247 | b.n negative_edge_loop 248 | 249 | 250 | negative_edge_romen: 251 | 252 | #ifdef DEBUG__ROMEN 253 | str r6,[reg_gpioa_odr] 254 | #endif 255 | 256 | // NB: If you wanted to support say 4 ROMS beginning at ROM 4, you need 4 .incbin lines near 257 | // the beginning, and you need 258 | // 259 | // .... 260 | // subs r6,reg_rom_bank,#4 261 | // .... 262 | // cmp r6,#3 263 | 264 | // get the address 265 | tst r5,#0x8000 // check A15. If it is high. We are interested 266 | beq.n positive_edge_romen 267 | subs r6,reg_rom_bank,#6 // Only support from ROM 6 upwards 268 | bmi.n positive_edge_romen 269 | cmp r6,#1 // Only support 2 ROMS 270 | bgt.n positive_edge_romen 271 | lsls r6,r6,#14 272 | movs r4,#ROMDIS_HIGH 273 | str r4,[reg_gpioc_base,ODR] // set ROMDIS high 274 | bfc r5,#14,#18 // mask with 0x3fff 275 | orr r5,r5,r6 276 | ldrb r6,[reg_rom_base,r5] 277 | lsls r6,r6, #8 278 | str r6,[reg_gpiod_base, ODR] // GPIOD ODR 279 | str reg_databus_out_mode,[reg_gpiod_base, MODER] // MODER set to outputs 280 | 281 | #ifdef DEBUG__ROMEN 282 | movs r5,#1 283 | str r5,[reg_gpioa_odr] 284 | #endif 285 | b.n positive_edge_romen 286 | // This next bit is for the end of the cycle. Waiting for _ROMEN to go high 287 | // Technically this comes at the end of the cycle, but putting it in the middle of the codebase for now 288 | // the IT bit is to make the data bus go tristate as fast as we can 289 | register_unused: 290 | positive_edge_romen: 291 | ldr r5,=DATA_IN_MODE 292 | 1: ldr r6,[reg_gpioc_base,IDR] 293 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 294 | IT CS 295 | strcs r5,[reg_gpiod_base, MODER] // MODER set to inputs 296 | bcs.n _romen_high 297 | 298 | ldr r6,[reg_gpioc_base,IDR] 299 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 300 | IT CS 301 | strcs r5,[reg_gpiod_base, MODER] // MODER set to inputs 302 | bcs.n _romen_high 303 | 304 | ldr r6,[reg_gpioc_base,IDR] 305 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 306 | IT CS 307 | strcs r5,[reg_gpiod_base, MODER] // MODER set to inputs 308 | bcs.n _romen_high 309 | 310 | ldr r6,[reg_gpioc_base,IDR] 311 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 312 | IT CS 313 | strcs r5,[reg_gpiod_base, MODER] // MODER set to inputs 314 | bcs.n _romen_high 315 | 316 | ldr r6,[reg_gpioc_base,IDR] 317 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 318 | IT CS 319 | strcs r5,[reg_gpiod_base, MODER] // MODER set to inputs 320 | bcs.n _romen_high 321 | 322 | ldr r6,[reg_gpioc_base,IDR] 323 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 324 | IT CS 325 | strcs r5,[reg_gpiod_base, MODER] // MODER set to inputs 326 | bcs.n _romen_high 327 | 328 | ldr r6,[reg_gpioc_base,IDR] 329 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 330 | IT CS 331 | strcs r5,[reg_gpiod_base, MODER] // MODER set to inputs 332 | bcs.n _romen_high 333 | 334 | b.n 1b 335 | _romen_high: 336 | movs r6,#0x0000 337 | str r6,[reg_gpioc_base,ODR] // set ROMDIS low 338 | //str r5,[reg_gpiod_base, #0x00] // MODER set to inputs 339 | #ifdef DEBUG_MAIN 340 | movs r6,#1 341 | str r6,[reg_gpioa_odr] // set PA0 HIGH 342 | #endif 343 | b.n negative_edge_loop 344 | 345 | 346 | 347 | 348 | 349 | negative_edge_iorq: 350 | // get the address 351 | tst r5,#0x0480 // check A10/A8 352 | beq.n fdc_chip_selected 353 | tst r5,#0x2000 // check A13 354 | bne.n positive_edge_iorq 355 | tst r5,#0x8000 // check A15 356 | beq.n positive_edge_iorq 357 | tst r6,#0x40000000 // see if r/w is low 358 | bne.n positive_edge_romen 359 | ldr reg_rom_bank,[reg_gpiod_base, IDR] // GPIOD IDR 360 | lsrs reg_rom_bank,reg_rom_bank, #8 361 | ands reg_rom_bank,reg_rom_bank,#0xff 362 | movs r6,#3 363 | str r6,[reg_gpioa_odr] 364 | 365 | b.n positive_edge_iorq 366 | 367 | positive_edge_iorq: 368 | ldr r5,=DATA_IN_MODE 369 | 1: ldr r6,[reg_gpioc_base,IDR] 370 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 371 | IT MI 372 | strmi r5,[reg_gpiod_base, MODER] // MODER set to inputs 373 | bmi.n _iorq_high 374 | 375 | ldr r6,[reg_gpioc_base,IDR] 376 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 377 | IT MI 378 | strmi r5,[reg_gpiod_base, MODER] // MODER set to inputs 379 | bmi.n _iorq_high 380 | 381 | ldr r6,[reg_gpioc_base,IDR] 382 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 383 | IT MI 384 | strmi r5,[reg_gpiod_base, MODER] // MODER set to inputs 385 | bmi.n _iorq_high 386 | 387 | ldr r6,[reg_gpioc_base,IDR] 388 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 389 | IT MI 390 | strmi r5,[reg_gpiod_base, MODER] // MODER set to inputs 391 | bmi.n _iorq_high 392 | 393 | ldr r6,[reg_gpioc_base,IDR] 394 | lsls r6,r6,#30 // Move PC2 (_ROMEN) into C and PC1 (_IORQ) into N 395 | IT MI 396 | strmi r5,[reg_gpiod_base, MODER] // MODER set to inputs 397 | bmi.n _iorq_high 398 | 399 | b.n 1b 400 | _iorq_high: 401 | //str r5,[reg_gpiod_base, #0x00] // MODER set to inputs 402 | b.n negative_edge_loop 403 | 404 | 405 | 406 | 407 | 408 | fdc_chip_selected: 409 | and r4,r5,0xff00 // You need to narrow it down further. 410 | cmp r4,#0xfb00 411 | bne positive_edge_iorq 412 | tst r6,#0x40000000 413 | bne read_fdc_chip 414 | // Must be a write 415 | tst r5,#0x0001 416 | beq special_port_write // Write to FB7E 417 | ldr r6,[reg_gpiod_base, IDR] // GPIOD IDR 418 | lsrs r6,r6, #8 419 | and r6,r6,#0xdf 420 | 421 | 422 | #ifdef FDC_LOGGING 423 | ldr r5,=fdc_log_ptr 424 | ldr r4,[r5] 425 | strb r6,[r4] 426 | add r4,r4,1 427 | strb r6,[r4] 428 | str r4,[r5] 429 | #endif 430 | 431 | ldr r4,=fdc_command_phase_index 432 | ldr r4,[r4] 433 | ldr r5,=fdc_current_command 434 | strb r6,[r5,r4] // store the current byte of the command 435 | 436 | ldrb r6,[r5,#0] // get the command byte 437 | // jump to the handler 438 | tbb.w [pc,r6] 439 | .include "fdc_command_table.S" 440 | cmd_unused: 441 | b.n positive_edge_iorq 442 | 443 | // 20180602. Many of the commands are not implemented 444 | 445 | cmd_0x03: 446 | // SPECIFY 447 | movs r6,#3 448 | add r4,#1 449 | cmp r4,r6 450 | bne.n 1f 451 | movs r4,#0 452 | 1: 453 | ldr r5,=fdc_command_phase_index 454 | str r4,[r5] 455 | b.n positive_edge_iorq 456 | cmd_0x04: 457 | //SENSE DEVICE STATUS 458 | movs r6,#2 459 | b.n positive_edge_iorq 460 | cmd_0x07: 461 | //RECALIBRATE 462 | movs r6,#2 463 | add r4,#1 464 | cmp r4,r6 465 | bne.n 1f 466 | movs r4,#0 467 | ldr r5,=fdc_track 468 | str r4,[r5] 469 | ldr r5,=dsk_base 470 | add r5,r5,#0x100 471 | ldr r6,=fdc_track_base 472 | str r5,[r6] 473 | 1: 474 | ldr r5,=fdc_command_phase_index 475 | str r4,[r5] 476 | b.n positive_edge_iorq 477 | cmd_0x08: 478 | //SENSE INTERRUPT STATUS 479 | movs r6,#RESULT_PHASE 480 | ldr r5,=fdc_phase 481 | str r6,[r5] 482 | movs r6,#0 483 | ldr r5,=fdc_result_phase_index 484 | str r6,[r5] 485 | 486 | b.n positive_edge_iorq 487 | cmd_0x0f: 488 | //SEEK 489 | movs r6,#3 // num of bytes for cmd 490 | add r4,#1 491 | cmp r4,r6 492 | bne.n 1f 493 | movs r6,#0 494 | sub r4,r4,#1 495 | ldrb r6,[r5,r4] // get the clylinder number 496 | ldr r5,=fdc_track 497 | str r6,[r5] // store the cyclinder. will use it in the sense interrupt status cmd 498 | 499 | movs r4,#0 500 | 1: ldr r5,=fdc_command_phase_index 501 | str r4,[r5] 502 | 503 | b.n positive_edge_iorq 504 | cmd_0x42: 505 | //READ DIAGNOSTIC 506 | movs r6,#9 507 | b.n positive_edge_iorq 508 | cmd_0x45: 509 | //WRITE DATA 510 | movs r6,#9 511 | b.n positive_edge_iorq 512 | cmd_0x46: 513 | //READ DATA 514 | movs r6,#9 // 9 bytes in cmd sequence 515 | add r4,#1 516 | cmp r4,r6 517 | bne.n 1f 518 | // Got all the cmd sequence 519 | // r5 points to to the command buffer. 520 | push {r2,r3} 521 | movs r3,#0 // clear upper bytes 522 | movs r4,#0 // clear upper bytes 523 | ldrb r4,[r5,#2] // get the 'C' cylinder number 524 | ldr r2,=dsk_base 525 | ldrh r3,[r2,#0x32] // get track sie 526 | subs r3,r3,#0 527 | bne.n 6f 528 | movs r3,#0x1300 // default to 1300 529 | 6: mul r3,r3,r4 // multiple cylinder number times track size 530 | ldr r6,=dsk_base 531 | add r6,#0x100 532 | add r6,r6,r3 // r6 should point to the track 533 | mov r2,r6 // save the track base in r2. This points to 'Track-Info' 534 | 535 | ldrb r4,[r5,#4] // get the 'R' record number 536 | add r6,r6,#0x1a // offset to sector info sector id . 0x18 + 0x02 537 | movs r5,#0 538 | movs r3,#0 539 | 2: 540 | ldrb r5,[r6,r3] // grab next sector id from sector info block 541 | cmp r5,r4 542 | beq.n 3f 543 | add r3,r3,#8 // bump to next sector info block 544 | b.n 2b 545 | 3: 546 | // found sector 547 | // r6+r3 points to the sector id in a sector info block 548 | add r6,r6,r3 549 | ldr r5,=fdc_result_buffer 550 | movs r4,#0 551 | strb r4,[r5],#1 //ST0 552 | 553 | ldrb r4,[r6,#2] //ST1 554 | strb r4,[r5],#1 //ST1 555 | 556 | ldrb r4,[r6,#3] //ST2 557 | strb r4,[r5],#1 //ST2 558 | 559 | ldrb r4,[r6,#-2] //C 560 | strb r4,[r5],#1 //C 561 | 562 | ldrb r4,[r6,#-1] //H 563 | strb r4,[r5],#1 //H 564 | 565 | ldrb r4,[r6] //R 566 | strb r4,[r5],#1 //R 567 | 568 | ldrb r4,[r6,#1] //N 569 | strb r4,[r5],#1 //N 570 | 571 | // update the fdc_read_data_ptr pointer 572 | // r3 is the sector number, 0,1,2,3 etc 573 | lsls r3,r3,#6 // 8 -> 0x200, 16 -> 0x400 574 | add r2,r2,#0x0100 575 | add r2,r2,r3 // r5 should point to the track base 576 | ldr r6,=fdc_read_data_ptr 577 | str r2,[r6] 578 | 579 | 580 | // TODO This needs to change 581 | ldr r5,=fdc_read_data_bytes_left 582 | movs r4,#0x200 583 | str r4,[r5] 584 | 585 | movs r6,#EXEC_PHASE 586 | ldr r5,=fdc_phase 587 | str r6,[r5] 588 | // we are about to go to exec phase, but reset the cmd index now too 589 | movs r6,#0 590 | ldr r5,=fdc_command_phase_index 591 | str r6,[r5] 592 | ldr r5,=fdc_result_phase_index 593 | str r6,[r5] 594 | 595 | pop {r2,r3} 596 | // reset cmd index back to zero for next command 597 | movs r4,#0 598 | 1: 599 | ldr r5,=fdc_command_phase_index 600 | str r4,[r5] 601 | 602 | b.n positive_edge_iorq 603 | cmd_0x49: 604 | //WRITE DELETED DATA 605 | movs r6,#9 606 | b.n positive_edge_iorq 607 | cmd_0x4a: 608 | //READ ID 609 | movs r6,#2 610 | add r4,#1 611 | cmp r4,r6 612 | bne.n 1f 613 | // last byte 614 | // r5 points to to the command buffer. 615 | push {r2,r3} 616 | movs r3,#0 // clear upper bytes 617 | movs r4,#0 // clear upper bytes 618 | ldr r5,=fdc_track 619 | ldr r4,[r5] 620 | ldr r2,=dsk_base 621 | ldrh r3,[r2,#0x32] // get track sie 622 | subs r3,r3,#0 623 | bne.n 6f 624 | movs r3,#0x1300 // default to 1300 625 | 6: mul r3,r3,r4 // multiple cylinder number times track size 626 | ldr r6,=dsk_base 627 | add r6,#0x100 628 | add r6,r6,r3 // r6 should point to the track 629 | mov r2,r6 // save the track base in r2. This points to 'Track-Info' 630 | 631 | 632 | ldr r5,=fdc_result_buffer 633 | movs r4,#0 634 | strb r4,[r5],#1 //ST0 635 | 636 | ldrb r4,[r6,#0x1c] //ST1 637 | strb r4,[r5],#1 //ST1 638 | 639 | ldrb r4,[r6,#0x1d] //ST2 640 | strb r4,[r5],#1 //ST2 641 | 642 | ldrb r4,[r6,#0x18] //C 643 | strb r4,[r5],#1 //C 644 | 645 | ldrb r4,[r6,#0x19] //H 646 | strb r4,[r5],#1 //H 647 | 648 | ldrb r4,[r6,#0x1a] //R 649 | strb r4,[r5],#1 //R 650 | 651 | ldrb r4,[r6,#0x1b] //N 652 | strb r4,[r5],#1 //N 653 | 654 | movs r6,#RESULT_PHASE 655 | ldr r5,=fdc_phase 656 | str r6,[r5] 657 | // we are about to go to result phase, but reset the cmd index now too 658 | movs r6,#0 659 | ldr r5,=fdc_command_phase_index 660 | str r6,[r5] 661 | ldr r5,=fdc_result_phase_index 662 | str r6,[r5] 663 | 664 | pop {r2,r3} 665 | 666 | // reset index back to zero for next command 667 | movs r4,#0 668 | 1: 669 | ldr r5,=fdc_command_phase_index 670 | str r4,[r5] 671 | b.n positive_edge_iorq 672 | cmd_0x4c: 673 | //READ DELETED DATA 674 | movs r6,#9 675 | b.n positive_edge_iorq 676 | cmd_0x4d: 677 | //WRITE ID 678 | movs r6,#6 679 | b.n positive_edge_iorq 680 | cmd_0x51: 681 | //SCAN EQUAL 682 | movs r6,#9 683 | b.n positive_edge_iorq 684 | cmd_0x59: 685 | //SCAN LOW OR EQUAL 686 | movs r6,#9 687 | b.n positive_edge_iorq 688 | cmd_0x5d: 689 | //SCAN HIGH OR EQUAL 690 | movs r6,#9 691 | b.n positive_edge_iorq 692 | 693 | read_fdc_chip: 694 | tst r5,#1 695 | bne.n read_data_register 696 | // A0 is low so must be status register 697 | 698 | ldr r6,=fdc_phase 699 | ldr r5,[r6] 700 | movs r6,#0x8000 // always ready 701 | cmp r5,#CMD_PHASE 702 | beq.n 1f 703 | cmp r5,#RESULT_PHASE 704 | bne.n 2f 705 | movs r6,#0xd000 706 | b.n 1f 707 | 2: cmp r5,#EXEC_PHASE 708 | bne.n 1f 709 | movs r6,#0xf000 710 | 1: 711 | 712 | str r6,[reg_gpiod_base, ODR] // GPIOD ODR 713 | str reg_databus_out_mode,[reg_gpiod_base, MODER] // MODER set to outputs 714 | 715 | b positive_edge_iorq 716 | read_data_register: 717 | ldr r5,=fdc_phase 718 | ldr r5,[r5] 719 | cmp r5,#RESULT_PHASE 720 | bne exec_phase 721 | // RESULT PHASE 722 | ldr r5,=fdc_current_command 723 | ldrb r6,[r5,#0] // get the command byte 724 | // jump to the handler 725 | tbb.w [pc,r6] 726 | .include "fdc_result_table.S" 727 | result_unused: 728 | b positive_edge_iorq 729 | 730 | result_0x03: 731 | // SPECIFY 732 | b.n positive_edge_iorq 733 | result_0x04: 734 | //SENSE DEVICE STATUS 735 | // only one byte response at all times 736 | movs r6,#0x0000 737 | 738 | str reg_databus_out_mode,[reg_gpiod_base, MODER] // MODER set to outputs 739 | ldr r5,=fdc_phase 740 | movs r6,#CMD_PHASE 741 | str r6,[r5] 742 | 743 | b positive_edge_iorq 744 | result_0x07: 745 | //RECALIBRATE 746 | b.n positive_edge_iorq 747 | result_0x08: 748 | //SENSE INTERRUPT STATUS 749 | movs r6,#2 750 | ldr r5,=fdc_result_phase_index 751 | ldr r4,[r5] 752 | add r4,r4,#1 753 | str r4,[r5] 754 | cmp r4,r6 755 | beq.n 1f 756 | // 1st byte of result 757 | movs r6,#0x2000 758 | b.n 2f 759 | 1: 760 | // on the last byte of the result phase 761 | movs r6,#CMD_PHASE 762 | ldr r5,=fdc_phase 763 | str r6,[r5] 764 | ldr r5,=fdc_result_phase_index 765 | movs r6,#0 766 | str r6,[r5] 767 | // 2nd byte is the track number 768 | ldr r6,=fdc_track 769 | ldr r6,[r6] 770 | lsls r6,r6,#8 771 | 2: 772 | str r6,[reg_gpiod_base, ODR] // GPIOD ODR 773 | str reg_databus_out_mode,[reg_gpiod_base, MODER] // MODER set to outputs 774 | 775 | b.n positive_edge_iorq 776 | result_0x0f: 777 | //SEEK 778 | b.n positive_edge_iorq 779 | result_0x42: 780 | //READ DIAGNOSTIC 781 | b.n positive_edge_iorq 782 | result_0x45: 783 | //WRITE DATA 784 | b.n positive_edge_iorq 785 | result_0x46: 786 | //READ DATA 787 | movs r6,#7 788 | ldr r5,=fdc_result_phase_index 789 | ldr r4,[r5] 790 | add r4,r4,#1 791 | str r4,[r5] 792 | cmp r4,r6 793 | bne.n 1f 794 | // last byte 795 | movs r6,#CMD_PHASE 796 | ldr r5,=fdc_phase 797 | str r6,[r5] 798 | movs r6,#0 799 | ldr r5,=fdc_result_phase_index 800 | str r6,[r5] 801 | ldr r5,=fdc_command_phase_index 802 | str r6,[r5] 803 | 804 | 1: sub r4,r4,#1 805 | ldr r5,=fdc_result_buffer 806 | ldrb r6,[r5,r4] 807 | lsls r6,r6,#8 808 | 809 | str r6,[reg_gpiod_base, ODR] // GPIOD ODR 810 | str reg_databus_out_mode,[reg_gpiod_base, MODER] // MODER set to outputs 811 | 812 | b.n positive_edge_iorq 813 | result_0x49: 814 | //WRITE DELETED DATA 815 | b.n positive_edge_iorq 816 | result_0x4a: 817 | //READ ID 818 | movs r6,#7 819 | ldr r5,=fdc_result_phase_index 820 | ldr r4,[r5] 821 | add r4,r4,#1 822 | str r4,[r5] 823 | cmp r4,r6 824 | bne.n 1f 825 | // last byte 826 | movs r6,#CMD_PHASE 827 | ldr r5,=fdc_phase 828 | str r6,[r5] 829 | movs r6,#0 830 | ldr r5,=fdc_result_phase_index 831 | str r6,[r5] 832 | ldr r5,=fdc_command_phase_index 833 | str r6,[r5] 834 | 835 | 1: sub r4,r4,#1 836 | ldr r5,=fdc_result_buffer 837 | ldrb r6,[r5,r4] 838 | lsls r6,r6,#8 839 | 840 | str r6,[reg_gpiod_base, ODR] // GPIOD ODR 841 | str reg_databus_out_mode,[reg_gpiod_base, MODER] // MODER set to outputs 842 | 843 | 844 | b.n positive_edge_iorq 845 | result_0x4c: 846 | //READ DELETED DATA 847 | b.n positive_edge_iorq 848 | result_0x4d: 849 | //WRITE ID 850 | b.n positive_edge_iorq 851 | result_0x51: 852 | //SCAN EQUAL 853 | b.n positive_edge_iorq 854 | result_0x59: 855 | //SCAN LOW OR EQUAL 856 | b.n positive_edge_iorq 857 | result_0x5d: 858 | //SCAN HIGH OR EQUAL 859 | b.n positive_edge_iorq 860 | exec_phase: 861 | cmp r5,#EXEC_PHASE 862 | bne positive_edge_iorq 863 | ldr r5,=fdc_current_command 864 | ldrb r6,[r5,#0] // get the command byte 865 | cmp r6,#0x46 866 | beq.n exec_read_data 867 | ldr r5,=fdc_phase 868 | movs r6,#CMD_PHASE 869 | str r6,[r5] 870 | b positive_edge_iorq 871 | // READ DATA EXEC PHASE 872 | exec_read_data: 873 | ldr r5,=fdc_read_data_bytes_left 874 | ldr r4,[r5] 875 | subs r4,r4,#1 876 | bne.n 1f 877 | // process last byte 878 | movs r6,#RESULT_PHASE 879 | ldr r5,=fdc_phase 880 | str r6,[r5] 881 | movs r6,#0 882 | ldr r5,=fdc_result_phase_index 883 | str r6,[r5] 884 | ldr r5,=fdc_command_phase_index 885 | str r6,[r5] 886 | 887 | 888 | 1: 889 | ldr r5,=fdc_read_data_bytes_left 890 | str r4,[r5] 891 | ldr r5,=fdc_read_data_ptr 892 | ldr r6,[r5] 893 | ldrb r4,[r6],#1 894 | str r6,[r5] 895 | 896 | ldr r5,=fdc_read_data_bytes_left 897 | ldr r5,[r5] 898 | cmp r5,#0x1f0 899 | blt.n 3f 900 | #ifdef FDC_LOGGING 901 | // Sort of log the first 16 bytes or so of a sector transfer 902 | ldr r5,=fdc_log_ptr 903 | ldr r6,[r5] 904 | strb r4,[r6],#1 905 | str r6,[r5] 906 | #endif 907 | 3: 908 | lsls r4,r4,#8 909 | 910 | str r4,[reg_gpiod_base, ODR] // GPIOD ODR 911 | str reg_databus_out_mode,[reg_gpiod_base, MODER] // MODER set to outputs 912 | 913 | b positive_edge_iorq 914 | 915 | // FB7E write support 916 | special_port_write: 917 | ldr r6,[reg_gpiod_base, IDR] // GPIOD IDR 918 | lsrs r6,r6, #8 919 | ldr r5,=special_port 920 | ldr r5,[r5] 921 | strb r6,[r5] 922 | eor r6,r6,#0xff 923 | ldr r5,=special_port_complement 924 | ldr r5,[r5] 925 | strb r6,[r5] 926 | dsb 927 | // reset the board. Yeah, really. 928 | ldr r5,=0x05fa0004 929 | ldr r6,=SCB_AIRCR 930 | str r5,[r6] 931 | 932 | b positive_edge_iorq 933 | 934 | 935 | -------------------------------------------------------------------------------- /roms/README.md: -------------------------------------------------------------------------------- 1 | put some 16KB roms in this dir, and refer to them in poller.S 2 | -------------------------------------------------------------------------------- /startup_stm32f4xx.s: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file startup_stm32f4xx.s 4 | * @author MCD Application Team 5 | * @version V1.0.0 6 | * @date 30-September-2011 7 | * @brief STM32F4xx Devices vector table for RIDE7 toolchain. 8 | * This module performs: 9 | * - Set the initial SP 10 | * - Set the initial PC == Reset_Handler, 11 | * - Set the vector table entries with the exceptions ISR address 12 | * - Configure the clock system and the external SRAM mounted on 13 | * STM324xG-EVAL board to be used as data memory (optional, 14 | * to be enabled by user) 15 | * - Branches to main in the C library (which eventually 16 | * calls main()). 17 | * After Reset the Cortex-M4 processor is in Thread mode, 18 | * priority is Privileged, and the Stack is set to Main. 19 | ****************************************************************************** 20 | * @attention 21 | * 22 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 23 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 24 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 25 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 26 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 27 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 28 | * 29 | *

© COPYRIGHT 2011 STMicroelectronics

30 | ****************************************************************************** 31 | */ 32 | 33 | .syntax unified 34 | .cpu cortex-m3 35 | .fpu softvfp 36 | .thumb 37 | 38 | .global g_pfnVectors 39 | .global Default_Handler 40 | 41 | /* start address for the initialization values of the .data section. 42 | defined in linker script */ 43 | .word _sidata 44 | /* start address for the .data section. defined in linker script */ 45 | .word _sdata 46 | /* end address for the .data section. defined in linker script */ 47 | .word _edata 48 | /* start address for the .bss section. defined in linker script */ 49 | .word _sbss 50 | /* end address for the .bss section. defined in linker script */ 51 | .word _ebss 52 | /* stack used for SystemInit_ExtMemCtl; always internal RAM used */ 53 | 54 | /** 55 | * @brief This is the code that gets called when the processor first 56 | * starts execution following a reset event. Only the absolutely 57 | * necessary set is performed, after which the application 58 | * supplied main() routine is called. 59 | * @param None 60 | * @retval : None 61 | */ 62 | 63 | .section .text.Reset_Handler 64 | .weak Reset_Handler 65 | .type Reset_Handler, %function 66 | Reset_Handler: 67 | 68 | /* Copy the data segment initializers from flash to SRAM */ 69 | movs r1, #0 70 | b LoopCopyDataInit 71 | 72 | CopyDataInit: 73 | ldr r3, =_sidata 74 | ldr r3, [r3, r1] 75 | str r3, [r0, r1] 76 | adds r1, r1, #4 77 | 78 | LoopCopyDataInit: 79 | ldr r0, =_sdata 80 | ldr r3, =_edata 81 | adds r2, r0, r1 82 | cmp r2, r3 83 | bcc CopyDataInit 84 | ldr r2, =_sbss 85 | b LoopFillZerobss 86 | /* Zero fill the bss segment. */ 87 | FillZerobss: 88 | movs r3, #0 89 | str r3, [r2], #4 90 | 91 | LoopFillZerobss: 92 | ldr r3, = _ebss 93 | cmp r2, r3 94 | bcc FillZerobss 95 | 96 | /* Call the clock system intitialization function.*/ 97 | bl SystemInit 98 | /* Call the application's entry point.*/ 99 | bl main 100 | bx lr 101 | .size Reset_Handler, .-Reset_Handler 102 | 103 | /** 104 | * @brief This is the code that gets called when the processor receives an 105 | * unexpected interrupt. This simply enters an infinite loop, preserving 106 | * the system state for examination by a debugger. 107 | * @param None 108 | * @retval None 109 | */ 110 | .section .text.Default_Handler,"ax",%progbits 111 | Default_Handler: 112 | Infinite_Loop: 113 | b Infinite_Loop 114 | .size Default_Handler, .-Default_Handler 115 | /****************************************************************************** 116 | * 117 | * The minimal vector table for a Cortex M3. Note that the proper constructs 118 | * must be placed on this to ensure that it ends up at physical address 119 | * 0x0000.0000. 120 | * 121 | *******************************************************************************/ 122 | .section .isr_vector,"a",%progbits 123 | .type g_pfnVectors, %object 124 | .size g_pfnVectors, .-g_pfnVectors 125 | 126 | 127 | g_pfnVectors: 128 | .word _estack 129 | .word Reset_Handler 130 | .word NMI_Handler 131 | .word HardFault_Handler 132 | .word MemManage_Handler 133 | .word BusFault_Handler 134 | .word UsageFault_Handler 135 | .word 0 136 | .word 0 137 | .word 0 138 | .word 0 139 | .word SVC_Handler 140 | .word DebugMon_Handler 141 | .word 0 142 | .word PendSV_Handler 143 | .word SysTick_Handler 144 | 145 | /* External Interrupts */ 146 | .word WWDG_IRQHandler /* Window WatchDog */ 147 | .word PVD_IRQHandler /* PVD through EXTI Line detection */ 148 | .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ 149 | .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ 150 | .word FLASH_IRQHandler /* FLASH */ 151 | .word RCC_IRQHandler /* RCC */ 152 | .word EXTI0_IRQHandler /* EXTI Line0 */ 153 | .word EXTI1_IRQHandler /* EXTI Line1 */ 154 | .word EXTI2_IRQHandler /* EXTI Line2 */ 155 | .word EXTI3_IRQHandler /* EXTI Line3 */ 156 | .word EXTI4_IRQHandler /* EXTI Line4 */ 157 | .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ 158 | .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ 159 | .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ 160 | .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ 161 | .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ 162 | .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ 163 | .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ 164 | .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ 165 | .word CAN1_TX_IRQHandler /* CAN1 TX */ 166 | .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ 167 | .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ 168 | .word CAN1_SCE_IRQHandler /* CAN1 SCE */ 169 | .word EXTI9_5_IRQHandler /* External Line[9:5]s */ 170 | .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ 171 | .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ 172 | .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ 173 | .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ 174 | .word TIM2_IRQHandler /* TIM2 */ 175 | .word TIM3_IRQHandler /* TIM3 */ 176 | .word TIM4_IRQHandler /* TIM4 */ 177 | .word I2C1_EV_IRQHandler /* I2C1 Event */ 178 | .word I2C1_ER_IRQHandler /* I2C1 Error */ 179 | .word I2C2_EV_IRQHandler /* I2C2 Event */ 180 | .word I2C2_ER_IRQHandler /* I2C2 Error */ 181 | .word SPI1_IRQHandler /* SPI1 */ 182 | .word SPI2_IRQHandler /* SPI2 */ 183 | .word USART1_IRQHandler /* USART1 */ 184 | .word USART2_IRQHandler /* USART2 */ 185 | .word USART3_IRQHandler /* USART3 */ 186 | .word EXTI15_10_IRQHandler /* External Line[15:10]s */ 187 | .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ 188 | .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ 189 | .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ 190 | .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ 191 | .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ 192 | .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ 193 | .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ 194 | .word FSMC_IRQHandler /* FSMC */ 195 | .word SDIO_IRQHandler /* SDIO */ 196 | .word TIM5_IRQHandler /* TIM5 */ 197 | .word SPI3_IRQHandler /* SPI3 */ 198 | .word UART4_IRQHandler /* UART4 */ 199 | .word UART5_IRQHandler /* UART5 */ 200 | .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ 201 | .word TIM7_IRQHandler /* TIM7 */ 202 | .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ 203 | .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ 204 | .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ 205 | .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ 206 | .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ 207 | .word ETH_IRQHandler /* Ethernet */ 208 | .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ 209 | .word CAN2_TX_IRQHandler /* CAN2 TX */ 210 | .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ 211 | .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ 212 | .word CAN2_SCE_IRQHandler /* CAN2 SCE */ 213 | .word OTG_FS_IRQHandler /* USB OTG FS */ 214 | .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ 215 | .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ 216 | .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ 217 | .word USART6_IRQHandler /* USART6 */ 218 | .word I2C3_EV_IRQHandler /* I2C3 event */ 219 | .word I2C3_ER_IRQHandler /* I2C3 error */ 220 | .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ 221 | .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ 222 | .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ 223 | .word OTG_HS_IRQHandler /* USB OTG HS */ 224 | .word DCMI_IRQHandler /* DCMI */ 225 | .word CRYP_IRQHandler /* CRYP crypto */ 226 | .word HASH_RNG_IRQHandler /* Hash and Rng */ 227 | .word FPU_IRQHandler /* FPU */ 228 | 229 | /******************************************************************************* 230 | * 231 | * Provide weak aliases for each Exception handler to the Default_Handler. 232 | * As they are weak aliases, any function with the same name will override 233 | * this definition. 234 | * 235 | *******************************************************************************/ 236 | .weak NMI_Handler 237 | .thumb_set NMI_Handler,Default_Handler 238 | 239 | .weak HardFault_Handler 240 | .thumb_set HardFault_Handler,Default_Handler 241 | 242 | .weak MemManage_Handler 243 | .thumb_set MemManage_Handler,Default_Handler 244 | 245 | .weak BusFault_Handler 246 | .thumb_set BusFault_Handler,Default_Handler 247 | 248 | .weak UsageFault_Handler 249 | .thumb_set UsageFault_Handler,Default_Handler 250 | 251 | .weak SVC_Handler 252 | .thumb_set SVC_Handler,Default_Handler 253 | 254 | .weak DebugMon_Handler 255 | .thumb_set DebugMon_Handler,Default_Handler 256 | 257 | .weak PendSV_Handler 258 | .thumb_set PendSV_Handler,Default_Handler 259 | 260 | .weak SysTick_Handler 261 | .thumb_set SysTick_Handler,Default_Handler 262 | 263 | .weak WWDG_IRQHandler 264 | .thumb_set WWDG_IRQHandler,Default_Handler 265 | 266 | .weak PVD_IRQHandler 267 | .thumb_set PVD_IRQHandler,Default_Handler 268 | 269 | .weak TAMP_STAMP_IRQHandler 270 | .thumb_set TAMP_STAMP_IRQHandler,Default_Handler 271 | 272 | .weak RTC_WKUP_IRQHandler 273 | .thumb_set RTC_WKUP_IRQHandler,Default_Handler 274 | 275 | .weak FLASH_IRQHandler 276 | .thumb_set FLASH_IRQHandler,Default_Handler 277 | 278 | .weak RCC_IRQHandler 279 | .thumb_set RCC_IRQHandler,Default_Handler 280 | 281 | .weak EXTI0_IRQHandler 282 | .thumb_set EXTI0_IRQHandler,Default_Handler 283 | 284 | .weak EXTI1_IRQHandler 285 | .thumb_set EXTI1_IRQHandler,Default_Handler 286 | 287 | .weak EXTI2_IRQHandler 288 | .thumb_set EXTI2_IRQHandler,Default_Handler 289 | 290 | .weak EXTI3_IRQHandler 291 | .thumb_set EXTI3_IRQHandler,Default_Handler 292 | 293 | .weak EXTI4_IRQHandler 294 | .thumb_set EXTI4_IRQHandler,Default_Handler 295 | 296 | .weak DMA1_Stream0_IRQHandler 297 | .thumb_set DMA1_Stream0_IRQHandler,Default_Handler 298 | 299 | .weak DMA1_Stream1_IRQHandler 300 | .thumb_set DMA1_Stream1_IRQHandler,Default_Handler 301 | 302 | .weak DMA1_Stream2_IRQHandler 303 | .thumb_set DMA1_Stream2_IRQHandler,Default_Handler 304 | 305 | .weak DMA1_Stream3_IRQHandler 306 | .thumb_set DMA1_Stream3_IRQHandler,Default_Handler 307 | 308 | .weak DMA1_Stream4_IRQHandler 309 | .thumb_set DMA1_Stream4_IRQHandler,Default_Handler 310 | 311 | .weak DMA1_Stream5_IRQHandler 312 | .thumb_set DMA1_Stream5_IRQHandler,Default_Handler 313 | 314 | .weak DMA1_Stream6_IRQHandler 315 | .thumb_set DMA1_Stream6_IRQHandler,Default_Handler 316 | 317 | .weak ADC_IRQHandler 318 | .thumb_set ADC_IRQHandler,Default_Handler 319 | 320 | .weak CAN1_TX_IRQHandler 321 | .thumb_set CAN1_TX_IRQHandler,Default_Handler 322 | 323 | .weak CAN1_RX0_IRQHandler 324 | .thumb_set CAN1_RX0_IRQHandler,Default_Handler 325 | 326 | .weak CAN1_RX1_IRQHandler 327 | .thumb_set CAN1_RX1_IRQHandler,Default_Handler 328 | 329 | .weak CAN1_SCE_IRQHandler 330 | .thumb_set CAN1_SCE_IRQHandler,Default_Handler 331 | 332 | .weak EXTI9_5_IRQHandler 333 | .thumb_set EXTI9_5_IRQHandler,Default_Handler 334 | 335 | .weak TIM1_BRK_TIM9_IRQHandler 336 | .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler 337 | 338 | .weak TIM1_UP_TIM10_IRQHandler 339 | .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler 340 | 341 | .weak TIM1_TRG_COM_TIM11_IRQHandler 342 | .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler 343 | 344 | .weak TIM1_CC_IRQHandler 345 | .thumb_set TIM1_CC_IRQHandler,Default_Handler 346 | 347 | .weak TIM2_IRQHandler 348 | .thumb_set TIM2_IRQHandler,Default_Handler 349 | 350 | .weak TIM3_IRQHandler 351 | .thumb_set TIM3_IRQHandler,Default_Handler 352 | 353 | .weak TIM4_IRQHandler 354 | .thumb_set TIM4_IRQHandler,Default_Handler 355 | 356 | .weak I2C1_EV_IRQHandler 357 | .thumb_set I2C1_EV_IRQHandler,Default_Handler 358 | 359 | .weak I2C1_ER_IRQHandler 360 | .thumb_set I2C1_ER_IRQHandler,Default_Handler 361 | 362 | .weak I2C2_EV_IRQHandler 363 | .thumb_set I2C2_EV_IRQHandler,Default_Handler 364 | 365 | .weak I2C2_ER_IRQHandler 366 | .thumb_set I2C2_ER_IRQHandler,Default_Handler 367 | 368 | .weak SPI1_IRQHandler 369 | .thumb_set SPI1_IRQHandler,Default_Handler 370 | 371 | .weak SPI2_IRQHandler 372 | .thumb_set SPI2_IRQHandler,Default_Handler 373 | 374 | .weak USART1_IRQHandler 375 | .thumb_set USART1_IRQHandler,Default_Handler 376 | 377 | .weak USART2_IRQHandler 378 | .thumb_set USART2_IRQHandler,Default_Handler 379 | 380 | .weak USART3_IRQHandler 381 | .thumb_set USART3_IRQHandler,Default_Handler 382 | 383 | .weak EXTI15_10_IRQHandler 384 | .thumb_set EXTI15_10_IRQHandler,Default_Handler 385 | 386 | .weak RTC_Alarm_IRQHandler 387 | .thumb_set RTC_Alarm_IRQHandler,Default_Handler 388 | 389 | .weak OTG_FS_WKUP_IRQHandler 390 | .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler 391 | 392 | .weak TIM8_BRK_TIM12_IRQHandler 393 | .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler 394 | 395 | .weak TIM8_UP_TIM13_IRQHandler 396 | .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler 397 | 398 | .weak TIM8_TRG_COM_TIM14_IRQHandler 399 | .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler 400 | 401 | .weak TIM8_CC_IRQHandler 402 | .thumb_set TIM8_CC_IRQHandler,Default_Handler 403 | 404 | .weak DMA1_Stream7_IRQHandler 405 | .thumb_set DMA1_Stream7_IRQHandler,Default_Handler 406 | 407 | .weak FSMC_IRQHandler 408 | .thumb_set FSMC_IRQHandler,Default_Handler 409 | 410 | .weak SDIO_IRQHandler 411 | .thumb_set SDIO_IRQHandler,Default_Handler 412 | 413 | .weak TIM5_IRQHandler 414 | .thumb_set TIM5_IRQHandler,Default_Handler 415 | 416 | .weak SPI3_IRQHandler 417 | .thumb_set SPI3_IRQHandler,Default_Handler 418 | 419 | .weak UART4_IRQHandler 420 | .thumb_set UART4_IRQHandler,Default_Handler 421 | 422 | .weak UART5_IRQHandler 423 | .thumb_set UART5_IRQHandler,Default_Handler 424 | 425 | .weak TIM6_DAC_IRQHandler 426 | .thumb_set TIM6_DAC_IRQHandler,Default_Handler 427 | 428 | .weak TIM7_IRQHandler 429 | .thumb_set TIM7_IRQHandler,Default_Handler 430 | 431 | .weak DMA2_Stream0_IRQHandler 432 | .thumb_set DMA2_Stream0_IRQHandler,Default_Handler 433 | 434 | .weak DMA2_Stream1_IRQHandler 435 | .thumb_set DMA2_Stream1_IRQHandler,Default_Handler 436 | 437 | .weak DMA2_Stream2_IRQHandler 438 | .thumb_set DMA2_Stream2_IRQHandler,Default_Handler 439 | 440 | .weak DMA2_Stream3_IRQHandler 441 | .thumb_set DMA2_Stream3_IRQHandler,Default_Handler 442 | 443 | .weak DMA2_Stream4_IRQHandler 444 | .thumb_set DMA2_Stream4_IRQHandler,Default_Handler 445 | 446 | .weak ETH_IRQHandler 447 | .thumb_set ETH_IRQHandler,Default_Handler 448 | 449 | .weak ETH_WKUP_IRQHandler 450 | .thumb_set ETH_WKUP_IRQHandler,Default_Handler 451 | 452 | .weak CAN2_TX_IRQHandler 453 | .thumb_set CAN2_TX_IRQHandler,Default_Handler 454 | 455 | .weak CAN2_RX0_IRQHandler 456 | .thumb_set CAN2_RX0_IRQHandler,Default_Handler 457 | 458 | .weak CAN2_RX1_IRQHandler 459 | .thumb_set CAN2_RX1_IRQHandler,Default_Handler 460 | 461 | .weak CAN2_SCE_IRQHandler 462 | .thumb_set CAN2_SCE_IRQHandler,Default_Handler 463 | 464 | .weak OTG_FS_IRQHandler 465 | .thumb_set OTG_FS_IRQHandler,Default_Handler 466 | 467 | .weak DMA2_Stream5_IRQHandler 468 | .thumb_set DMA2_Stream5_IRQHandler,Default_Handler 469 | 470 | .weak DMA2_Stream6_IRQHandler 471 | .thumb_set DMA2_Stream6_IRQHandler,Default_Handler 472 | 473 | .weak DMA2_Stream7_IRQHandler 474 | .thumb_set DMA2_Stream7_IRQHandler,Default_Handler 475 | 476 | .weak USART6_IRQHandler 477 | .thumb_set USART6_IRQHandler,Default_Handler 478 | 479 | .weak I2C3_EV_IRQHandler 480 | .thumb_set I2C3_EV_IRQHandler,Default_Handler 481 | 482 | .weak I2C3_ER_IRQHandler 483 | .thumb_set I2C3_ER_IRQHandler,Default_Handler 484 | 485 | .weak OTG_HS_EP1_OUT_IRQHandler 486 | .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler 487 | 488 | .weak OTG_HS_EP1_IN_IRQHandler 489 | .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler 490 | 491 | .weak OTG_HS_WKUP_IRQHandler 492 | .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler 493 | 494 | .weak OTG_HS_IRQHandler 495 | .thumb_set OTG_HS_IRQHandler,Default_Handler 496 | 497 | .weak DCMI_IRQHandler 498 | .thumb_set DCMI_IRQHandler,Default_Handler 499 | 500 | .weak CRYP_IRQHandler 501 | .thumb_set CRYP_IRQHandler,Default_Handler 502 | 503 | .weak HASH_RNG_IRQHandler 504 | .thumb_set HASH_RNG_IRQHandler,Default_Handler 505 | 506 | .weak FPU_IRQHandler 507 | .thumb_set FPU_IRQHandler,Default_Handler 508 | 509 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 510 | -------------------------------------------------------------------------------- /stm32_flash.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | ** 4 | 5 | ** File : LinkerScript.ld 6 | ** 7 | ** Abstract : Linker script for STM32F407VGTx Device with 8 | ** 1024KByte FLASH, 128KByte RAM 9 | ** 10 | ** Set heap size, stack size and stack location according 11 | ** to application requirements. 12 | ** 13 | ** Set memory bank area and size if external memory is used. 14 | ** 15 | ** Target : STMicroelectronics STM32 16 | ** 17 | ** 18 | ** Distribution: The file is distributed as is, without any warranty 19 | ** of any kind. 20 | ** 21 | ** (c)Copyright Ac6. 22 | ** You may use this file as-is or modify it according to the needs of your 23 | ** project. Distribution of this file (unmodified or modified) is not 24 | ** permitted. Ac6 permit registered System Workbench for MCU users the 25 | ** rights to distribute the assembled, compiled & linked contents of this 26 | ** file as part of an application binary file, provided that it is built 27 | ** using the System Workbench for MCU toolchain. 28 | ** 29 | ***************************************************************************** 30 | */ 31 | 32 | /* Entry Point */ 33 | ENTRY(Reset_Handler) 34 | 35 | /* Highest address of the user mode stack */ 36 | _estack = 0x20020000; /* end of RAM */ 37 | /* Generate a link error if heap and stack don't fit into RAM */ 38 | _Min_Heap_Size = 0x800;; /* required amount of heap */ 39 | _Min_Stack_Size = 0x800;; /* required amount of stack */ 40 | 41 | /* Specify the memory areas */ 42 | MEMORY 43 | { 44 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K 45 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K 46 | CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K 47 | } 48 | 49 | /* Define output sections */ 50 | SECTIONS 51 | { 52 | /* The startup code goes first into FLASH */ 53 | .isr_vector : 54 | { 55 | . = ALIGN(4); 56 | KEEP(*(.isr_vector)) /* Startup code */ 57 | . = ALIGN(4); 58 | } >FLASH 59 | 60 | /* The program code and other data goes into FLASH */ 61 | .text : 62 | { 63 | . = ALIGN(4); 64 | *(.text) /* .text sections (code) */ 65 | *(.text*) /* .text* sections (code) */ 66 | *(.glue_7) /* glue arm to thumb code */ 67 | *(.glue_7t) /* glue thumb to arm code */ 68 | *(.eh_frame) 69 | 70 | KEEP (*(.init)) 71 | KEEP (*(.fini)) 72 | 73 | . = ALIGN(4); 74 | _etext = .; /* define a global symbols at end of code */ 75 | } >FLASH 76 | 77 | /* Constant data goes into FLASH */ 78 | .rodata : 79 | { 80 | . = ALIGN(4); 81 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 82 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 83 | . = ALIGN(4); 84 | } >FLASH 85 | 86 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 87 | .ARM : { 88 | __exidx_start = .; 89 | *(.ARM.exidx*) 90 | __exidx_end = .; 91 | } >FLASH 92 | 93 | .preinit_array : 94 | { 95 | PROVIDE_HIDDEN (__preinit_array_start = .); 96 | KEEP (*(.preinit_array*)) 97 | PROVIDE_HIDDEN (__preinit_array_end = .); 98 | } >FLASH 99 | .init_array : 100 | { 101 | PROVIDE_HIDDEN (__init_array_start = .); 102 | KEEP (*(SORT(.init_array.*))) 103 | KEEP (*(.init_array*)) 104 | PROVIDE_HIDDEN (__init_array_end = .); 105 | } >FLASH 106 | .fini_array : 107 | { 108 | PROVIDE_HIDDEN (__fini_array_start = .); 109 | KEEP (*(SORT(.fini_array.*))) 110 | KEEP (*(.fini_array*)) 111 | PROVIDE_HIDDEN (__fini_array_end = .); 112 | } >FLASH 113 | 114 | /* used by the startup to initialize data */ 115 | _sidata = LOADADDR(.data); 116 | 117 | /* Initialized data sections goes into RAM, load LMA copy after code */ 118 | .data : 119 | { 120 | . = ALIGN(4); 121 | _sdata = .; /* create a global symbol at data start */ 122 | *(.data) /* .data sections */ 123 | *(.data*) /* .data* sections */ 124 | 125 | . = ALIGN(4); 126 | _edata = .; /* define a global symbol at data end */ 127 | } >RAM AT> FLASH 128 | 129 | _siccmram = LOADADDR(.ccmram); 130 | 131 | /* CCM-RAM section 132 | * 133 | * IMPORTANT NOTE! 134 | * If initialized variables will be placed in this section, 135 | * the startup code needs to be modified to copy the init-values. 136 | */ 137 | .ccmram : 138 | { 139 | . = ALIGN(4); 140 | _sccmram = .; /* create a global symbol at ccmram start */ 141 | *(.ccmram) 142 | *(.ccmram*) 143 | 144 | . = ALIGN(4); 145 | _eccmram = .; /* create a global symbol at ccmram end */ 146 | } >CCMRAM AT> FLASH 147 | 148 | 149 | /* Uninitialized data section */ 150 | . = ALIGN(4); 151 | .bss : 152 | { 153 | /* This is used by the startup in order to initialize the .bss secion */ 154 | _sbss = .; /* define a global symbol at bss start */ 155 | __bss_start__ = _sbss; 156 | *(.bss) 157 | *(.bss*) 158 | *(COMMON) 159 | 160 | . = ALIGN(4); 161 | _ebss = .; /* define a global symbol at bss end */ 162 | __bss_end__ = _ebss; 163 | } >RAM 164 | 165 | /* User_heap_stack section, used to check that there is enough RAM left */ 166 | ._user_heap_stack : 167 | { 168 | . = ALIGN(4); 169 | PROVIDE ( end = . ); 170 | PROVIDE ( _end = . ); 171 | PROVIDE ( __end__ = . ); 172 | . = . + _Min_Heap_Size; 173 | . = . + _Min_Stack_Size; 174 | . = ALIGN(4); 175 | } >RAM 176 | 177 | 178 | 179 | /* Remove information from the standard libraries */ 180 | /DISCARD/ : 181 | { 182 | libc.a ( * ) 183 | libm.a ( * ) 184 | libgcc.a ( * ) 185 | } 186 | 187 | .ARM.attributes 0 : { *(.ARM.attributes) } 188 | } 189 | 190 | 191 | -------------------------------------------------------------------------------- /stm32f4_discovery.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f4_discovery.c 4 | * @author MCD Application Team 5 | * @version V1.1.0 6 | * @date 28-October-2011 7 | * @brief This file provides set of firmware functions to manage Leds and 8 | * push-button available on STM32F4-Discovery Kit from STMicroelectronics. 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 13 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 14 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 15 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 16 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 17 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 18 | * 19 | *

© COPYRIGHT 2011 STMicroelectronics

20 | ****************************************************************************** 21 | 22 | PATCHED BY CLIVE SOURCER32@GMAIL.COM TO SDIO 23 | 24 | ****************************************************************************** 25 | */ 26 | 27 | /* Includes ------------------------------------------------------------------*/ 28 | #include "stm32f4_discovery.h" 29 | 30 | /** @addtogroup Utilities 31 | * @{ 32 | */ 33 | 34 | /** @addtogroup STM32F4_DISCOVERY 35 | * @{ 36 | */ 37 | 38 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL 39 | * @brief This file provides set of firmware functions to manage Leds and push-button 40 | * available on STM32F4-Discovery Kit from STMicroelectronics. 41 | * @{ 42 | */ 43 | 44 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_TypesDefinitions 45 | * @{ 46 | */ 47 | /** 48 | * @} 49 | */ 50 | 51 | 52 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Defines 53 | * @{ 54 | */ 55 | /** 56 | * @} 57 | */ 58 | 59 | 60 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Macros 61 | * @{ 62 | */ 63 | /** 64 | * @} 65 | */ 66 | 67 | 68 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Variables 69 | * @{ 70 | */ 71 | GPIO_TypeDef* GPIO_PORT[LEDn] = {LED4_GPIO_PORT, LED3_GPIO_PORT, LED5_GPIO_PORT, 72 | LED6_GPIO_PORT}; 73 | const uint16_t GPIO_PIN[LEDn] = {LED4_PIN, LED3_PIN, LED5_PIN, 74 | LED6_PIN}; 75 | const uint32_t GPIO_CLK[LEDn] = {LED4_GPIO_CLK, LED3_GPIO_CLK, LED5_GPIO_CLK, 76 | LED6_GPIO_CLK}; 77 | 78 | GPIO_TypeDef* BUTTON_PORT[BUTTONn] = {USER_BUTTON_GPIO_PORT }; 79 | 80 | const uint16_t BUTTON_PIN[BUTTONn] = {USER_BUTTON_PIN }; 81 | 82 | const uint32_t BUTTON_CLK[BUTTONn] = {USER_BUTTON_GPIO_CLK }; 83 | 84 | const uint16_t BUTTON_EXTI_LINE[BUTTONn] = {USER_BUTTON_EXTI_LINE }; 85 | 86 | const uint8_t BUTTON_PORT_SOURCE[BUTTONn] = {USER_BUTTON_EXTI_PORT_SOURCE}; 87 | 88 | const uint8_t BUTTON_PIN_SOURCE[BUTTONn] = {USER_BUTTON_EXTI_PIN_SOURCE }; 89 | const uint8_t BUTTON_IRQn[BUTTONn] = {USER_BUTTON_EXTI_IRQn }; 90 | 91 | NVIC_InitTypeDef NVIC_InitStructure; 92 | 93 | /** 94 | * @} 95 | */ 96 | 97 | 98 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_FunctionPrototypes 99 | * @{ 100 | */ 101 | 102 | /** 103 | * @} 104 | */ 105 | 106 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Functions 107 | * @{ 108 | */ 109 | 110 | /** 111 | * @brief Configures LED GPIO. 112 | * @param Led: Specifies the Led to be configured. 113 | * This parameter can be one of following parameters: 114 | * @arg LED4 115 | * @arg LED3 116 | * @arg LED5 117 | * @arg LED6 118 | * @retval None 119 | */ 120 | void STM_EVAL_LEDInit(Led_TypeDef Led) 121 | { 122 | GPIO_InitTypeDef GPIO_InitStructure; 123 | 124 | /* Enable the GPIO_LED Clock */ 125 | RCC_AHB1PeriphClockCmd(GPIO_CLK[Led], ENABLE); 126 | 127 | /* Configure the GPIO_LED pin */ 128 | GPIO_InitStructure.GPIO_Pin = GPIO_PIN[Led]; 129 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; 130 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 131 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 132 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 133 | GPIO_Init(GPIO_PORT[Led], &GPIO_InitStructure); 134 | } 135 | 136 | /** 137 | * @brief Turns selected LED On. 138 | * @param Led: Specifies the Led to be set on. 139 | * This parameter can be one of following parameters: 140 | * @arg LED4 141 | * @arg LED3 142 | * @arg LED5 143 | * @arg LED6 144 | * @retval None 145 | */ 146 | void STM_EVAL_LEDOn(Led_TypeDef Led) 147 | { 148 | GPIO_PORT[Led]->BSRRL = GPIO_PIN[Led]; 149 | } 150 | 151 | /** 152 | * @brief Turns selected LED Off. 153 | * @param Led: Specifies the Led to be set off. 154 | * This parameter can be one of following parameters: 155 | * @arg LED4 156 | * @arg LED3 157 | * @arg LED5 158 | * @arg LED6 159 | * @retval None 160 | */ 161 | void STM_EVAL_LEDOff(Led_TypeDef Led) 162 | { 163 | GPIO_PORT[Led]->BSRRH = GPIO_PIN[Led]; 164 | } 165 | 166 | /** 167 | * @brief Toggles the selected LED. 168 | * @param Led: Specifies the Led to be toggled. 169 | * This parameter can be one of following parameters: 170 | * @arg LED4 171 | * @arg LED3 172 | * @arg LED5 173 | * @arg LED6 174 | * @retval None 175 | */ 176 | void STM_EVAL_LEDToggle(Led_TypeDef Led) 177 | { 178 | GPIO_PORT[Led]->ODR ^= GPIO_PIN[Led]; 179 | } 180 | 181 | /** 182 | * @brief Configures Button GPIO and EXTI Line. 183 | * @param Button: Specifies the Button to be configured. 184 | * This parameter should be: BUTTON_USER 185 | * @param Button_Mode: Specifies Button mode. 186 | * This parameter can be one of following parameters: 187 | * @arg BUTTON_MODE_GPIO: Button will be used as simple IO 188 | * @arg BUTTON_MODE_EXTI: Button will be connected to EXTI line with interrupt 189 | * generation capability 190 | * @retval None 191 | */ 192 | void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode) 193 | { 194 | GPIO_InitTypeDef GPIO_InitStructure; 195 | EXTI_InitTypeDef EXTI_InitStructure; 196 | NVIC_InitTypeDef NVIC_InitStructure; 197 | 198 | /* Enable the BUTTON Clock */ 199 | RCC_AHB1PeriphClockCmd(BUTTON_CLK[Button], ENABLE); 200 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 201 | 202 | /* Configure Button pin as input */ 203 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 204 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 205 | GPIO_InitStructure.GPIO_Pin = BUTTON_PIN[Button]; 206 | GPIO_Init(BUTTON_PORT[Button], &GPIO_InitStructure); 207 | 208 | if (Button_Mode == BUTTON_MODE_EXTI) 209 | { 210 | /* Connect Button EXTI Line to Button GPIO Pin */ 211 | SYSCFG_EXTILineConfig(BUTTON_PORT_SOURCE[Button], BUTTON_PIN_SOURCE[Button]); 212 | 213 | /* Configure Button EXTI line */ 214 | EXTI_InitStructure.EXTI_Line = BUTTON_EXTI_LINE[Button]; 215 | EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 216 | EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 217 | EXTI_InitStructure.EXTI_LineCmd = ENABLE; 218 | EXTI_Init(&EXTI_InitStructure); 219 | 220 | /* Enable and set Button EXTI Interrupt to the lowest priority */ 221 | NVIC_InitStructure.NVIC_IRQChannel = BUTTON_IRQn[Button]; 222 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; 223 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; 224 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 225 | 226 | NVIC_Init(&NVIC_InitStructure); 227 | } 228 | } 229 | 230 | /** 231 | * @brief Returns the selected Button state. 232 | * @param Button: Specifies the Button to be checked. 233 | * This parameter should be: BUTTON_USER 234 | * @retval The Button GPIO pin value. 235 | */ 236 | uint32_t STM_EVAL_PBGetState(Button_TypeDef Button) 237 | { 238 | return GPIO_ReadInputDataBit(BUTTON_PORT[Button], BUTTON_PIN[Button]); 239 | } 240 | 241 | /** 242 | * @} 243 | */ 244 | 245 | /** 246 | * @brief DeInitializes the SDIO interface. 247 | * @param None 248 | * @retval None 249 | */ 250 | void SD_LowLevel_DeInit(void) 251 | { 252 | GPIO_InitTypeDef GPIO_InitStructure; 253 | 254 | /*!< Disable SDIO Clock */ 255 | SDIO_ClockCmd(DISABLE); 256 | 257 | /*!< Set Power State to OFF */ 258 | SDIO_SetPowerState(SDIO_PowerState_OFF); 259 | 260 | /*!< DeInitializes the SDIO peripheral */ 261 | SDIO_DeInit(); 262 | 263 | /* Disable the SDIO APB2 Clock */ 264 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, DISABLE); 265 | 266 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_MCO); 267 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_MCO); 268 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_MCO); 269 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_MCO); 270 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_MCO); 271 | GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_MCO); 272 | 273 | /* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */ 274 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; 275 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 276 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 277 | GPIO_Init(GPIOC, &GPIO_InitStructure); 278 | 279 | /* Configure PD.02 CMD line */ 280 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 281 | GPIO_Init(GPIOD, &GPIO_InitStructure); 282 | 283 | /* Configure PC.12 pin: CLK pin */ 284 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; 285 | GPIO_Init(GPIOC, &GPIO_InitStructure); 286 | } 287 | 288 | /** 289 | * @brief Initializes the SD Card and put it into StandBy State (Ready for 290 | * data transfer). 291 | * @param None 292 | * @retval None 293 | */ 294 | void SD_LowLevel_Init(void) 295 | { 296 | GPIO_InitTypeDef GPIO_InitStructure; 297 | 298 | /* GPIOC and GPIOD Periph clock enable */ 299 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | SD_DETECT_GPIO_CLK, ENABLE); 300 | 301 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_SDIO); 302 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_SDIO); 303 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SDIO); 304 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_SDIO); 305 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SDIO); 306 | GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_SDIO); 307 | 308 | /* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */ 309 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; 310 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; 311 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 312 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 313 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 314 | GPIO_Init(GPIOC, &GPIO_InitStructure); 315 | 316 | /* Configure PD.02 CMD line */ 317 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 318 | GPIO_Init(GPIOD, &GPIO_InitStructure); 319 | 320 | /* Configure PC.12 pin: CLK pin */ 321 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; 322 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 323 | GPIO_Init(GPIOC, &GPIO_InitStructure); 324 | 325 | /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */ 326 | //GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN; 327 | //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 328 | //GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 329 | //GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure); 330 | 331 | /* Enable the SDIO APB2 Clock */ 332 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE); 333 | 334 | /* Enable the DMA2 Clock */ 335 | RCC_AHB1PeriphClockCmd(SD_SDIO_DMA_CLK, ENABLE); 336 | } 337 | 338 | /** 339 | * @brief Configures the DMA2 Channel4 for SDIO Tx request. 340 | * @param BufferSRC: pointer to the source buffer 341 | * @param BufferSize: buffer size 342 | * @retval None 343 | */ 344 | void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize) 345 | { 346 | DMA_InitTypeDef SDDMA_InitStructure; 347 | 348 | DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_FEIF | SD_SDIO_DMA_FLAG_DMEIF | SD_SDIO_DMA_FLAG_TEIF | SD_SDIO_DMA_FLAG_HTIF | SD_SDIO_DMA_FLAG_TCIF); 349 | 350 | /* DMA2 Stream3 or Stream6 disable */ 351 | DMA_Cmd(SD_SDIO_DMA_STREAM, DISABLE); 352 | 353 | /* DMA2 Stream3 or Stream6 Config */ 354 | DMA_DeInit(SD_SDIO_DMA_STREAM); 355 | 356 | SDDMA_InitStructure.DMA_Channel = SD_SDIO_DMA_CHANNEL; 357 | SDDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS; 358 | SDDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BufferSRC; 359 | SDDMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; 360 | SDDMA_InitStructure.DMA_BufferSize = 0; 361 | SDDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 362 | SDDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 363 | SDDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 364 | SDDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 365 | SDDMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 366 | SDDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; 367 | SDDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; 368 | SDDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; 369 | SDDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4; 370 | SDDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4; 371 | DMA_Init(SD_SDIO_DMA_STREAM, &SDDMA_InitStructure); 372 | DMA_ITConfig(SD_SDIO_DMA_STREAM, DMA_IT_TC, ENABLE); 373 | DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral); 374 | 375 | /* DMA2 Stream3 or Stream6 enable */ 376 | DMA_Cmd(SD_SDIO_DMA_STREAM, ENABLE); 377 | 378 | } 379 | 380 | /** 381 | * @brief Configures the DMA2 Channel4 for SDIO Rx request. 382 | * @param BufferDST: pointer to the destination buffer 383 | * @param BufferSize: buffer size 384 | * @retval None 385 | */ 386 | void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize) 387 | { 388 | DMA_InitTypeDef SDDMA_InitStructure; 389 | 390 | DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_FEIF | SD_SDIO_DMA_FLAG_DMEIF | SD_SDIO_DMA_FLAG_TEIF | SD_SDIO_DMA_FLAG_HTIF | SD_SDIO_DMA_FLAG_TCIF); 391 | 392 | /* DMA2 Stream3 or Stream6 disable */ 393 | DMA_Cmd(SD_SDIO_DMA_STREAM, DISABLE); 394 | 395 | /* DMA2 Stream3 or Stream6 Config */ 396 | DMA_DeInit(SD_SDIO_DMA_STREAM); 397 | 398 | SDDMA_InitStructure.DMA_Channel = SD_SDIO_DMA_CHANNEL; 399 | SDDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS; 400 | SDDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BufferDST; 401 | SDDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 402 | SDDMA_InitStructure.DMA_BufferSize = 0; 403 | SDDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 404 | SDDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 405 | SDDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 406 | SDDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 407 | SDDMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 408 | SDDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; 409 | SDDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; 410 | SDDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; 411 | SDDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4; 412 | SDDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4; 413 | DMA_Init(SD_SDIO_DMA_STREAM, &SDDMA_InitStructure); 414 | DMA_ITConfig(SD_SDIO_DMA_STREAM, DMA_IT_TC, ENABLE); 415 | DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral); 416 | 417 | /* DMA2 Stream3 or Stream6 enable */ 418 | DMA_Cmd(SD_SDIO_DMA_STREAM, ENABLE); 419 | } 420 | 421 | /** 422 | * @} 423 | */ 424 | 425 | /** 426 | * @} 427 | */ 428 | 429 | /** 430 | * @} 431 | */ 432 | 433 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 434 | -------------------------------------------------------------------------------- /stm32f4_discovery.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f4_discovery.h 4 | * @author MCD Application Team 5 | * @version V1.1.0 6 | * @date 28-October-2011 7 | * @brief This file contains definitions for STM32F4-Discovery Kit's Leds and 8 | * push-button hardware resources. 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 13 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 14 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 15 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 16 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 17 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 18 | * 19 | *

© COPYRIGHT 2011 STMicroelectronics

20 | ****************************************************************************** 21 | 22 | PATCHED BY CLIVE SOURCER32@GMAIL.COM TO SDIO 23 | 24 | ****************************************************************************** 25 | */ 26 | 27 | /* Define to prevent recursive inclusion -------------------------------------*/ 28 | #ifndef __STM32F4_DISCOVERY_H 29 | #define __STM32F4_DISCOVERY_H 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* Includes ------------------------------------------------------------------*/ 36 | #include "stm32f4xx.h" 37 | 38 | /** @addtogroup Utilities 39 | * @{ 40 | */ 41 | 42 | /** @addtogroup STM32F4_DISCOVERY 43 | * @{ 44 | */ 45 | 46 | /** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL 47 | * @{ 48 | */ 49 | 50 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Types 51 | * @{ 52 | */ 53 | typedef enum 54 | { 55 | LED4 = 0, 56 | LED3 = 1, 57 | LED5 = 2, 58 | LED6 = 3 59 | } Led_TypeDef; 60 | 61 | typedef enum 62 | { 63 | BUTTON_USER = 0, 64 | } Button_TypeDef; 65 | 66 | typedef enum 67 | { 68 | BUTTON_MODE_GPIO = 0, 69 | BUTTON_MODE_EXTI = 1 70 | } ButtonMode_TypeDef; 71 | /** 72 | * @} 73 | */ 74 | 75 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Constants 76 | * @{ 77 | */ 78 | 79 | /** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL_LED 80 | * @{ 81 | */ 82 | #define LEDn 4 83 | 84 | #define LED4_PIN GPIO_Pin_12 85 | #define LED4_GPIO_PORT GPIOD 86 | #define LED4_GPIO_CLK RCC_AHB1Periph_GPIOD 87 | 88 | #define LED3_PIN GPIO_Pin_13 89 | #define LED3_GPIO_PORT GPIOD 90 | #define LED3_GPIO_CLK RCC_AHB1Periph_GPIOD 91 | 92 | #define LED5_PIN GPIO_Pin_14 93 | #define LED5_GPIO_PORT GPIOD 94 | #define LED5_GPIO_CLK RCC_AHB1Periph_GPIOD 95 | 96 | #define LED6_PIN GPIO_Pin_15 97 | #define LED6_GPIO_PORT GPIOD 98 | #define LED6_GPIO_CLK RCC_AHB1Periph_GPIOD 99 | /** 100 | * @} 101 | */ 102 | 103 | /** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL_BUTTON 104 | * @{ 105 | */ 106 | #define BUTTONn 1 107 | 108 | /** 109 | * @brief Wakeup push-button 110 | */ 111 | #define USER_BUTTON_PIN GPIO_Pin_0 112 | #define USER_BUTTON_GPIO_PORT GPIOA 113 | #define USER_BUTTON_GPIO_CLK RCC_AHB1Periph_GPIOA 114 | #define USER_BUTTON_EXTI_LINE EXTI_Line0 115 | #define USER_BUTTON_EXTI_PORT_SOURCE EXTI_PortSourceGPIOA 116 | #define USER_BUTTON_EXTI_PIN_SOURCE EXTI_PinSource0 117 | #define USER_BUTTON_EXTI_IRQn EXTI0_IRQn 118 | /** 119 | * @} 120 | */ 121 | 122 | /** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL_SD_FLASH 123 | * @{ 124 | */ 125 | /** 126 | * @brief SD FLASH SDIO Interface 127 | */ 128 | // NOTE I force SD_Detect to always return presetn to avoid using PC2 129 | #define SD_DETECT_PIN GPIO_Pin_2 /* PC.02 */ 130 | #define SD_DETECT_GPIO_PORT GPIOC /* GPIOC */ 131 | #define SD_DETECT_GPIO_CLK RCC_AHB1Periph_GPIOC 132 | 133 | #define SDIO_FIFO_ADDRESS ((uint32_t)0x40012C80) 134 | /** 135 | * @brief SDIO Intialization Frequency (400KHz max) 136 | */ 137 | #define SDIO_INIT_CLK_DIV ((uint8_t)0x76) 138 | /** 139 | * @brief SDIO Data Transfer Frequency (25MHz max) 140 | */ 141 | #define SDIO_TRANSFER_CLK_DIV ((uint8_t)0x2) 142 | //#define SDIO_TRANSFER_CLK_DIV ((uint8_t)0x40) 143 | 144 | #define SD_SDIO_DMA DMA2 145 | #define SD_SDIO_DMA_CLK RCC_AHB1Periph_DMA2 146 | 147 | #define SD_SDIO_DMA_STREAM3 3 148 | //#define SD_SDIO_DMA_STREAM6 6 149 | 150 | #ifdef SD_SDIO_DMA_STREAM3 151 | #define SD_SDIO_DMA_STREAM DMA2_Stream3 152 | #define SD_SDIO_DMA_CHANNEL DMA_Channel_4 153 | #define SD_SDIO_DMA_FLAG_FEIF DMA_FLAG_FEIF3 154 | #define SD_SDIO_DMA_FLAG_DMEIF DMA_FLAG_DMEIF3 155 | #define SD_SDIO_DMA_FLAG_TEIF DMA_FLAG_TEIF3 156 | #define SD_SDIO_DMA_FLAG_HTIF DMA_FLAG_HTIF3 157 | #define SD_SDIO_DMA_FLAG_TCIF DMA_FLAG_TCIF3 158 | #define SD_SDIO_DMA_IRQn DMA2_Stream3_IRQn 159 | #define SD_SDIO_DMA_IRQHANDLER DMA2_Stream3_IRQHandler 160 | #elif defined SD_SDIO_DMA_STREAM6 161 | #define SD_SDIO_DMA_STREAM DMA2_Stream6 162 | #define SD_SDIO_DMA_CHANNEL DMA_Channel_4 163 | #define SD_SDIO_DMA_FLAG_FEIF DMA_FLAG_FEIF6 164 | #define SD_SDIO_DMA_FLAG_DMEIF DMA_FLAG_DMEIF6 165 | #define SD_SDIO_DMA_FLAG_TEIF DMA_FLAG_TEIF6 166 | #define SD_SDIO_DMA_FLAG_HTIF DMA_FLAG_HTIF6 167 | #define SD_SDIO_DMA_FLAG_TCIF DMA_FLAG_TCIF6 168 | #define SD_SDIO_DMA_IRQn DMA2_Stream6_IRQn 169 | #define SD_SDIO_DMA_IRQHANDLER DMA2_Stream6_IRQHandler 170 | #endif /* SD_SDIO_DMA_STREAM3 */ 171 | 172 | /** 173 | * @} 174 | */ 175 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Macros 176 | * @{ 177 | */ 178 | /** 179 | * @} 180 | */ 181 | 182 | 183 | /** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Functions 184 | * @{ 185 | */ 186 | void STM_EVAL_LEDInit(Led_TypeDef Led); 187 | void STM_EVAL_LEDOn(Led_TypeDef Led); 188 | void STM_EVAL_LEDOff(Led_TypeDef Led); 189 | void STM_EVAL_LEDToggle(Led_TypeDef Led); 190 | 191 | void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode); 192 | uint32_t STM_EVAL_PBGetState(Button_TypeDef Button); 193 | 194 | void SD_LowLevel_DeInit(void); 195 | void SD_LowLevel_Init(void); 196 | void SD_LowLevel_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize); 197 | void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize); 198 | /** 199 | * @} 200 | */ 201 | 202 | #ifdef __cplusplus 203 | } 204 | #endif 205 | 206 | #endif /* __STM32F4_DISCOVERY_H */ 207 | /** 208 | * @} 209 | */ 210 | 211 | /** 212 | * @} 213 | */ 214 | 215 | /** 216 | * @} 217 | */ 218 | 219 | 220 | 221 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 222 | -------------------------------------------------------------------------------- /stm32f4_discovery_sdio_sd.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f4_discovery_sdio_sd.h 4 | * @author MCD Application Team 5 | * @version V1.0.2 6 | * @date 05-March-2012 7 | * @brief This file contains all the functions prototypes for the SD Card 8 | * stm324xg_eval_sdio_sd driver firmware library. 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT 2012 STMicroelectronics

13 | * 14 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 15 | * You may not use this file except in compliance with the License. 16 | * You may obtain a copy of the License at: 17 | * 18 | * http://www.st.com/software_license_agreement_liberty_v2 19 | * 20 | * Unless required by applicable law or agreed to in writing, software 21 | * distributed under the License is distributed on an "AS IS" BASIS, 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | * See the License for the specific language governing permissions and 24 | * limitations under the License. 25 | * 26 | ****************************************************************************** 27 | */ 28 | 29 | /* Define to prevent recursive inclusion -------------------------------------*/ 30 | #ifndef __STM32F4_DISCOVERY_SDIO_SD_H 31 | #define __STM32F4_DISCOVERY_SDIO_SD_H 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /* Includes ------------------------------------------------------------------*/ 38 | #include "stm32f4_discovery.h" 39 | 40 | /** @addtogroup Utilities 41 | * @{ 42 | */ 43 | 44 | /** @addtogroup STM32_EVAL 45 | * @{ 46 | */ 47 | 48 | /** @addtogroup STM32F4_DISCOVERY 49 | * @{ 50 | */ 51 | 52 | /** @addtogroup STM32F4_DISCOVERY_SDIO_SD 53 | * @{ 54 | */ 55 | 56 | /** @defgroup STM32F4_DISCOVERY_SDIO_SD_Exported_Types 57 | * @{ 58 | */ 59 | typedef enum 60 | { 61 | /** 62 | * @brief SDIO specific error defines 63 | */ 64 | SD_CMD_CRC_FAIL = (1), /*!< Command response received (but CRC check failed) */ 65 | SD_DATA_CRC_FAIL = (2), /*!< Data bock sent/received (CRC check Failed) */ 66 | SD_CMD_RSP_TIMEOUT = (3), /*!< Command response timeout */ 67 | SD_DATA_TIMEOUT = (4), /*!< Data time out */ 68 | SD_TX_UNDERRUN = (5), /*!< Transmit FIFO under-run */ 69 | SD_RX_OVERRUN = (6), /*!< Receive FIFO over-run */ 70 | SD_START_BIT_ERR = (7), /*!< Start bit not detected on all data signals in widE bus mode */ 71 | SD_CMD_OUT_OF_RANGE = (8), /*!< CMD's argument was out of range.*/ 72 | SD_ADDR_MISALIGNED = (9), /*!< Misaligned address */ 73 | SD_BLOCK_LEN_ERR = (10), /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */ 74 | SD_ERASE_SEQ_ERR = (11), /*!< An error in the sequence of erase command occurs.*/ 75 | SD_BAD_ERASE_PARAM = (12), /*!< An Invalid selection for erase groups */ 76 | SD_WRITE_PROT_VIOLATION = (13), /*!< Attempt to program a write protect block */ 77 | SD_LOCK_UNLOCK_FAILED = (14), /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */ 78 | SD_COM_CRC_FAILED = (15), /*!< CRC check of the previous command failed */ 79 | SD_ILLEGAL_CMD = (16), /*!< Command is not legal for the card state */ 80 | SD_CARD_ECC_FAILED = (17), /*!< Card internal ECC was applied but failed to correct the data */ 81 | SD_CC_ERROR = (18), /*!< Internal card controller error */ 82 | SD_GENERAL_UNKNOWN_ERROR = (19), /*!< General or Unknown error */ 83 | SD_STREAM_READ_UNDERRUN = (20), /*!< The card could not sustain data transfer in stream read operation. */ 84 | SD_STREAM_WRITE_OVERRUN = (21), /*!< The card could not sustain data programming in stream mode */ 85 | SD_CID_CSD_OVERWRITE = (22), /*!< CID/CSD overwrite error */ 86 | SD_WP_ERASE_SKIP = (23), /*!< only partial address space was erased */ 87 | SD_CARD_ECC_DISABLED = (24), /*!< Command has been executed without using internal ECC */ 88 | SD_ERASE_RESET = (25), /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */ 89 | SD_AKE_SEQ_ERROR = (26), /*!< Error in sequence of authentication. */ 90 | SD_INVALID_VOLTRANGE = (27), 91 | SD_ADDR_OUT_OF_RANGE = (28), 92 | SD_SWITCH_ERROR = (29), 93 | SD_SDIO_DISABLED = (30), 94 | SD_SDIO_FUNCTION_BUSY = (31), 95 | SD_SDIO_FUNCTION_FAILED = (32), 96 | SD_SDIO_UNKNOWN_FUNCTION = (33), 97 | 98 | /** 99 | * @brief Standard error defines 100 | */ 101 | SD_INTERNAL_ERROR, 102 | SD_NOT_CONFIGURED, 103 | SD_REQUEST_PENDING, 104 | SD_REQUEST_NOT_APPLICABLE, 105 | SD_INVALID_PARAMETER, 106 | SD_UNSUPPORTED_FEATURE, 107 | SD_UNSUPPORTED_HW, 108 | SD_ERROR, 109 | SD_OK = 0 110 | } SD_Error; 111 | 112 | /** 113 | * @brief SDIO Transfer state 114 | */ 115 | typedef enum 116 | { 117 | SD_TRANSFER_OK = 0, 118 | SD_TRANSFER_BUSY = 1, 119 | SD_TRANSFER_ERROR 120 | } SDTransferState; 121 | 122 | /** 123 | * @brief SD Card States 124 | */ 125 | typedef enum 126 | { 127 | SD_CARD_READY = ((uint32_t)0x00000001), 128 | SD_CARD_IDENTIFICATION = ((uint32_t)0x00000002), 129 | SD_CARD_STANDBY = ((uint32_t)0x00000003), 130 | SD_CARD_TRANSFER = ((uint32_t)0x00000004), 131 | SD_CARD_SENDING = ((uint32_t)0x00000005), 132 | SD_CARD_RECEIVING = ((uint32_t)0x00000006), 133 | SD_CARD_PROGRAMMING = ((uint32_t)0x00000007), 134 | SD_CARD_DISCONNECTED = ((uint32_t)0x00000008), 135 | SD_CARD_ERROR = ((uint32_t)0x000000FF) 136 | }SDCardState; 137 | 138 | 139 | /** 140 | * @brief Card Specific Data: CSD Register 141 | */ 142 | typedef struct 143 | { 144 | __IO uint8_t CSDStruct; /*!< CSD structure */ 145 | __IO uint8_t SysSpecVersion; /*!< System specification version */ 146 | __IO uint8_t Reserved1; /*!< Reserved */ 147 | __IO uint8_t TAAC; /*!< Data read access-time 1 */ 148 | __IO uint8_t NSAC; /*!< Data read access-time 2 in CLK cycles */ 149 | __IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */ 150 | __IO uint16_t CardComdClasses; /*!< Card command classes */ 151 | __IO uint8_t RdBlockLen; /*!< Max. read data block length */ 152 | __IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */ 153 | __IO uint8_t WrBlockMisalign; /*!< Write block misalignment */ 154 | __IO uint8_t RdBlockMisalign; /*!< Read block misalignment */ 155 | __IO uint8_t DSRImpl; /*!< DSR implemented */ 156 | __IO uint8_t Reserved2; /*!< Reserved */ 157 | __IO uint32_t DeviceSize; /*!< Device Size */ 158 | __IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */ 159 | __IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */ 160 | __IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */ 161 | __IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */ 162 | __IO uint8_t DeviceSizeMul; /*!< Device size multiplier */ 163 | __IO uint8_t EraseGrSize; /*!< Erase group size */ 164 | __IO uint8_t EraseGrMul; /*!< Erase group size multiplier */ 165 | __IO uint8_t WrProtectGrSize; /*!< Write protect group size */ 166 | __IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */ 167 | __IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */ 168 | __IO uint8_t WrSpeedFact; /*!< Write speed factor */ 169 | __IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */ 170 | __IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */ 171 | __IO uint8_t Reserved3; /*!< Reserded */ 172 | __IO uint8_t ContentProtectAppli; /*!< Content protection application */ 173 | __IO uint8_t FileFormatGrouop; /*!< File format group */ 174 | __IO uint8_t CopyFlag; /*!< Copy flag (OTP) */ 175 | __IO uint8_t PermWrProtect; /*!< Permanent write protection */ 176 | __IO uint8_t TempWrProtect; /*!< Temporary write protection */ 177 | __IO uint8_t FileFormat; /*!< File Format */ 178 | __IO uint8_t ECC; /*!< ECC code */ 179 | __IO uint8_t CSD_CRC; /*!< CSD CRC */ 180 | __IO uint8_t Reserved4; /*!< always 1*/ 181 | } SD_CSD; 182 | 183 | /** 184 | * @brief Card Identification Data: CID Register 185 | */ 186 | typedef struct 187 | { 188 | __IO uint8_t ManufacturerID; /*!< ManufacturerID */ 189 | __IO uint16_t OEM_AppliID; /*!< OEM/Application ID */ 190 | __IO uint32_t ProdName1; /*!< Product Name part1 */ 191 | __IO uint8_t ProdName2; /*!< Product Name part2*/ 192 | __IO uint8_t ProdRev; /*!< Product Revision */ 193 | __IO uint32_t ProdSN; /*!< Product Serial Number */ 194 | __IO uint8_t Reserved1; /*!< Reserved1 */ 195 | __IO uint16_t ManufactDate; /*!< Manufacturing Date */ 196 | __IO uint8_t CID_CRC; /*!< CID CRC */ 197 | __IO uint8_t Reserved2; /*!< always 1 */ 198 | } SD_CID; 199 | 200 | /** 201 | * @brief SD Card Status 202 | */ 203 | typedef struct 204 | { 205 | __IO uint8_t DAT_BUS_WIDTH; 206 | __IO uint8_t SECURED_MODE; 207 | __IO uint16_t SD_CARD_TYPE; 208 | __IO uint32_t SIZE_OF_PROTECTED_AREA; 209 | __IO uint8_t SPEED_CLASS; 210 | __IO uint8_t PERFORMANCE_MOVE; 211 | __IO uint8_t AU_SIZE; 212 | __IO uint16_t ERASE_SIZE; 213 | __IO uint8_t ERASE_TIMEOUT; 214 | __IO uint8_t ERASE_OFFSET; 215 | } SD_CardStatus; 216 | 217 | 218 | /** 219 | * @brief SD Card information 220 | */ 221 | typedef struct 222 | { 223 | SD_CSD SD_csd; 224 | SD_CID SD_cid; 225 | uint64_t CardCapacity; /*!< Card Capacity */ 226 | uint32_t CardBlockSize; /*!< Card Block Size */ 227 | uint16_t RCA; 228 | uint8_t CardType; 229 | } SD_CardInfo; 230 | 231 | /** 232 | * @} 233 | */ 234 | 235 | /** @defgroup STM32F4_DISCOVERY_SDIO_SD_Exported_Constants 236 | * @{ 237 | */ 238 | 239 | /** 240 | * @brief SDIO Commands Index 241 | */ 242 | #define SD_CMD_GO_IDLE_STATE ((uint8_t)0) 243 | #define SD_CMD_SEND_OP_COND ((uint8_t)1) 244 | #define SD_CMD_ALL_SEND_CID ((uint8_t)2) 245 | #define SD_CMD_SET_REL_ADDR ((uint8_t)3) /*!< SDIO_SEND_REL_ADDR for SD Card */ 246 | #define SD_CMD_SET_DSR ((uint8_t)4) 247 | #define SD_CMD_SDIO_SEN_OP_COND ((uint8_t)5) 248 | #define SD_CMD_HS_SWITCH ((uint8_t)6) 249 | #define SD_CMD_SEL_DESEL_CARD ((uint8_t)7) 250 | #define SD_CMD_HS_SEND_EXT_CSD ((uint8_t)8) 251 | #define SD_CMD_SEND_CSD ((uint8_t)9) 252 | #define SD_CMD_SEND_CID ((uint8_t)10) 253 | #define SD_CMD_READ_DAT_UNTIL_STOP ((uint8_t)11) /*!< SD Card doesn't support it */ 254 | #define SD_CMD_STOP_TRANSMISSION ((uint8_t)12) 255 | #define SD_CMD_SEND_STATUS ((uint8_t)13) 256 | #define SD_CMD_HS_BUSTEST_READ ((uint8_t)14) 257 | #define SD_CMD_GO_INACTIVE_STATE ((uint8_t)15) 258 | #define SD_CMD_SET_BLOCKLEN ((uint8_t)16) 259 | #define SD_CMD_READ_SINGLE_BLOCK ((uint8_t)17) 260 | #define SD_CMD_READ_MULT_BLOCK ((uint8_t)18) 261 | #define SD_CMD_HS_BUSTEST_WRITE ((uint8_t)19) 262 | #define SD_CMD_WRITE_DAT_UNTIL_STOP ((uint8_t)20) /*!< SD Card doesn't support it */ 263 | #define SD_CMD_SET_BLOCK_COUNT ((uint8_t)23) /*!< SD Card doesn't support it */ 264 | #define SD_CMD_WRITE_SINGLE_BLOCK ((uint8_t)24) 265 | #define SD_CMD_WRITE_MULT_BLOCK ((uint8_t)25) 266 | #define SD_CMD_PROG_CID ((uint8_t)26) /*!< reserved for manufacturers */ 267 | #define SD_CMD_PROG_CSD ((uint8_t)27) 268 | #define SD_CMD_SET_WRITE_PROT ((uint8_t)28) 269 | #define SD_CMD_CLR_WRITE_PROT ((uint8_t)29) 270 | #define SD_CMD_SEND_WRITE_PROT ((uint8_t)30) 271 | #define SD_CMD_SD_ERASE_GRP_START ((uint8_t)32) /*!< To set the address of the first write 272 | block to be erased. (For SD card only) */ 273 | #define SD_CMD_SD_ERASE_GRP_END ((uint8_t)33) /*!< To set the address of the last write block of the 274 | continuous range to be erased. (For SD card only) */ 275 | #define SD_CMD_ERASE_GRP_START ((uint8_t)35) /*!< To set the address of the first write block to be erased. 276 | (For MMC card only spec 3.31) */ 277 | 278 | #define SD_CMD_ERASE_GRP_END ((uint8_t)36) /*!< To set the address of the last write block of the 279 | continuous range to be erased. (For MMC card only spec 3.31) */ 280 | 281 | #define SD_CMD_ERASE ((uint8_t)38) 282 | #define SD_CMD_FAST_IO ((uint8_t)39) /*!< SD Card doesn't support it */ 283 | #define SD_CMD_GO_IRQ_STATE ((uint8_t)40) /*!< SD Card doesn't support it */ 284 | #define SD_CMD_LOCK_UNLOCK ((uint8_t)42) 285 | #define SD_CMD_APP_CMD ((uint8_t)55) 286 | #define SD_CMD_GEN_CMD ((uint8_t)56) 287 | #define SD_CMD_NO_CMD ((uint8_t)64) 288 | 289 | /** 290 | * @brief Following commands are SD Card Specific commands. 291 | * SDIO_APP_CMD should be sent before sending these commands. 292 | */ 293 | #define SD_CMD_APP_SD_SET_BUSWIDTH ((uint8_t)6) /*!< For SD Card only */ 294 | #define SD_CMD_SD_APP_STAUS ((uint8_t)13) /*!< For SD Card only */ 295 | #define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) /*!< For SD Card only */ 296 | #define SD_CMD_SD_APP_OP_COND ((uint8_t)41) /*!< For SD Card only */ 297 | #define SD_CMD_SD_APP_SET_CLR_CARD_DETECT ((uint8_t)42) /*!< For SD Card only */ 298 | #define SD_CMD_SD_APP_SEND_SCR ((uint8_t)51) /*!< For SD Card only */ 299 | #define SD_CMD_SDIO_RW_DIRECT ((uint8_t)52) /*!< For SD I/O Card only */ 300 | #define SD_CMD_SDIO_RW_EXTENDED ((uint8_t)53) /*!< For SD I/O Card only */ 301 | 302 | /** 303 | * @brief Following commands are SD Card Specific security commands. 304 | * SDIO_APP_CMD should be sent before sending these commands. 305 | */ 306 | #define SD_CMD_SD_APP_GET_MKB ((uint8_t)43) /*!< For SD Card only */ 307 | #define SD_CMD_SD_APP_GET_MID ((uint8_t)44) /*!< For SD Card only */ 308 | #define SD_CMD_SD_APP_SET_CER_RN1 ((uint8_t)45) /*!< For SD Card only */ 309 | #define SD_CMD_SD_APP_GET_CER_RN2 ((uint8_t)46) /*!< For SD Card only */ 310 | #define SD_CMD_SD_APP_SET_CER_RES2 ((uint8_t)47) /*!< For SD Card only */ 311 | #define SD_CMD_SD_APP_GET_CER_RES1 ((uint8_t)48) /*!< For SD Card only */ 312 | #define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK ((uint8_t)18) /*!< For SD Card only */ 313 | #define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK ((uint8_t)25) /*!< For SD Card only */ 314 | #define SD_CMD_SD_APP_SECURE_ERASE ((uint8_t)38) /*!< For SD Card only */ 315 | #define SD_CMD_SD_APP_CHANGE_SECURE_AREA ((uint8_t)49) /*!< For SD Card only */ 316 | #define SD_CMD_SD_APP_SECURE_WRITE_MKB ((uint8_t)48) /*!< For SD Card only */ 317 | 318 | /* Uncomment the following line to select the SDIO Data transfer mode */ 319 | #if !defined (SD_DMA_MODE) && !defined (SD_POLLING_MODE) 320 | #define SD_DMA_MODE ((uint32_t)0x00000000) 321 | /*#define SD_POLLING_MODE ((uint32_t)0x00000002) */ 322 | #endif 323 | 324 | /** 325 | * @brief SD detection on its memory slot 326 | */ 327 | #define SD_PRESENT ((uint8_t)0x01) 328 | #define SD_NOT_PRESENT ((uint8_t)0x00) 329 | 330 | /** 331 | * @brief Supported SD Memory Cards 332 | */ 333 | #define SDIO_STD_CAPACITY_SD_CARD_V1_1 ((uint32_t)0x00000000) 334 | #define SDIO_STD_CAPACITY_SD_CARD_V2_0 ((uint32_t)0x00000001) 335 | #define SDIO_HIGH_CAPACITY_SD_CARD ((uint32_t)0x00000002) 336 | #define SDIO_MULTIMEDIA_CARD ((uint32_t)0x00000003) 337 | #define SDIO_SECURE_DIGITAL_IO_CARD ((uint32_t)0x00000004) 338 | #define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((uint32_t)0x00000005) 339 | #define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006) 340 | #define SDIO_HIGH_CAPACITY_MMC_CARD ((uint32_t)0x00000007) 341 | 342 | /** 343 | * @} 344 | */ 345 | 346 | /** @defgroup STM32F4_DISCOVERY_SDIO_SD_Exported_Macros 347 | * @{ 348 | */ 349 | /** 350 | * @} 351 | */ 352 | 353 | /** @defgroup STM32F4_DISCOVERY_SDIO_SD_Exported_Functions 354 | * @{ 355 | */ 356 | void SD_DeInit(void); 357 | SD_Error SD_Init(void); 358 | SDTransferState SD_GetStatus(void); 359 | SDCardState SD_GetState(void); 360 | uint8_t SD_Detect(void); 361 | SD_Error SD_PowerON(void); 362 | SD_Error SD_PowerOFF(void); 363 | SD_Error SD_InitializeCards(void); 364 | SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo); 365 | SD_Error SD_GetCardStatus(SD_CardStatus *cardstatus); 366 | SD_Error SD_EnableWideBusOperation(uint32_t WideMode); 367 | SD_Error SD_SelectDeselect(uint32_t addr); 368 | SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize); 369 | SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks); 370 | SD_Error SD_ReadMultiBlocksFIXED(uint8_t *readbuff, uint32_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks); 371 | SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize); 372 | SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks); 373 | SD_Error SD_WriteMultiBlocksFIXED(uint8_t *writebuff, uint32_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks); 374 | SDTransferState SD_GetTransferState(void); 375 | SD_Error SD_StopTransfer(void); 376 | SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr); 377 | SD_Error SD_SendStatus(uint32_t *pcardstatus); 378 | SD_Error SD_SendSDStatus(uint32_t *psdstatus); 379 | SD_Error SD_ProcessIRQSrc(void); 380 | void SD_ProcessDMAIRQ(void); 381 | SD_Error SD_WaitReadOperation(void); 382 | SD_Error SD_WaitWriteOperation(void); 383 | #ifdef __cplusplus 384 | } 385 | #endif 386 | 387 | #endif /* __STM32F4_DISCOVERY_SDIO_SD_H */ 388 | /** 389 | * @} 390 | */ 391 | 392 | /** 393 | * @} 394 | */ 395 | 396 | /** 397 | * @} 398 | */ 399 | 400 | /** 401 | * @} 402 | */ 403 | 404 | /** 405 | * @} 406 | */ 407 | 408 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 409 | -------------------------------------------------------------------------------- /stm32f4xx_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file TIM_TimeBase/stm32f4xx_conf.h 4 | * @author MCD Application Team 5 | * @version V1.0.0 6 | * @date 19-September-2011 7 | * @brief Library configuration file. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 12 | * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 13 | * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 14 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 15 | * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 16 | * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 17 | * 18 | *

© COPYRIGHT 2011 STMicroelectronics

19 | ****************************************************************************** 20 | */ 21 | 22 | /* Define to prevent recursive inclusion -------------------------------------*/ 23 | #ifndef __STM32F4xx_CONF_H 24 | #define __STM32F4xx_CONF_H 25 | 26 | #if defined (HSE_VALUE) 27 | /* Redefine the HSE value; it's equal to 8 MHz on the STM32F4-DISCOVERY Kit */ 28 | #undef HSE_VALUE 29 | #define HSE_VALUE ((uint32_t)8000000) 30 | #endif /* HSE_VALUE */ 31 | 32 | /* Includes ------------------------------------------------------------------*/ 33 | /* Uncomment the line below to enable peripheral header file inclusion */ 34 | #include "stm32f4xx_adc.h" 35 | #include "stm32f4xx_can.h" 36 | #include "stm32f4xx_crc.h" 37 | #include "stm32f4xx_cryp.h" 38 | #include "stm32f4xx_dac.h" 39 | #include "stm32f4xx_dbgmcu.h" 40 | #include "stm32f4xx_dcmi.h" 41 | #include "stm32f4xx_dma.h" 42 | #include "stm32f4xx_exti.h" 43 | #include "stm32f4xx_flash.h" 44 | #include "stm32f4xx_fsmc.h" 45 | #include "stm32f4xx_hash.h" 46 | #include "stm32f4xx_gpio.h" 47 | #include "stm32f4xx_i2c.h" 48 | #include "stm32f4xx_iwdg.h" 49 | #include "stm32f4xx_pwr.h" 50 | #include "stm32f4xx_rcc.h" 51 | #include "stm32f4xx_rng.h" 52 | #include "stm32f4xx_rtc.h" 53 | #include "stm32f4xx_sdio.h" 54 | #include "stm32f4xx_spi.h" 55 | #include "stm32f4xx_syscfg.h" 56 | #include "stm32f4xx_tim.h" 57 | #include "stm32f4xx_usart.h" 58 | #include "stm32f4xx_wwdg.h" 59 | #include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ 60 | 61 | /* Exported types ------------------------------------------------------------*/ 62 | /* Exported constants --------------------------------------------------------*/ 63 | 64 | /* If an external clock source is used, then the value of the following define 65 | should be set to the value of the external clock source, else, if no external 66 | clock is used, keep this define commented */ 67 | /*#define I2S_EXTERNAL_CLOCK_VAL 12288000 */ /* Value of the external clock in Hz */ 68 | 69 | 70 | /* Uncomment the line below to expanse the "assert_param" macro in the 71 | Standard Peripheral Library drivers code */ 72 | /* #define USE_FULL_ASSERT 1 */ 73 | 74 | /* Exported macro ------------------------------------------------------------*/ 75 | #ifdef USE_FULL_ASSERT 76 | 77 | /** 78 | * @brief The assert_param macro is used for function's parameters check. 79 | * @param expr: If expr is false, it calls assert_failed function which reports 80 | * the name of the source file and the source line number of the call 81 | * that failed. If expr is true, it returns no value. 82 | * @retval None 83 | */ 84 | #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) 85 | /* Exported functions ------------------------------------------------------- */ 86 | void assert_failed(uint8_t* file, uint32_t line); 87 | #else 88 | #define assert_param(expr) ((void)0) 89 | #endif /* USE_FULL_ASSERT */ 90 | 91 | #endif /* __STM32F4xx_CONF_H */ 92 | 93 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 94 | -------------------------------------------------------------------------------- /stm32fxxx_it.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32fxxx_it.c 4 | * @author MCD Application Team 5 | * @version V1.1.0 6 | * @date 19-March-2012 7 | * @brief Main Interrupt Service Routines. 8 | * This file provides all exceptions handler and peripherals interrupt 9 | * service routine. 10 | ****************************************************************************** 11 | * @attention 12 | * 13 | *

© COPYRIGHT 2012 STMicroelectronics

14 | * 15 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 16 | * You may not use this file except in compliance with the License. 17 | * You may obtain a copy of the License at: 18 | * 19 | * http://www.st.com/software_license_agreement_liberty_v2 20 | * 21 | * Unless required by applicable law or agreed to in writing, software 22 | * distributed under the License is distributed on an "AS IS" BASIS, 23 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 | * See the License for the specific language governing permissions and 25 | * limitations under the License. 26 | * 27 | ****************************************************************************** 28 | */ 29 | 30 | /* Includes ------------------------------------------------------------------*/ 31 | #include "stm32f4xx.h" 32 | #include "stm32f4_discovery_sdio_sd.h" 33 | #include "stm32fxxx_it.h" 34 | 35 | /* Private typedef -----------------------------------------------------------*/ 36 | /* Private define ------------------------------------------------------------*/ 37 | /* Private macro -------------------------------------------------------------*/ 38 | /* Private variables ---------------------------------------------------------*/ 39 | /* Private function prototypes -----------------------------------------------*/ 40 | /* Private functions ---------------------------------------------------------*/ 41 | 42 | /******************************************************************************/ 43 | /* Cortex-M Processor Exceptions Handlers */ 44 | /******************************************************************************/ 45 | 46 | /** 47 | * @brief This function handles NMI exception. 48 | * @param None 49 | * @retval None 50 | */ 51 | void NMI_Handler(void) 52 | { 53 | } 54 | 55 | /** 56 | * @brief This function handles Hard Fault exception. 57 | * @param None 58 | * @retval None 59 | */ 60 | void HardFault_Handler(void) 61 | { 62 | /* Go to infinite loop when Hard Fault exception occurs */ 63 | while (1) 64 | { 65 | } 66 | } 67 | 68 | /** 69 | * @brief This function handles Memory Manage exception. 70 | * @param None 71 | * @retval None 72 | */ 73 | void MemManage_Handler(void) 74 | { 75 | /* Go to infinite loop when Memory Manage exception occurs */ 76 | while (1) 77 | { 78 | } 79 | } 80 | 81 | /** 82 | * @brief This function handles Bus Fault exception. 83 | * @param None 84 | * @retval None 85 | */ 86 | void BusFault_Handler(void) 87 | { 88 | /* Go to infinite loop when Bus Fault exception occurs */ 89 | while (1) 90 | { 91 | } 92 | } 93 | 94 | /** 95 | * @brief This function handles Usage Fault exception. 96 | * @param None 97 | * @retval None 98 | */ 99 | void UsageFault_Handler(void) 100 | { 101 | /* Go to infinite loop when Usage Fault exception occurs */ 102 | while (1) 103 | { 104 | } 105 | } 106 | 107 | /** 108 | * @brief This function handles SVCall exception. 109 | * @param None 110 | * @retval None 111 | */ 112 | void SVC_Handler(void) 113 | { 114 | } 115 | 116 | /** 117 | * @brief This function handles Debug Monitor exception. 118 | * @param None 119 | * @retval None 120 | */ 121 | void DebugMon_Handler(void) 122 | { 123 | } 124 | 125 | /** 126 | * @brief This function handles PendSVC exception. 127 | * @param None 128 | * @retval None 129 | */ 130 | void PendSV_Handler(void) 131 | { 132 | } 133 | 134 | /** 135 | * @brief This function handles SysTick Handler. 136 | * @param None 137 | * @retval None 138 | */ 139 | void SysTick_Handler(void) 140 | { 141 | } 142 | 143 | /** 144 | * @brief This function handles SDIO global interrupt request. 145 | * @param None 146 | * @retval None 147 | */ 148 | void SDIO_IRQHandler(void) 149 | { 150 | /* Process All SDIO Interrupt Sources */ 151 | SD_ProcessIRQSrc(); 152 | } 153 | 154 | /******************************************************************************/ 155 | /* STM32Fxxx Peripherals Interrupt Handlers */ 156 | /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ 157 | /* available peripheral interrupt handler's name please refer to the startup */ 158 | /* file (startup_stm32fxxx.s). */ 159 | /******************************************************************************/ 160 | 161 | /** 162 | * @brief This function handles PPP interrupt request. 163 | * @param None 164 | * @retval None 165 | */ 166 | /*void PPP_IRQHandler(void) 167 | { 168 | } 169 | */ 170 | 171 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 172 | -------------------------------------------------------------------------------- /stm32fxxx_it.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32fxxx_it.h 4 | * @author MCD Application Team 5 | * @version V1.1.0 6 | * @date 19-March-2012 7 | * @brief This file contains the headers of the interrupt handlers. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT 2012 STMicroelectronics

12 | * 13 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 14 | * You may not use this file except in compliance with the License. 15 | * You may obtain a copy of the License at: 16 | * 17 | * http://www.st.com/software_license_agreement_liberty_v2 18 | * 19 | * Unless required by applicable law or agreed to in writing, software 20 | * distributed under the License is distributed on an "AS IS" BASIS, 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | * See the License for the specific language governing permissions and 23 | * limitations under the License. 24 | * 25 | ****************************************************************************** 26 | */ 27 | 28 | /* Define to prevent recursive inclusion -------------------------------------*/ 29 | #ifndef __STM32Fxxx_IT_H 30 | #define __STM32Fxxx_IT_H 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /* Includes ------------------------------------------------------------------*/ 37 | /* Exported types ------------------------------------------------------------*/ 38 | /* Exported constants --------------------------------------------------------*/ 39 | /* Exported macro ------------------------------------------------------------*/ 40 | /* Exported functions ------------------------------------------------------- */ 41 | 42 | void NMI_Handler(void); 43 | void HardFault_Handler(void); 44 | void MemManage_Handler(void); 45 | void BusFault_Handler(void); 46 | void UsageFault_Handler(void); 47 | void SVC_Handler(void); 48 | void DebugMon_Handler(void); 49 | void PendSV_Handler(void); 50 | void SysTick_Handler(void); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif /* __STM32Fxxx_IT_H */ 57 | 58 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 59 | -------------------------------------------------------------------------------- /system_stm32f4xx.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f4xx.c 4 | * @author MCD Application Team 5 | * @version V1.1.0 6 | * @date 19-March-2012 7 | * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. 8 | * This file contains the system clock configuration for STM32F4xx devices, 9 | * and is generated by the clock configuration tool 10 | * stm32f4xx_Clock_Configuration_V1.0.0.xls 11 | * 12 | * 1. This file provides two functions and one global variable to be called from 13 | * user application: 14 | * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier 15 | * and Divider factors, AHB/APBx prescalers and Flash settings), 16 | * depending on the configuration made in the clock xls tool. 17 | * This function is called at startup just after reset and 18 | * before branch to main program. This call is made inside 19 | * the "startup_stm32f4xx.s" file. 20 | * 21 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used 22 | * by the user application to setup the SysTick 23 | * timer or configure other parameters. 24 | * 25 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must 26 | * be called whenever the core clock is changed 27 | * during program execution. 28 | * 29 | * 2. After each device reset the HSI (16 MHz) is used as system clock source. 30 | * Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to 31 | * configure the system clock before to branch to main program. 32 | * 33 | * 3. If the system clock source selected by user fails to startup, the SystemInit() 34 | * function will do nothing and HSI still used as system clock source. User can 35 | * add some code to deal with this issue inside the SetSysClock() function. 36 | * 37 | * 4. The default value of HSE crystal is set to 8 MHz, refer to "HSE_VALUE" define 38 | * in "stm32f4xx.h" file. When HSE is used as system clock source, directly or 39 | * through PLL, and you are using different crystal you have to adapt the HSE 40 | * value to your own configuration. 41 | * 42 | * 5. This file configures the system clock as follows: 43 | *============================================================================= 44 | *============================================================================= 45 | * Supported STM32F4xx device revision | Rev A 46 | *----------------------------------------------------------------------------- 47 | * System Clock source | PLL (HSE) 48 | *----------------------------------------------------------------------------- 49 | * SYSCLK(Hz) | 168000000 50 | *----------------------------------------------------------------------------- 51 | * HCLK(Hz) | 168000000 52 | *----------------------------------------------------------------------------- 53 | * AHB Prescaler | 1 54 | *----------------------------------------------------------------------------- 55 | * APB1 Prescaler | 4 56 | *----------------------------------------------------------------------------- 57 | * APB2 Prescaler | 2 58 | *----------------------------------------------------------------------------- 59 | * HSE Frequency(Hz) | 8000000 60 | *----------------------------------------------------------------------------- 61 | * PLL_M | 8 62 | *----------------------------------------------------------------------------- 63 | * PLL_N | 240 64 | *----------------------------------------------------------------------------- 65 | * PLL_P | 2 66 | *----------------------------------------------------------------------------- 67 | * PLL_Q | 5 68 | *----------------------------------------------------------------------------- 69 | * PLLI2S_N | 192 70 | *----------------------------------------------------------------------------- 71 | * PLLI2S_R | 5 72 | *----------------------------------------------------------------------------- 73 | * I2S input clock(Hz) | 38400000 74 | *----------------------------------------------------------------------------- 75 | * VDD(V) | 3.3 76 | *----------------------------------------------------------------------------- 77 | * High Performance mode | Enabled 78 | *----------------------------------------------------------------------------- 79 | * Flash Latency(WS) | 5 80 | *----------------------------------------------------------------------------- 81 | * Prefetch Buffer | OFF 82 | *----------------------------------------------------------------------------- 83 | * Instruction cache | ON 84 | *----------------------------------------------------------------------------- 85 | * Data cache | ON 86 | *----------------------------------------------------------------------------- 87 | * Require 48MHz for USB OTG FS, | Enabled 88 | * SDIO and RNG clock | 89 | *----------------------------------------------------------------------------- 90 | *============================================================================= 91 | ****************************************************************************** 92 | * @attention 93 | * 94 | *

© COPYRIGHT 2012 STMicroelectronics

95 | * 96 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 97 | * You may not use this file except in compliance with the License. 98 | * You may obtain a copy of the License at: 99 | * 100 | * http://www.st.com/software_license_agreement_liberty_v2 101 | * 102 | * Unless required by applicable law or agreed to in writing, software 103 | * distributed under the License is distributed on an "AS IS" BASIS, 104 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 105 | * See the License for the specific language governing permissions and 106 | * limitations under the License. 107 | * 108 | ****************************************************************************** 109 | */ 110 | 111 | /** @addtogroup CMSIS 112 | * @{ 113 | */ 114 | 115 | /** @addtogroup stm32f4xx_system 116 | * @{ 117 | */ 118 | 119 | /** @addtogroup STM32F4xx_System_Private_Includes 120 | * @{ 121 | */ 122 | 123 | #include "stm32f4xx.h" 124 | 125 | /** 126 | * @} 127 | */ 128 | 129 | /** @addtogroup STM32F4xx_System_Private_TypesDefinitions 130 | * @{ 131 | */ 132 | 133 | /** 134 | * @} 135 | */ 136 | 137 | /** @addtogroup STM32F4xx_System_Private_Defines 138 | * @{ 139 | */ 140 | 141 | /************************* Miscellaneous Configuration ************************/ 142 | /*!< Uncomment the following line if you need to use external SRAM mounted 143 | on STM324xG_EVAL board as data memory */ 144 | /* #define DATA_IN_ExtSRAM */ 145 | 146 | /*!< Uncomment the following line if you need to relocate your vector Table in 147 | Internal SRAM. */ 148 | /* #define VECT_TAB_SRAM */ 149 | #define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. 150 | This value must be a multiple of 0x200. */ 151 | /******************************************************************************/ 152 | 153 | /************************* PLL Parameters *************************************/ 154 | /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ 155 | #define PLL_M 8 156 | #define PLL_N 240 157 | 158 | /* SYSCLK = PLL_VCO / PLL_P */ 159 | #define PLL_P 2 160 | 161 | /* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ 162 | #define PLL_Q 5 163 | 164 | /* PLLI2S_VCO = (HSE_VALUE Or HSI_VALUE / PLL_M) * PLLI2S_N 165 | I2SCLK = PLLI2S_VCO / PLLI2S_R */ 166 | #define PLLI2S_N 192 167 | #define PLLI2S_R 5 168 | 169 | /******************************************************************************/ 170 | 171 | /** 172 | * @} 173 | */ 174 | 175 | /** @addtogroup STM32F4xx_System_Private_Macros 176 | * @{ 177 | */ 178 | 179 | /** 180 | * @} 181 | */ 182 | 183 | /** @addtogroup STM32F4xx_System_Private_Variables 184 | * @{ 185 | */ 186 | 187 | uint32_t SystemCoreClock = 120000000; 188 | 189 | __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; 190 | 191 | /** 192 | * @} 193 | */ 194 | 195 | /** @addtogroup STM32F4xx_System_Private_FunctionPrototypes 196 | * @{ 197 | */ 198 | 199 | static void SetSysClock(void); 200 | #ifdef DATA_IN_ExtSRAM 201 | static void SystemInit_ExtMemCtl(void); 202 | #endif /* DATA_IN_ExtSRAM */ 203 | 204 | /** 205 | * @} 206 | */ 207 | 208 | /** @addtogroup STM32F4xx_System_Private_Functions 209 | * @{ 210 | */ 211 | 212 | /** 213 | * @brief Setup the microcontroller system 214 | * Initialize the Embedded Flash Interface, the PLL and update the 215 | * SystemFrequency variable. 216 | * @param None 217 | * @retval None 218 | */ 219 | void SystemInit(void) 220 | { 221 | /* FPU settings ------------------------------------------------------------*/ 222 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 223 | SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ 224 | #endif 225 | 226 | /* Reset the RCC clock configuration to the default reset state ------------*/ 227 | /* Set HSION bit */ 228 | RCC->CR |= (uint32_t)0x00000001; 229 | 230 | /* Reset CFGR register */ 231 | RCC->CFGR = 0x00000000; 232 | 233 | /* Reset HSEON, CSSON and PLLON bits */ 234 | RCC->CR &= (uint32_t)0xFEF6FFFF; 235 | 236 | /* Reset PLLCFGR register */ 237 | RCC->PLLCFGR = 0x24003010; 238 | 239 | /* Reset HSEBYP bit */ 240 | RCC->CR &= (uint32_t)0xFFFBFFFF; 241 | 242 | /* Disable all interrupts */ 243 | RCC->CIR = 0x00000000; 244 | 245 | #ifdef DATA_IN_ExtSRAM 246 | SystemInit_ExtMemCtl(); 247 | #endif /* DATA_IN_ExtSRAM */ 248 | 249 | /* Configure the System clock source, PLL Multiplier and Divider factors, 250 | AHB/APBx prescalers and Flash settings ----------------------------------*/ 251 | SetSysClock(); 252 | 253 | /* Configure the Vector Table location add offset address ------------------*/ 254 | #ifdef VECT_TAB_SRAM 255 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ 256 | #else 257 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ 258 | #endif 259 | } 260 | 261 | /** 262 | * @brief Update SystemCoreClock variable according to Clock Register Values. 263 | * The SystemCoreClock variable contains the core clock (HCLK), it can 264 | * be used by the user application to setup the SysTick timer or configure 265 | * other parameters. 266 | * 267 | * @note Each time the core clock (HCLK) changes, this function must be called 268 | * to update SystemCoreClock variable value. Otherwise, any configuration 269 | * based on this variable will be incorrect. 270 | * 271 | * @note - The system frequency computed by this function is not the real 272 | * frequency in the chip. It is calculated based on the predefined 273 | * constant and the selected clock source: 274 | * 275 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) 276 | * 277 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) 278 | * 279 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 280 | * or HSI_VALUE(*) multiplied/divided by the PLL factors. 281 | * 282 | * (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value 283 | * 16 MHz) but the real value may vary depending on the variations 284 | * in voltage and temperature. 285 | * 286 | * (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value 287 | * 25 MHz), user has to ensure that HSE_VALUE is same as the real 288 | * frequency of the crystal used. Otherwise, this function may 289 | * have wrong result. 290 | * 291 | * - The result of this function could be not correct when using fractional 292 | * value for HSE crystal. 293 | * 294 | * @param None 295 | * @retval None 296 | */ 297 | void SystemCoreClockUpdate(void) 298 | { 299 | uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2; 300 | 301 | /* Get SYSCLK source -------------------------------------------------------*/ 302 | tmp = RCC->CFGR & RCC_CFGR_SWS; 303 | 304 | switch (tmp) 305 | { 306 | case 0x00: /* HSI used as system clock source */ 307 | SystemCoreClock = HSI_VALUE; 308 | break; 309 | case 0x04: /* HSE used as system clock source */ 310 | SystemCoreClock = HSE_VALUE; 311 | break; 312 | case 0x08: /* PLL used as system clock source */ 313 | 314 | /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N 315 | SYSCLK = PLL_VCO / PLL_P 316 | */ 317 | pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; 318 | pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; 319 | 320 | if (pllsource != 0) 321 | { 322 | /* HSE used as PLL clock source */ 323 | pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); 324 | } 325 | else 326 | { 327 | /* HSI used as PLL clock source */ 328 | pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); 329 | } 330 | 331 | pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; 332 | SystemCoreClock = pllvco/pllp; 333 | break; 334 | default: 335 | SystemCoreClock = HSI_VALUE; 336 | break; 337 | } 338 | /* Compute HCLK frequency --------------------------------------------------*/ 339 | /* Get HCLK prescaler */ 340 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; 341 | /* HCLK frequency */ 342 | SystemCoreClock >>= tmp; 343 | } 344 | 345 | /** 346 | * @brief Configures the System clock source, PLL Multiplier and Divider factors, 347 | * AHB/APBx prescalers and Flash settings 348 | * @Note This function should be called only once the RCC clock configuration 349 | * is reset to the default reset state (done in SystemInit() function). 350 | * @param None 351 | * @retval None 352 | */ 353 | static void SetSysClock(void) 354 | { 355 | /******************************************************************************/ 356 | /* PLL (clocked by HSE) used as System clock source */ 357 | /******************************************************************************/ 358 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 359 | 360 | /* Enable HSE */ 361 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 362 | 363 | /* Wait till HSE is ready and if Time out is reached exit */ 364 | do 365 | { 366 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 367 | StartUpCounter++; 368 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 369 | 370 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 371 | { 372 | HSEStatus = (uint32_t)0x01; 373 | } 374 | else 375 | { 376 | HSEStatus = (uint32_t)0x00; 377 | } 378 | 379 | if (HSEStatus == (uint32_t)0x01) 380 | { 381 | /* Enable high performance mode, System frequency up to 168 MHz */ 382 | RCC->APB1ENR |= RCC_APB1ENR_PWREN; 383 | PWR->CR |= PWR_CR_PMODE; 384 | 385 | /* HCLK = SYSCLK / 1*/ 386 | RCC->CFGR |= RCC_CFGR_HPRE_DIV1; 387 | 388 | /* PCLK2 = HCLK / 2*/ 389 | RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; 390 | 391 | /* PCLK1 = HCLK / 4*/ 392 | RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; 393 | 394 | /* Configure the main PLL */ 395 | RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | 396 | (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); 397 | 398 | /* Enable the main PLL */ 399 | RCC->CR |= RCC_CR_PLLON; 400 | 401 | /* Wait till the main PLL is ready */ 402 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 403 | { 404 | } 405 | 406 | /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ 407 | FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; 408 | 409 | /* Select the main PLL as system clock source */ 410 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 411 | RCC->CFGR |= RCC_CFGR_SW_PLL; 412 | 413 | /* Wait till the main PLL is used as system clock source */ 414 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); 415 | } 416 | else 417 | { /* If HSE fails to start-up, the application will have wrong clock 418 | configuration. User can add here some code to deal with this error */ 419 | } 420 | 421 | /******************************************************************************/ 422 | /* I2S clock configuration */ 423 | /******************************************************************************/ 424 | /* PLLI2S clock used as I2S clock source */ 425 | RCC->CFGR &= ~RCC_CFGR_I2SSRC; 426 | 427 | /* Configure PLLI2S */ 428 | RCC->PLLI2SCFGR = (PLLI2S_N << 6) | (PLLI2S_R << 28); 429 | 430 | /* Enable PLLI2S */ 431 | RCC->CR |= ((uint32_t)RCC_CR_PLLI2SON); 432 | 433 | /* Wait till PLLI2S is ready */ 434 | while((RCC->CR & RCC_CR_PLLI2SRDY) == 0) 435 | { 436 | } 437 | } 438 | 439 | /** 440 | * @brief Setup the external memory controller. Called in startup_stm32f4xx.s 441 | * before jump to __main 442 | * @param None 443 | * @retval None 444 | */ 445 | #ifdef DATA_IN_ExtSRAM 446 | /** 447 | * @brief Setup the external memory controller. 448 | * Called in startup_stm32f4xx.s before jump to main. 449 | * This function configures the external SRAM mounted on STM324xG_EVAL board 450 | * This SRAM will be used as program data memory (including heap and stack). 451 | * @param None 452 | * @retval None 453 | */ 454 | void SystemInit_ExtMemCtl(void) 455 | { 456 | /*-- GPIOs Configuration -----------------------------------------------------*/ 457 | /* 458 | +-------------------+--------------------+------------------+------------------+ 459 | + SRAM pins assignment + 460 | +-------------------+--------------------+------------------+------------------+ 461 | | PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 | 462 | | PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 | 463 | | PD4 <-> FSMC_NOE | PE3 <-> FSMC_A19 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 | 464 | | PD5 <-> FSMC_NWE | PE4 <-> FSMC_A20 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 | 465 | | PD8 <-> FSMC_D13 | PE7 <-> FSMC_D4 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 | 466 | | PD9 <-> FSMC_D14 | PE8 <-> FSMC_D5 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 | 467 | | PD10 <-> FSMC_D15 | PE9 <-> FSMC_D6 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | 468 | | PD11 <-> FSMC_A16 | PE10 <-> FSMC_D7 | PF13 <-> FSMC_A7 |------------------+ 469 | | PD12 <-> FSMC_A17 | PE11 <-> FSMC_D8 | PF14 <-> FSMC_A8 | 470 | | PD13 <-> FSMC_A18 | PE12 <-> FSMC_D9 | PF15 <-> FSMC_A9 | 471 | | PD14 <-> FSMC_D0 | PE13 <-> FSMC_D10 |------------------+ 472 | | PD15 <-> FSMC_D1 | PE14 <-> FSMC_D11 | 473 | | | PE15 <-> FSMC_D12 | 474 | +-------------------+--------------------+ 475 | */ 476 | /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ 477 | RCC->AHB1ENR = 0x00000078; 478 | 479 | /* Connect PDx pins to FSMC Alternate function */ 480 | GPIOD->AFR[0] = 0x00cc00cc; 481 | GPIOD->AFR[1] = 0xcc0ccccc; 482 | /* Configure PDx pins in Alternate function mode */ 483 | GPIOD->MODER = 0xaaaa0a0a; 484 | /* Configure PDx pins speed to 100 MHz */ 485 | GPIOD->OSPEEDR = 0xffff0f0f; 486 | /* Configure PDx pins Output type to push-pull */ 487 | GPIOD->OTYPER = 0x00000000; 488 | /* No pull-up, pull-down for PDx pins */ 489 | GPIOD->PUPDR = 0x00000000; 490 | 491 | /* Connect PEx pins to FSMC Alternate function */ 492 | GPIOE->AFR[0] = 0xc00cc0cc; 493 | GPIOE->AFR[1] = 0xcccccccc; 494 | /* Configure PEx pins in Alternate function mode */ 495 | GPIOE->MODER = 0xaaaa828a; 496 | /* Configure PEx pins speed to 100 MHz */ 497 | GPIOE->OSPEEDR = 0xffffc3cf; 498 | /* Configure PEx pins Output type to push-pull */ 499 | GPIOE->OTYPER = 0x00000000; 500 | /* No pull-up, pull-down for PEx pins */ 501 | GPIOE->PUPDR = 0x00000000; 502 | 503 | /* Connect PFx pins to FSMC Alternate function */ 504 | GPIOF->AFR[0] = 0x00cccccc; 505 | GPIOF->AFR[1] = 0xcccc0000; 506 | /* Configure PFx pins in Alternate function mode */ 507 | GPIOF->MODER = 0xaa000aaa; 508 | /* Configure PFx pins speed to 100 MHz */ 509 | GPIOF->OSPEEDR = 0xff000fff; 510 | /* Configure PFx pins Output type to push-pull */ 511 | GPIOF->OTYPER = 0x00000000; 512 | /* No pull-up, pull-down for PFx pins */ 513 | GPIOF->PUPDR = 0x00000000; 514 | 515 | /* Connect PGx pins to FSMC Alternate function */ 516 | GPIOG->AFR[0] = 0x00cccccc; 517 | GPIOG->AFR[1] = 0x000000c0; 518 | /* Configure PGx pins in Alternate function mode */ 519 | GPIOG->MODER = 0x00080aaa; 520 | /* Configure PGx pins speed to 100 MHz */ 521 | GPIOG->OSPEEDR = 0x000c0fff; 522 | /* Configure PGx pins Output type to push-pull */ 523 | GPIOG->OTYPER = 0x00000000; 524 | /* No pull-up, pull-down for PGx pins */ 525 | GPIOG->PUPDR = 0x00000000; 526 | 527 | /*-- FSMC Configuration ------------------------------------------------------*/ 528 | /* Enable the FSMC interface clock */ 529 | RCC->AHB3ENR = 0x00000001; 530 | 531 | /* Configure and enable Bank1_SRAM2 */ 532 | FSMC_Bank1->BTCR[2] = 0x00001015; 533 | FSMC_Bank1->BTCR[3] = 0x00010603;//0x00010400; 534 | FSMC_Bank1E->BWTR[2] = 0x0fffffff; 535 | /* 536 | Bank1_SRAM2 is configured as follow: 537 | 538 | p.FSMC_AddressSetupTime = 3;//0; 539 | p.FSMC_AddressHoldTime = 0; 540 | p.FSMC_DataSetupTime = 6;//4; 541 | p.FSMC_BusTurnAroundDuration = 1; 542 | p.FSMC_CLKDivision = 0; 543 | p.FSMC_DataLatency = 0; 544 | p.FSMC_AccessMode = FSMC_AccessMode_A; 545 | 546 | FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2; 547 | FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; 548 | FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; 549 | FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; 550 | FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; 551 | FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; 552 | FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; 553 | FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; 554 | FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; 555 | FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; 556 | FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; 557 | FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; 558 | FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; 559 | FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p; 560 | FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; 561 | */ 562 | 563 | } 564 | #endif /* DATA_IN_ExtSRAM */ 565 | 566 | 567 | /** 568 | * @} 569 | */ 570 | 571 | /** 572 | * @} 573 | */ 574 | 575 | /** 576 | * @} 577 | */ 578 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 579 | 580 | -------------------------------------------------------------------------------- /transfer.sh: -------------------------------------------------------------------------------- 1 | sudo dfu-util -v -d 0483:df11 -a 0 -s 0x08000000 -D amstradcpc-rom-emulator 2 | --------------------------------------------------------------------------------