Eli Hughes
/
COMPACT_FLASH
Compact Flash I/O test
FAT_FS/diskio.c@0:6b1e6c9e48ba, 2011-12-27 (annotated)
- Committer:
- emh203
- Date:
- Tue Dec 27 02:03:56 2011 +0000
- Revision:
- 0:6b1e6c9e48ba
- Child:
- 1:dc171f34db9b
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
emh203 | 0:6b1e6c9e48ba | 1 | #include "mbed.h" |
emh203 | 0:6b1e6c9e48ba | 2 | #include "LPC17xx.h" |
emh203 | 0:6b1e6c9e48ba | 3 | #include "integer.h" |
emh203 | 0:6b1e6c9e48ba | 4 | #include "diskio.h" |
emh203 | 0:6b1e6c9e48ba | 5 | #include "stdarg.h" |
emh203 | 0:6b1e6c9e48ba | 6 | |
emh203 | 0:6b1e6c9e48ba | 7 | #define _CF_DEBUG_MESSAGES |
emh203 | 0:6b1e6c9e48ba | 8 | //#define _CF_DEBUG_READ_ATA |
emh203 | 0:6b1e6c9e48ba | 9 | |
emh203 | 0:6b1e6c9e48ba | 10 | #ifdef _CF_DEBUG_MESSAGES |
emh203 | 0:6b1e6c9e48ba | 11 | #define CF_DEBUG(...) printf(__VA_ARGS__) |
emh203 | 0:6b1e6c9e48ba | 12 | #else |
emh203 | 0:6b1e6c9e48ba | 13 | #define CF_DEBUG |
emh203 | 0:6b1e6c9e48ba | 14 | #endif |
emh203 | 0:6b1e6c9e48ba | 15 | |
emh203 | 0:6b1e6c9e48ba | 16 | |
emh203 | 0:6b1e6c9e48ba | 17 | void disk_timerproc (void); |
emh203 | 0:6b1e6c9e48ba | 18 | |
emh203 | 0:6b1e6c9e48ba | 19 | |
emh203 | 0:6b1e6c9e48ba | 20 | #define LED1_MASK (uint32_t )(1<<18) |
emh203 | 0:6b1e6c9e48ba | 21 | #define LED2_MASK (uint32_t )(1<<20) |
emh203 | 0:6b1e6c9e48ba | 22 | #define LED3_MASK (uint32_t )(1<<21) |
emh203 | 0:6b1e6c9e48ba | 23 | #define LED4_MASK (uint32_t )(1<<23) |
emh203 | 0:6b1e6c9e48ba | 24 | |
emh203 | 0:6b1e6c9e48ba | 25 | |
emh203 | 0:6b1e6c9e48ba | 26 | #define LED1_ON LPC_GPIO1->FIOSET=LED1_MASK |
emh203 | 0:6b1e6c9e48ba | 27 | #define LED1_OFF LPC_GPIO1->FIOCLR=LED1_MASK |
emh203 | 0:6b1e6c9e48ba | 28 | #define LED1_TOGGLE LPC_GPIO1->FIOPIN^=LED1_MASK |
emh203 | 0:6b1e6c9e48ba | 29 | |
emh203 | 0:6b1e6c9e48ba | 30 | #define LED2_ON LPC_GPIO1->FIOSET=LED2_MASK |
emh203 | 0:6b1e6c9e48ba | 31 | #define LED2_OFF LPC_GPIO1->FIOCLR=LED2_MASK |
emh203 | 0:6b1e6c9e48ba | 32 | #define LED2_TOGGLE LPC_GPIO1->FIOPIN^=LED2_MASK |
emh203 | 0:6b1e6c9e48ba | 33 | |
emh203 | 0:6b1e6c9e48ba | 34 | #define LED3_ON LPC_GPIO1->FIOSET=LED3_MASK |
emh203 | 0:6b1e6c9e48ba | 35 | #define LED3_OFF LPC_GPIO1->FIOCLR=LED3_MASK |
emh203 | 0:6b1e6c9e48ba | 36 | #define LED3_TOGGLE LPC_GPIO1->FIOPIN^=LED3_MASK |
emh203 | 0:6b1e6c9e48ba | 37 | |
emh203 | 0:6b1e6c9e48ba | 38 | #define LED4_ON LPC_GPIO1->FIOSET=LED4_MASK |
emh203 | 0:6b1e6c9e48ba | 39 | #define LED4_OFF LPC_GPIO1->FIOCLR=LED4_MASK |
emh203 | 0:6b1e6c9e48ba | 40 | #define LED4_TOGGLE LPC_GPIO1->FIOPIN^=LED4_MASK |
emh203 | 0:6b1e6c9e48ba | 41 | |
emh203 | 0:6b1e6c9e48ba | 42 | |
emh203 | 0:6b1e6c9e48ba | 43 | |
emh203 | 0:6b1e6c9e48ba | 44 | //8-bit Data Bus is on Pins P0.4 - P0.11 |
emh203 | 0:6b1e6c9e48ba | 45 | #define DATA_BUS_MASK (uint32_t )((0xFF)<<4) |
emh203 | 0:6b1e6c9e48ba | 46 | |
emh203 | 0:6b1e6c9e48ba | 47 | //3 bit address is on Port 2.0 - 2.2 |
emh203 | 0:6b1e6c9e48ba | 48 | #define ADDRESS_BUS_MASK (uint32_t )(0x7) |
emh203 | 0:6b1e6c9e48ba | 49 | |
emh203 | 0:6b1e6c9e48ba | 50 | //ChipSelects are on port 2 |
emh203 | 0:6b1e6c9e48ba | 51 | #define CS0_MASK (uint32_t )(1<<3) |
emh203 | 0:6b1e6c9e48ba | 52 | #define CS1_MASK (uint32_t )(1<<4) |
emh203 | 0:6b1e6c9e48ba | 53 | |
emh203 | 0:6b1e6c9e48ba | 54 | //IORD and IOWR are on port 0 |
emh203 | 0:6b1e6c9e48ba | 55 | #define IORD_MASK (uint32_t )(1<<24) |
emh203 | 0:6b1e6c9e48ba | 56 | #define IOWR_MASK (uint32_t )(1<<23) |
emh203 | 0:6b1e6c9e48ba | 57 | |
emh203 | 0:6b1e6c9e48ba | 58 | |
emh203 | 0:6b1e6c9e48ba | 59 | //Reset and power enable are on port 1 |
emh203 | 0:6b1e6c9e48ba | 60 | #define COMPACT_FLASH_RESET_MASK (uint32_t )(1<<30) |
emh203 | 0:6b1e6c9e48ba | 61 | #define COMPACT_FLASH_POWER_ENABLE_MASK (uint32_t )(0x80000000) |
emh203 | 0:6b1e6c9e48ba | 62 | //Card Detect is on Port 2 |
emh203 | 0:6b1e6c9e48ba | 63 | #define COMPACT_FLASH_CARD_DETECT_MASK (uint32_t )(1<<5) |
emh203 | 0:6b1e6c9e48ba | 64 | |
emh203 | 0:6b1e6c9e48ba | 65 | //Low Level Bus Operation Macros |
emh203 | 0:6b1e6c9e48ba | 66 | //Note: LPC 176x have dedicate set and clear registers |
emh203 | 0:6b1e6c9e48ba | 67 | |
emh203 | 0:6b1e6c9e48ba | 68 | #define SET_DATA_BUS_TO_INPUTS LPC_GPIO0->FIODIR &= ~(DATA_BUS_MASK); |
emh203 | 0:6b1e6c9e48ba | 69 | #define SET_DATA_BUS_TO_OUTPUT LPC_GPIO0->FIODIR |= (DATA_BUS_MASK); |
emh203 | 0:6b1e6c9e48ba | 70 | |
emh203 | 0:6b1e6c9e48ba | 71 | #define CS0_ACTIVE LPC_GPIO2->FIOCLR = CS0_MASK |
emh203 | 0:6b1e6c9e48ba | 72 | #define CS0_INACTIVE LPC_GPIO2->FIOSET = CS0_MASK |
emh203 | 0:6b1e6c9e48ba | 73 | #define CS1_ACTIVE LPC_GPIO2->FIOCLR = CS1_MASK |
emh203 | 0:6b1e6c9e48ba | 74 | #define CS1_INACTIVE LPC_GPIO2->FIOSET = CS1_MASK |
emh203 | 0:6b1e6c9e48ba | 75 | |
emh203 | 0:6b1e6c9e48ba | 76 | #define IORD_ACTIVE LPC_GPIO0->FIOCLR = IORD_MASK |
emh203 | 0:6b1e6c9e48ba | 77 | #define IORD_INACTIVE LPC_GPIO0->FIOSET = IORD_MASK |
emh203 | 0:6b1e6c9e48ba | 78 | |
emh203 | 0:6b1e6c9e48ba | 79 | #define IOWR_ACTIVE LPC_GPIO0->FIOCLR = IOWR_MASK |
emh203 | 0:6b1e6c9e48ba | 80 | #define IOWR_INACTIVE LPC_GPIO0->FIOSET = IOWR_MASK |
emh203 | 0:6b1e6c9e48ba | 81 | |
emh203 | 0:6b1e6c9e48ba | 82 | #define COMPACT_FLASH_RESET_ACTIVE LPC_GPIO1->FIOCLR = COMPACT_FLASH_RESET_MASK |
emh203 | 0:6b1e6c9e48ba | 83 | #define COMPACT_FLASH_RESET_INACTIVE LPC_GPIO1->FIOSET = COMPACT_FLASH_RESET_MASK |
emh203 | 0:6b1e6c9e48ba | 84 | |
emh203 | 0:6b1e6c9e48ba | 85 | #define COMPACT_FLASH_POWER_ENABLE LPC_GPIO1->FIOCLR = COMPACT_FLASH_POWER_ENABLE_MASK |
emh203 | 0:6b1e6c9e48ba | 86 | #define COMPACT_FLASH_POWER_DISABLE LPC_GPIO1->FIOSET = COMPACT_FLASH_POWER_ENABLE_MASK |
emh203 | 0:6b1e6c9e48ba | 87 | |
emh203 | 0:6b1e6c9e48ba | 88 | #define COMPACT_FLASH_CARD_DETECTED (!((LPC_GPIO2->FIOPIN)&COMPACT_FLASH_CARD_DETECT_MASK)) |
emh203 | 0:6b1e6c9e48ba | 89 | |
emh203 | 0:6b1e6c9e48ba | 90 | //To set the Address and Data Bus Lines we will use the convient Mask register in the Port I/O modules |
emh203 | 0:6b1e6c9e48ba | 91 | //The Hardware will mask out pins that are set to 1 in the MASK register |
emh203 | 0:6b1e6c9e48ba | 92 | |
emh203 | 0:6b1e6c9e48ba | 93 | #define SET_CF_ADDRESS(ADDRESS) LPC_GPIO2->FIOMASK=~(ADDRESS_BUS_MASK); \ |
emh203 | 0:6b1e6c9e48ba | 94 | LPC_GPIO2->FIOPIN=ADDRESS; \ |
emh203 | 0:6b1e6c9e48ba | 95 | LPC_GPIO2->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly |
emh203 | 0:6b1e6c9e48ba | 96 | |
emh203 | 0:6b1e6c9e48ba | 97 | |
emh203 | 0:6b1e6c9e48ba | 98 | #define SET_CF_DATA(DATA) LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK); \ |
emh203 | 0:6b1e6c9e48ba | 99 | LPC_GPIO0->FIOPIN=(((uint32_t)DATA)<<4); \ |
emh203 | 0:6b1e6c9e48ba | 100 | LPC_GPIO0->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly |
emh203 | 0:6b1e6c9e48ba | 101 | |
emh203 | 0:6b1e6c9e48ba | 102 | #define GET_CF_DATA(DATA) LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK); \ |
emh203 | 0:6b1e6c9e48ba | 103 | (DATA) = (LPC_GPIO0->FIOPIN)>>4; \ |
emh203 | 0:6b1e6c9e48ba | 104 | LPC_GPIO0->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly |
emh203 | 0:6b1e6c9e48ba | 105 | |
emh203 | 0:6b1e6c9e48ba | 106 | #define SET_DATA_BUS_AS_OUTPUTS LPC_GPIO0->FIODIR|=DATA_BUS_MASK |
emh203 | 0:6b1e6c9e48ba | 107 | #define SET_DATA_BUS_AS_INPUTS LPC_GPIO0->FIODIR&=~DATA_BUS_MASK |
emh203 | 0:6b1e6c9e48ba | 108 | |
emh203 | 0:6b1e6c9e48ba | 109 | |
emh203 | 0:6b1e6c9e48ba | 110 | |
emh203 | 0:6b1e6c9e48ba | 111 | /* ATA command */ |
emh203 | 0:6b1e6c9e48ba | 112 | #define CMD_RESET 0x08 /* DEVICE RESET */ |
emh203 | 0:6b1e6c9e48ba | 113 | #define CMD_READ 0x20 /* READ SECTOR(S) */ |
emh203 | 0:6b1e6c9e48ba | 114 | #define CMD_WRITE 0x30 /* WRITE SECTOR(S) */ |
emh203 | 0:6b1e6c9e48ba | 115 | #define CMD_IDENTIFY 0xEC /* DEVICE IDENTIFY */ |
emh203 | 0:6b1e6c9e48ba | 116 | #define CMD_SETFEATURES 0xEF /* SET FEATURES */ |
emh203 | 0:6b1e6c9e48ba | 117 | |
emh203 | 0:6b1e6c9e48ba | 118 | /* ATA register bit definitions */ |
emh203 | 0:6b1e6c9e48ba | 119 | #define LBA 0xE0 |
emh203 | 0:6b1e6c9e48ba | 120 | #define BUSY 0x80 |
emh203 | 0:6b1e6c9e48ba | 121 | #define DRDY 0x40 |
emh203 | 0:6b1e6c9e48ba | 122 | #define DF 0x20 |
emh203 | 0:6b1e6c9e48ba | 123 | #define DRQ 0x08 |
emh203 | 0:6b1e6c9e48ba | 124 | #define ERR 0x01 |
emh203 | 0:6b1e6c9e48ba | 125 | #define SRST 0x40 |
emh203 | 0:6b1e6c9e48ba | 126 | #define nIEN 0x20 |
emh203 | 0:6b1e6c9e48ba | 127 | |
emh203 | 0:6b1e6c9e48ba | 128 | /* Bit definitions for Control Port */ |
emh203 | 0:6b1e6c9e48ba | 129 | #define CTL_READ 0x20 |
emh203 | 0:6b1e6c9e48ba | 130 | #define CTL_WRITE 0x40 |
emh203 | 0:6b1e6c9e48ba | 131 | #define CTL_RESET 0x80 |
emh203 | 0:6b1e6c9e48ba | 132 | #define REG_DATA 0x0 |
emh203 | 0:6b1e6c9e48ba | 133 | #define REG_ERROR 0x1 |
emh203 | 0:6b1e6c9e48ba | 134 | #define REG_FEATURES 0x1 |
emh203 | 0:6b1e6c9e48ba | 135 | #define REG_COUNT 0x2 |
emh203 | 0:6b1e6c9e48ba | 136 | #define REG_SECTOR 0x3 |
emh203 | 0:6b1e6c9e48ba | 137 | #define REG_CYLL 0x4 |
emh203 | 0:6b1e6c9e48ba | 138 | #define REG_CYLH 0x5 |
emh203 | 0:6b1e6c9e48ba | 139 | #define REG_DEV 0x6 |
emh203 | 0:6b1e6c9e48ba | 140 | #define REG_COMMAND 0x7 |
emh203 | 0:6b1e6c9e48ba | 141 | #define REG_STATUS 0x7 |
emh203 | 0:6b1e6c9e48ba | 142 | #define REG_DEVCTRL 0xE |
emh203 | 0:6b1e6c9e48ba | 143 | #define REG_ALTSTAT 0xE |
emh203 | 0:6b1e6c9e48ba | 144 | |
emh203 | 0:6b1e6c9e48ba | 145 | |
emh203 | 0:6b1e6c9e48ba | 146 | |
emh203 | 0:6b1e6c9e48ba | 147 | /*-------------------------------------------------------------------------- |
emh203 | 0:6b1e6c9e48ba | 148 | |
emh203 | 0:6b1e6c9e48ba | 149 | Module Private Functions |
emh203 | 0:6b1e6c9e48ba | 150 | |
emh203 | 0:6b1e6c9e48ba | 151 | ---------------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 152 | |
emh203 | 0:6b1e6c9e48ba | 153 | static volatile |
emh203 | 0:6b1e6c9e48ba | 154 | DSTATUS Stat = STA_NOINIT; /* Disk status */ |
emh203 | 0:6b1e6c9e48ba | 155 | |
emh203 | 0:6b1e6c9e48ba | 156 | static volatile |
emh203 | 0:6b1e6c9e48ba | 157 | BYTE DiskProcTimer; /* 100Hz decrement timer */ |
emh203 | 0:6b1e6c9e48ba | 158 | |
emh203 | 0:6b1e6c9e48ba | 159 | |
emh203 | 0:6b1e6c9e48ba | 160 | |
emh203 | 0:6b1e6c9e48ba | 161 | void InitCompactFlashInterface() |
emh203 | 0:6b1e6c9e48ba | 162 | { |
emh203 | 0:6b1e6c9e48ba | 163 | SET_DATA_BUS_AS_INPUTS; |
emh203 | 0:6b1e6c9e48ba | 164 | |
emh203 | 0:6b1e6c9e48ba | 165 | LPC_GPIO2->FIODIR |= ADDRESS_BUS_MASK | CS0_MASK | CS1_MASK; |
emh203 | 0:6b1e6c9e48ba | 166 | LPC_GPIO2->FIODIR &=~(COMPACT_FLASH_CARD_DETECT_MASK); |
emh203 | 0:6b1e6c9e48ba | 167 | LPC_GPIO1->FIODIR |= COMPACT_FLASH_RESET_MASK | COMPACT_FLASH_POWER_ENABLE_MASK | LED1_MASK | LED2_MASK | LED3_MASK | LED4_MASK; |
emh203 | 0:6b1e6c9e48ba | 168 | LPC_GPIO0->FIODIR |= IORD_MASK | IOWR_MASK ; |
emh203 | 0:6b1e6c9e48ba | 169 | |
emh203 | 0:6b1e6c9e48ba | 170 | COMPACT_FLASH_RESET_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 171 | COMPACT_FLASH_POWER_DISABLE; |
emh203 | 0:6b1e6c9e48ba | 172 | CS0_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 173 | CS1_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 174 | |
emh203 | 0:6b1e6c9e48ba | 175 | SysTick_Config(SystemCoreClock/100); |
emh203 | 0:6b1e6c9e48ba | 176 | NVIC_SetVector(SysTick_IRQn, (uint32_t)(&disk_timerproc)); |
emh203 | 0:6b1e6c9e48ba | 177 | } |
emh203 | 0:6b1e6c9e48ba | 178 | |
emh203 | 0:6b1e6c9e48ba | 179 | |
emh203 | 0:6b1e6c9e48ba | 180 | void CompactFlashIO_Test() |
emh203 | 0:6b1e6c9e48ba | 181 | { |
emh203 | 0:6b1e6c9e48ba | 182 | |
emh203 | 0:6b1e6c9e48ba | 183 | SET_DATA_BUS_AS_OUTPUTS; |
emh203 | 0:6b1e6c9e48ba | 184 | while(1) |
emh203 | 0:6b1e6c9e48ba | 185 | { |
emh203 | 0:6b1e6c9e48ba | 186 | |
emh203 | 0:6b1e6c9e48ba | 187 | wait(0.1); |
emh203 | 0:6b1e6c9e48ba | 188 | COMPACT_FLASH_RESET_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 189 | COMPACT_FLASH_POWER_ENABLE; |
emh203 | 0:6b1e6c9e48ba | 190 | IOWR_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 191 | IORD_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 192 | CS0_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 193 | CS1_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 194 | SET_CF_ADDRESS(0x04); |
emh203 | 0:6b1e6c9e48ba | 195 | SET_CF_DATA(0x80); |
emh203 | 0:6b1e6c9e48ba | 196 | |
emh203 | 0:6b1e6c9e48ba | 197 | wait(0.1); |
emh203 | 0:6b1e6c9e48ba | 198 | COMPACT_FLASH_RESET_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 199 | COMPACT_FLASH_POWER_DISABLE; |
emh203 | 0:6b1e6c9e48ba | 200 | IOWR_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 201 | IORD_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 202 | CS0_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 203 | CS1_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 204 | SET_CF_ADDRESS(0x00); |
emh203 | 0:6b1e6c9e48ba | 205 | SET_CF_DATA(0x00); |
emh203 | 0:6b1e6c9e48ba | 206 | } |
emh203 | 0:6b1e6c9e48ba | 207 | } |
emh203 | 0:6b1e6c9e48ba | 208 | |
emh203 | 0:6b1e6c9e48ba | 209 | |
emh203 | 0:6b1e6c9e48ba | 210 | |
emh203 | 0:6b1e6c9e48ba | 211 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 212 | /* Read an ATA register */ |
emh203 | 0:6b1e6c9e48ba | 213 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 214 | |
emh203 | 0:6b1e6c9e48ba | 215 | static |
emh203 | 0:6b1e6c9e48ba | 216 | BYTE read_ata ( |
emh203 | 0:6b1e6c9e48ba | 217 | BYTE reg /* Register to be read */ |
emh203 | 0:6b1e6c9e48ba | 218 | ) |
emh203 | 0:6b1e6c9e48ba | 219 | { |
emh203 | 0:6b1e6c9e48ba | 220 | BYTE rd; |
emh203 | 0:6b1e6c9e48ba | 221 | DWORD i; |
emh203 | 0:6b1e6c9e48ba | 222 | |
emh203 | 0:6b1e6c9e48ba | 223 | CS0_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 224 | SET_DATA_BUS_AS_INPUTS; |
emh203 | 0:6b1e6c9e48ba | 225 | SET_CF_ADDRESS(reg); |
emh203 | 0:6b1e6c9e48ba | 226 | IORD_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 227 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 228 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 229 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 230 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 231 | |
emh203 | 0:6b1e6c9e48ba | 232 | GET_CF_DATA(rd); |
emh203 | 0:6b1e6c9e48ba | 233 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 234 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 235 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 236 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 237 | IORD_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 238 | CS0_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 239 | #ifdef _CF_DEBUG_READ_ATA |
emh203 | 0:6b1e6c9e48ba | 240 | CF_DEBUG("rd 0x%2x\r\n",rd); |
emh203 | 0:6b1e6c9e48ba | 241 | #endif |
emh203 | 0:6b1e6c9e48ba | 242 | return rd; |
emh203 | 0:6b1e6c9e48ba | 243 | } |
emh203 | 0:6b1e6c9e48ba | 244 | |
emh203 | 0:6b1e6c9e48ba | 245 | |
emh203 | 0:6b1e6c9e48ba | 246 | |
emh203 | 0:6b1e6c9e48ba | 247 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 248 | /* Write a byte to an ATA register */ |
emh203 | 0:6b1e6c9e48ba | 249 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 250 | |
emh203 | 0:6b1e6c9e48ba | 251 | static |
emh203 | 0:6b1e6c9e48ba | 252 | void write_ata ( |
emh203 | 0:6b1e6c9e48ba | 253 | BYTE reg, /* Register to be written */ |
emh203 | 0:6b1e6c9e48ba | 254 | BYTE dat /* Data to be written */ |
emh203 | 0:6b1e6c9e48ba | 255 | ) |
emh203 | 0:6b1e6c9e48ba | 256 | { |
emh203 | 0:6b1e6c9e48ba | 257 | DWORD i; |
emh203 | 0:6b1e6c9e48ba | 258 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 259 | CS0_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 260 | SET_DATA_BUS_AS_OUTPUTS; |
emh203 | 0:6b1e6c9e48ba | 261 | SET_CF_ADDRESS(reg); |
emh203 | 0:6b1e6c9e48ba | 262 | SET_CF_DATA(dat); |
emh203 | 0:6b1e6c9e48ba | 263 | IOWR_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 264 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 265 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 266 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 267 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 268 | IOWR_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 269 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 270 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 271 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 272 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 273 | CS0_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 274 | SET_DATA_BUS_AS_INPUTS; |
emh203 | 0:6b1e6c9e48ba | 275 | } |
emh203 | 0:6b1e6c9e48ba | 276 | |
emh203 | 0:6b1e6c9e48ba | 277 | |
emh203 | 0:6b1e6c9e48ba | 278 | |
emh203 | 0:6b1e6c9e48ba | 279 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 280 | /* Read a part of data block */ |
emh203 | 0:6b1e6c9e48ba | 281 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 282 | |
emh203 | 0:6b1e6c9e48ba | 283 | static |
emh203 | 0:6b1e6c9e48ba | 284 | void read_part ( |
emh203 | 0:6b1e6c9e48ba | 285 | BYTE *buff, /* Data buffer to store read data */ |
emh203 | 0:6b1e6c9e48ba | 286 | BYTE ofs, /* Offset of the part of data in unit of word */ |
emh203 | 0:6b1e6c9e48ba | 287 | BYTE count /* Number of word to pick up */ |
emh203 | 0:6b1e6c9e48ba | 288 | ) |
emh203 | 0:6b1e6c9e48ba | 289 | { |
emh203 | 0:6b1e6c9e48ba | 290 | BYTE c = 0, dl, dh; |
emh203 | 0:6b1e6c9e48ba | 291 | DWORD i; |
emh203 | 0:6b1e6c9e48ba | 292 | |
emh203 | 0:6b1e6c9e48ba | 293 | SET_CF_ADDRESS(REG_DATA); /* Select Data register */ |
emh203 | 0:6b1e6c9e48ba | 294 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 295 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 296 | |
emh203 | 0:6b1e6c9e48ba | 297 | SET_DATA_BUS_AS_INPUTS; |
emh203 | 0:6b1e6c9e48ba | 298 | CS0_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 299 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 300 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 301 | do { |
emh203 | 0:6b1e6c9e48ba | 302 | IORD_ACTIVE; /* IORD = L */ |
emh203 | 0:6b1e6c9e48ba | 303 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 304 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 305 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 306 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 307 | GET_CF_DATA(dl); /* Read Even data */ |
emh203 | 0:6b1e6c9e48ba | 308 | IORD_INACTIVE; /* IORD = H */ |
emh203 | 0:6b1e6c9e48ba | 309 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 310 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 311 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 312 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 313 | IORD_ACTIVE; /* IORD = L */ |
emh203 | 0:6b1e6c9e48ba | 314 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 315 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 316 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 317 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 318 | GET_CF_DATA(dh); /* Read Odd data */ |
emh203 | 0:6b1e6c9e48ba | 319 | IORD_INACTIVE; /* IORD = H */ |
emh203 | 0:6b1e6c9e48ba | 320 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 321 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 322 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 323 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 324 | if (count && (c >= ofs)) { /* Pick up a part of block */ |
emh203 | 0:6b1e6c9e48ba | 325 | *buff++ = dl; |
emh203 | 0:6b1e6c9e48ba | 326 | *buff++ = dh; |
emh203 | 0:6b1e6c9e48ba | 327 | count--; |
emh203 | 0:6b1e6c9e48ba | 328 | } |
emh203 | 0:6b1e6c9e48ba | 329 | } while (++c); |
emh203 | 0:6b1e6c9e48ba | 330 | CS0_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 331 | |
emh203 | 0:6b1e6c9e48ba | 332 | read_ata(REG_ALTSTAT); |
emh203 | 0:6b1e6c9e48ba | 333 | read_ata(REG_STATUS); |
emh203 | 0:6b1e6c9e48ba | 334 | } |
emh203 | 0:6b1e6c9e48ba | 335 | |
emh203 | 0:6b1e6c9e48ba | 336 | |
emh203 | 0:6b1e6c9e48ba | 337 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 338 | /* Wait for Data Ready */ |
emh203 | 0:6b1e6c9e48ba | 339 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 340 | |
emh203 | 0:6b1e6c9e48ba | 341 | static |
emh203 | 0:6b1e6c9e48ba | 342 | int wait_data (void) |
emh203 | 0:6b1e6c9e48ba | 343 | { |
emh203 | 0:6b1e6c9e48ba | 344 | BYTE s; |
emh203 | 0:6b1e6c9e48ba | 345 | |
emh203 | 0:6b1e6c9e48ba | 346 | DiskProcTimer = 100; /* Time out = 1 sec */ |
emh203 | 0:6b1e6c9e48ba | 347 | do { |
emh203 | 0:6b1e6c9e48ba | 348 | if (!DiskProcTimer) return 0; /* Abort when timeout occured */ |
emh203 | 0:6b1e6c9e48ba | 349 | s = read_ata(REG_STATUS); /* Get status */ |
emh203 | 0:6b1e6c9e48ba | 350 | } while ((s & (BUSY|DRQ)) != DRQ); /* Wait for BUSY goes low and DRQ goes high */ |
emh203 | 0:6b1e6c9e48ba | 351 | |
emh203 | 0:6b1e6c9e48ba | 352 | read_ata(REG_ALTSTAT); |
emh203 | 0:6b1e6c9e48ba | 353 | return 1; |
emh203 | 0:6b1e6c9e48ba | 354 | } |
emh203 | 0:6b1e6c9e48ba | 355 | |
emh203 | 0:6b1e6c9e48ba | 356 | |
emh203 | 0:6b1e6c9e48ba | 357 | |
emh203 | 0:6b1e6c9e48ba | 358 | |
emh203 | 0:6b1e6c9e48ba | 359 | |
emh203 | 0:6b1e6c9e48ba | 360 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 361 | /* Initialize Disk Drive */ |
emh203 | 0:6b1e6c9e48ba | 362 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 363 | |
emh203 | 0:6b1e6c9e48ba | 364 | DSTATUS disk_initialize ( |
emh203 | 0:6b1e6c9e48ba | 365 | BYTE drv /* Physical drive nmuber (0) */ |
emh203 | 0:6b1e6c9e48ba | 366 | ) |
emh203 | 0:6b1e6c9e48ba | 367 | { |
emh203 | 0:6b1e6c9e48ba | 368 | if (drv) return STA_NOINIT; /* Supports only single drive */ |
emh203 | 0:6b1e6c9e48ba | 369 | |
emh203 | 0:6b1e6c9e48ba | 370 | Stat |= STA_NOINIT; |
emh203 | 0:6b1e6c9e48ba | 371 | |
emh203 | 0:6b1e6c9e48ba | 372 | for (DiskProcTimer = 10; DiskProcTimer; ); /* 100ms */ |
emh203 | 0:6b1e6c9e48ba | 373 | |
emh203 | 0:6b1e6c9e48ba | 374 | if (Stat & STA_NODISK) return Stat; /* Exit when socket is empty */ |
emh203 | 0:6b1e6c9e48ba | 375 | |
emh203 | 0:6b1e6c9e48ba | 376 | /* Initialize CFC control port */ |
emh203 | 0:6b1e6c9e48ba | 377 | COMPACT_FLASH_POWER_ENABLE; |
emh203 | 0:6b1e6c9e48ba | 378 | |
emh203 | 0:6b1e6c9e48ba | 379 | for (DiskProcTimer = 1;DiskProcTimer; ); /* 10ms */ |
emh203 | 0:6b1e6c9e48ba | 380 | |
emh203 | 0:6b1e6c9e48ba | 381 | SET_DATA_BUS_AS_INPUTS; |
emh203 | 0:6b1e6c9e48ba | 382 | for (DiskProcTimer = 5; DiskProcTimer; ); /* 50ms */ |
emh203 | 0:6b1e6c9e48ba | 383 | COMPACT_FLASH_RESET_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 384 | for (DiskProcTimer = 5; DiskProcTimer; ); /* 50ms */ |
emh203 | 0:6b1e6c9e48ba | 385 | write_ata(REG_DEV, LBA); /* Select Device 0 */ |
emh203 | 0:6b1e6c9e48ba | 386 | DiskProcTimer = 200; |
emh203 | 0:6b1e6c9e48ba | 387 | do { /* Wait for card goes ready */ |
emh203 | 0:6b1e6c9e48ba | 388 | if (!DiskProcTimer) |
emh203 | 0:6b1e6c9e48ba | 389 | { |
emh203 | 0:6b1e6c9e48ba | 390 | CF_DEBUG("Timeout waiting for card BUSY to go inactive\r\n"); |
emh203 | 0:6b1e6c9e48ba | 391 | return Stat; |
emh203 | 0:6b1e6c9e48ba | 392 | } |
emh203 | 0:6b1e6c9e48ba | 393 | } while (read_ata(REG_STATUS) & BUSY); |
emh203 | 0:6b1e6c9e48ba | 394 | |
emh203 | 0:6b1e6c9e48ba | 395 | write_ata(REG_DEVCTRL, SRST | nIEN); /* Software reset */ |
emh203 | 0:6b1e6c9e48ba | 396 | for (DiskProcTimer = 2; DiskProcTimer; ); /* 20ms */ |
emh203 | 0:6b1e6c9e48ba | 397 | write_ata(REG_DEVCTRL, nIEN); /* Release software reset */ |
emh203 | 0:6b1e6c9e48ba | 398 | for (DiskProcTimer = 2; DiskProcTimer; ); /* 20ms */ |
emh203 | 0:6b1e6c9e48ba | 399 | DiskProcTimer = 200; |
emh203 | 0:6b1e6c9e48ba | 400 | do { /* Wait for card goes ready */ |
emh203 | 0:6b1e6c9e48ba | 401 | if (!DiskProcTimer) |
emh203 | 0:6b1e6c9e48ba | 402 | { |
emh203 | 0:6b1e6c9e48ba | 403 | CF_DEBUG("Timeout waiting for card DRDY\r\n"); |
emh203 | 0:6b1e6c9e48ba | 404 | return Stat; |
emh203 | 0:6b1e6c9e48ba | 405 | } |
emh203 | 0:6b1e6c9e48ba | 406 | } while ((read_ata(REG_STATUS) & (DRDY|BUSY)) != DRDY); |
emh203 | 0:6b1e6c9e48ba | 407 | |
emh203 | 0:6b1e6c9e48ba | 408 | |
emh203 | 0:6b1e6c9e48ba | 409 | |
emh203 | 0:6b1e6c9e48ba | 410 | |
emh203 | 0:6b1e6c9e48ba | 411 | CF_DEBUG("Setting to 8-bit PIO MOD\r\n"); |
emh203 | 0:6b1e6c9e48ba | 412 | write_ata(REG_FEATURES, 0x01); /* Select 8-bit PIO transfer mode */ |
emh203 | 0:6b1e6c9e48ba | 413 | write_ata(REG_COMMAND, CMD_SETFEATURES); |
emh203 | 0:6b1e6c9e48ba | 414 | DiskProcTimer = 100; |
emh203 | 0:6b1e6c9e48ba | 415 | do { |
emh203 | 0:6b1e6c9e48ba | 416 | wait(.25); |
emh203 | 0:6b1e6c9e48ba | 417 | if (!DiskProcTimer) |
emh203 | 0:6b1e6c9e48ba | 418 | { |
emh203 | 0:6b1e6c9e48ba | 419 | CF_DEBUG("Timeout waiting after trying to call the SETFEATURES command\r\n"); |
emh203 | 0:6b1e6c9e48ba | 420 | return Stat; |
emh203 | 0:6b1e6c9e48ba | 421 | } |
emh203 | 0:6b1e6c9e48ba | 422 | |
emh203 | 0:6b1e6c9e48ba | 423 | } while (read_ata(REG_STATUS) & (BUSY | ERR)); |
emh203 | 0:6b1e6c9e48ba | 424 | |
emh203 | 0:6b1e6c9e48ba | 425 | Stat &= ~STA_NOINIT; /* When device goes ready, clear STA_NOINIT */ |
emh203 | 0:6b1e6c9e48ba | 426 | |
emh203 | 0:6b1e6c9e48ba | 427 | return Stat; |
emh203 | 0:6b1e6c9e48ba | 428 | } |
emh203 | 0:6b1e6c9e48ba | 429 | |
emh203 | 0:6b1e6c9e48ba | 430 | |
emh203 | 0:6b1e6c9e48ba | 431 | |
emh203 | 0:6b1e6c9e48ba | 432 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 433 | /* Return Disk Status */ |
emh203 | 0:6b1e6c9e48ba | 434 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 435 | |
emh203 | 0:6b1e6c9e48ba | 436 | DSTATUS disk_status ( |
emh203 | 0:6b1e6c9e48ba | 437 | BYTE drv /* Physical drive nmuber (0) */ |
emh203 | 0:6b1e6c9e48ba | 438 | ) |
emh203 | 0:6b1e6c9e48ba | 439 | { |
emh203 | 0:6b1e6c9e48ba | 440 | if (drv) return STA_NOINIT; /* Supports only single drive */ |
emh203 | 0:6b1e6c9e48ba | 441 | return Stat; |
emh203 | 0:6b1e6c9e48ba | 442 | } |
emh203 | 0:6b1e6c9e48ba | 443 | |
emh203 | 0:6b1e6c9e48ba | 444 | |
emh203 | 0:6b1e6c9e48ba | 445 | |
emh203 | 0:6b1e6c9e48ba | 446 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 447 | /* Read Sector(s) */ |
emh203 | 0:6b1e6c9e48ba | 448 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 449 | |
emh203 | 0:6b1e6c9e48ba | 450 | DRESULT disk_read ( |
emh203 | 0:6b1e6c9e48ba | 451 | BYTE drv, /* Physical drive nmuber (0) */ |
emh203 | 0:6b1e6c9e48ba | 452 | BYTE *buff, /* Data buffer to store read data */ |
emh203 | 0:6b1e6c9e48ba | 453 | DWORD sector, /* Sector number (LBA) */ |
emh203 | 0:6b1e6c9e48ba | 454 | BYTE count /* Sector count (1..255) */ |
emh203 | 0:6b1e6c9e48ba | 455 | ) |
emh203 | 0:6b1e6c9e48ba | 456 | { |
emh203 | 0:6b1e6c9e48ba | 457 | BYTE c; |
emh203 | 0:6b1e6c9e48ba | 458 | DWORD i; |
emh203 | 0:6b1e6c9e48ba | 459 | |
emh203 | 0:6b1e6c9e48ba | 460 | |
emh203 | 0:6b1e6c9e48ba | 461 | if (drv || !count) return RES_PARERR; |
emh203 | 0:6b1e6c9e48ba | 462 | if (Stat & STA_NOINIT) return RES_NOTRDY; |
emh203 | 0:6b1e6c9e48ba | 463 | |
emh203 | 0:6b1e6c9e48ba | 464 | /* Issue Read Setor(s) command */ |
emh203 | 0:6b1e6c9e48ba | 465 | write_ata(REG_COUNT, count); |
emh203 | 0:6b1e6c9e48ba | 466 | write_ata(REG_SECTOR, (BYTE)sector); |
emh203 | 0:6b1e6c9e48ba | 467 | write_ata(REG_CYLL, (BYTE)(sector >> 8)); |
emh203 | 0:6b1e6c9e48ba | 468 | write_ata(REG_CYLH, (BYTE)(sector >> 16)); |
emh203 | 0:6b1e6c9e48ba | 469 | write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA); |
emh203 | 0:6b1e6c9e48ba | 470 | write_ata(REG_COMMAND, CMD_READ); |
emh203 | 0:6b1e6c9e48ba | 471 | |
emh203 | 0:6b1e6c9e48ba | 472 | |
emh203 | 0:6b1e6c9e48ba | 473 | do { |
emh203 | 0:6b1e6c9e48ba | 474 | if (!wait_data()) return RES_ERROR; /* Wait data ready */ |
emh203 | 0:6b1e6c9e48ba | 475 | |
emh203 | 0:6b1e6c9e48ba | 476 | |
emh203 | 0:6b1e6c9e48ba | 477 | SET_CF_ADDRESS(REG_DATA); |
emh203 | 0:6b1e6c9e48ba | 478 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 479 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 480 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 481 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 482 | CS0_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 483 | c = 0; |
emh203 | 0:6b1e6c9e48ba | 484 | |
emh203 | 0:6b1e6c9e48ba | 485 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 486 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 487 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 488 | |
emh203 | 0:6b1e6c9e48ba | 489 | SET_DATA_BUS_AS_INPUTS; |
emh203 | 0:6b1e6c9e48ba | 490 | do { |
emh203 | 0:6b1e6c9e48ba | 491 | IORD_ACTIVE; /* IORD = L */ |
emh203 | 0:6b1e6c9e48ba | 492 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 493 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 494 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 495 | GET_CF_DATA(*buff++); /* Get even data */ |
emh203 | 0:6b1e6c9e48ba | 496 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 497 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 498 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 499 | |
emh203 | 0:6b1e6c9e48ba | 500 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 501 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 502 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 503 | |
emh203 | 0:6b1e6c9e48ba | 504 | IORD_INACTIVE; /* IORD = H */ |
emh203 | 0:6b1e6c9e48ba | 505 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 506 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 507 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 508 | |
emh203 | 0:6b1e6c9e48ba | 509 | IORD_ACTIVE; /* IORD = L */ |
emh203 | 0:6b1e6c9e48ba | 510 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 511 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 512 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 513 | |
emh203 | 0:6b1e6c9e48ba | 514 | GET_CF_DATA(*buff++); /* Get Odd data */ |
emh203 | 0:6b1e6c9e48ba | 515 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 516 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 517 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 518 | |
emh203 | 0:6b1e6c9e48ba | 519 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 520 | IORD_INACTIVE; /* IORD = H */ |
emh203 | 0:6b1e6c9e48ba | 521 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 522 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 523 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 524 | |
emh203 | 0:6b1e6c9e48ba | 525 | |
emh203 | 0:6b1e6c9e48ba | 526 | } while (--c); |
emh203 | 0:6b1e6c9e48ba | 527 | } while (--count); |
emh203 | 0:6b1e6c9e48ba | 528 | |
emh203 | 0:6b1e6c9e48ba | 529 | CS0_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 530 | read_ata(REG_ALTSTAT); |
emh203 | 0:6b1e6c9e48ba | 531 | read_ata(REG_STATUS); |
emh203 | 0:6b1e6c9e48ba | 532 | |
emh203 | 0:6b1e6c9e48ba | 533 | |
emh203 | 0:6b1e6c9e48ba | 534 | return RES_OK; |
emh203 | 0:6b1e6c9e48ba | 535 | } |
emh203 | 0:6b1e6c9e48ba | 536 | |
emh203 | 0:6b1e6c9e48ba | 537 | |
emh203 | 0:6b1e6c9e48ba | 538 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 539 | /* Write Sector(s) */ |
emh203 | 0:6b1e6c9e48ba | 540 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 541 | |
emh203 | 0:6b1e6c9e48ba | 542 | DRESULT disk_write ( |
emh203 | 0:6b1e6c9e48ba | 543 | BYTE drv, /* Physical drive number (0) */ |
emh203 | 0:6b1e6c9e48ba | 544 | const BYTE *buff, /* Data to be written */ |
emh203 | 0:6b1e6c9e48ba | 545 | DWORD sector, /* Sector number (LBA) */ |
emh203 | 0:6b1e6c9e48ba | 546 | BYTE count /* Sector count (1..255) */ |
emh203 | 0:6b1e6c9e48ba | 547 | ) |
emh203 | 0:6b1e6c9e48ba | 548 | { |
emh203 | 0:6b1e6c9e48ba | 549 | BYTE s, c; |
emh203 | 0:6b1e6c9e48ba | 550 | DWORD i; |
emh203 | 0:6b1e6c9e48ba | 551 | |
emh203 | 0:6b1e6c9e48ba | 552 | if (drv || !count) return RES_PARERR; |
emh203 | 0:6b1e6c9e48ba | 553 | if (Stat & STA_NOINIT) return RES_NOTRDY; |
emh203 | 0:6b1e6c9e48ba | 554 | |
emh203 | 0:6b1e6c9e48ba | 555 | /* Issue Write Setor(s) command */ |
emh203 | 0:6b1e6c9e48ba | 556 | write_ata(REG_COUNT, count); |
emh203 | 0:6b1e6c9e48ba | 557 | write_ata(REG_SECTOR, (BYTE)sector); |
emh203 | 0:6b1e6c9e48ba | 558 | write_ata(REG_CYLL, (BYTE)(sector >> 8)); |
emh203 | 0:6b1e6c9e48ba | 559 | write_ata(REG_CYLH, (BYTE)(sector >> 16)); |
emh203 | 0:6b1e6c9e48ba | 560 | write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA); |
emh203 | 0:6b1e6c9e48ba | 561 | write_ata(REG_COMMAND, CMD_WRITE); |
emh203 | 0:6b1e6c9e48ba | 562 | |
emh203 | 0:6b1e6c9e48ba | 563 | |
emh203 | 0:6b1e6c9e48ba | 564 | |
emh203 | 0:6b1e6c9e48ba | 565 | do { |
emh203 | 0:6b1e6c9e48ba | 566 | if (!wait_data()) return RES_ERROR; |
emh203 | 0:6b1e6c9e48ba | 567 | |
emh203 | 0:6b1e6c9e48ba | 568 | SET_CF_ADDRESS(REG_DATA); |
emh203 | 0:6b1e6c9e48ba | 569 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 570 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 571 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 572 | CS0_ACTIVE; |
emh203 | 0:6b1e6c9e48ba | 573 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 574 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 575 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 576 | |
emh203 | 0:6b1e6c9e48ba | 577 | SET_DATA_BUS_AS_OUTPUTS; |
emh203 | 0:6b1e6c9e48ba | 578 | c = 0; |
emh203 | 0:6b1e6c9e48ba | 579 | do { |
emh203 | 0:6b1e6c9e48ba | 580 | SET_CF_DATA(*buff++); /* Set even data */ |
emh203 | 0:6b1e6c9e48ba | 581 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 582 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 583 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 584 | |
emh203 | 0:6b1e6c9e48ba | 585 | IOWR_ACTIVE; /* IOWR = L */ |
emh203 | 0:6b1e6c9e48ba | 586 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 587 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 588 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 589 | |
emh203 | 0:6b1e6c9e48ba | 590 | IOWR_INACTIVE; /* IOWR = H */ |
emh203 | 0:6b1e6c9e48ba | 591 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 592 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 593 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 594 | |
emh203 | 0:6b1e6c9e48ba | 595 | SET_CF_DATA(*buff++); /* Set odd data */ |
emh203 | 0:6b1e6c9e48ba | 596 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 597 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 598 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 599 | |
emh203 | 0:6b1e6c9e48ba | 600 | IOWR_ACTIVE; /* IOWR = L */ |
emh203 | 0:6b1e6c9e48ba | 601 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 602 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 603 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 604 | |
emh203 | 0:6b1e6c9e48ba | 605 | IOWR_INACTIVE; /* IOWR = H */ |
emh203 | 0:6b1e6c9e48ba | 606 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 607 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 608 | __nop(); |
emh203 | 0:6b1e6c9e48ba | 609 | |
emh203 | 0:6b1e6c9e48ba | 610 | } while (--c); |
emh203 | 0:6b1e6c9e48ba | 611 | |
emh203 | 0:6b1e6c9e48ba | 612 | } while (--count); |
emh203 | 0:6b1e6c9e48ba | 613 | SET_DATA_BUS_AS_INPUTS; |
emh203 | 0:6b1e6c9e48ba | 614 | CS0_INACTIVE; |
emh203 | 0:6b1e6c9e48ba | 615 | |
emh203 | 0:6b1e6c9e48ba | 616 | DiskProcTimer = 100; |
emh203 | 0:6b1e6c9e48ba | 617 | do { |
emh203 | 0:6b1e6c9e48ba | 618 | if (!DiskProcTimer) return RES_ERROR; |
emh203 | 0:6b1e6c9e48ba | 619 | s = read_ata(REG_STATUS); |
emh203 | 0:6b1e6c9e48ba | 620 | } while (s & BUSY); |
emh203 | 0:6b1e6c9e48ba | 621 | if (s & ERR) return RES_ERROR; |
emh203 | 0:6b1e6c9e48ba | 622 | |
emh203 | 0:6b1e6c9e48ba | 623 | read_ata(REG_ALTSTAT); |
emh203 | 0:6b1e6c9e48ba | 624 | read_ata(REG_STATUS); |
emh203 | 0:6b1e6c9e48ba | 625 | |
emh203 | 0:6b1e6c9e48ba | 626 | return RES_OK; |
emh203 | 0:6b1e6c9e48ba | 627 | } |
emh203 | 0:6b1e6c9e48ba | 628 | |
emh203 | 0:6b1e6c9e48ba | 629 | |
emh203 | 0:6b1e6c9e48ba | 630 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 631 | /* Miscellaneous Functions */ |
emh203 | 0:6b1e6c9e48ba | 632 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 633 | |
emh203 | 0:6b1e6c9e48ba | 634 | DRESULT disk_ioctl ( |
emh203 | 0:6b1e6c9e48ba | 635 | BYTE drv, /* Physical drive nmuber (0) */ |
emh203 | 0:6b1e6c9e48ba | 636 | BYTE ctrl, /* Control code */ |
emh203 | 0:6b1e6c9e48ba | 637 | void *buff /* Buffer to send/receive data block */ |
emh203 | 0:6b1e6c9e48ba | 638 | ) |
emh203 | 0:6b1e6c9e48ba | 639 | { |
emh203 | 0:6b1e6c9e48ba | 640 | BYTE n, w, ofs, dl, dh, *ptr = (BYTE *)buff; |
emh203 | 0:6b1e6c9e48ba | 641 | |
emh203 | 0:6b1e6c9e48ba | 642 | |
emh203 | 0:6b1e6c9e48ba | 643 | if (drv) return RES_PARERR; |
emh203 | 0:6b1e6c9e48ba | 644 | if (Stat & STA_NOINIT) return RES_NOTRDY; |
emh203 | 0:6b1e6c9e48ba | 645 | |
emh203 | 0:6b1e6c9e48ba | 646 | switch (ctrl) { |
emh203 | 0:6b1e6c9e48ba | 647 | case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ |
emh203 | 0:6b1e6c9e48ba | 648 | ofs = 60; w = 2; n = 0; |
emh203 | 0:6b1e6c9e48ba | 649 | break; |
emh203 | 0:6b1e6c9e48ba | 650 | |
emh203 | 0:6b1e6c9e48ba | 651 | case GET_BLOCK_SIZE : /* Get erase block size in sectors (DWORD) */ |
emh203 | 0:6b1e6c9e48ba | 652 | *(DWORD*)buff = 32; |
emh203 | 0:6b1e6c9e48ba | 653 | return RES_OK; |
emh203 | 0:6b1e6c9e48ba | 654 | |
emh203 | 0:6b1e6c9e48ba | 655 | case CTRL_SYNC : /* Nothing to do */ |
emh203 | 0:6b1e6c9e48ba | 656 | return RES_OK; |
emh203 | 0:6b1e6c9e48ba | 657 | |
emh203 | 0:6b1e6c9e48ba | 658 | case ATA_GET_REV : /* Get firmware revision (8 chars) */ |
emh203 | 0:6b1e6c9e48ba | 659 | ofs = 23; w = 4; n = 4; |
emh203 | 0:6b1e6c9e48ba | 660 | break; |
emh203 | 0:6b1e6c9e48ba | 661 | |
emh203 | 0:6b1e6c9e48ba | 662 | case ATA_GET_MODEL : /* Get model name (40 chars) */ |
emh203 | 0:6b1e6c9e48ba | 663 | ofs = 27; w = 20; n = 20; |
emh203 | 0:6b1e6c9e48ba | 664 | break; |
emh203 | 0:6b1e6c9e48ba | 665 | |
emh203 | 0:6b1e6c9e48ba | 666 | case ATA_GET_SN : /* Get serial number (20 chars) */ |
emh203 | 0:6b1e6c9e48ba | 667 | ofs = 10; w = 10; n = 10; |
emh203 | 0:6b1e6c9e48ba | 668 | break; |
emh203 | 0:6b1e6c9e48ba | 669 | |
emh203 | 0:6b1e6c9e48ba | 670 | default: |
emh203 | 0:6b1e6c9e48ba | 671 | return RES_PARERR; |
emh203 | 0:6b1e6c9e48ba | 672 | } |
emh203 | 0:6b1e6c9e48ba | 673 | |
emh203 | 0:6b1e6c9e48ba | 674 | write_ata(REG_COMMAND, CMD_IDENTIFY); |
emh203 | 0:6b1e6c9e48ba | 675 | if (!wait_data()) return RES_ERROR; |
emh203 | 0:6b1e6c9e48ba | 676 | read_part(ptr, ofs, w); |
emh203 | 0:6b1e6c9e48ba | 677 | while (n--) { |
emh203 | 0:6b1e6c9e48ba | 678 | dl = *ptr; dh = *(ptr+1); |
emh203 | 0:6b1e6c9e48ba | 679 | *ptr++ = dh; *ptr++ = dl; |
emh203 | 0:6b1e6c9e48ba | 680 | } |
emh203 | 0:6b1e6c9e48ba | 681 | |
emh203 | 0:6b1e6c9e48ba | 682 | return RES_OK; |
emh203 | 0:6b1e6c9e48ba | 683 | } |
emh203 | 0:6b1e6c9e48ba | 684 | |
emh203 | 0:6b1e6c9e48ba | 685 | |
emh203 | 0:6b1e6c9e48ba | 686 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 687 | /* Device timer interrupt procedure */ |
emh203 | 0:6b1e6c9e48ba | 688 | /*-----------------------------------------------------------------------*/ |
emh203 | 0:6b1e6c9e48ba | 689 | /* This function must be called in period of 10ms */ |
emh203 | 0:6b1e6c9e48ba | 690 | |
emh203 | 0:6b1e6c9e48ba | 691 | void disk_timerproc (void) |
emh203 | 0:6b1e6c9e48ba | 692 | { |
emh203 | 0:6b1e6c9e48ba | 693 | static BYTE pv; |
emh203 | 0:6b1e6c9e48ba | 694 | BYTE n; |
emh203 | 0:6b1e6c9e48ba | 695 | |
emh203 | 0:6b1e6c9e48ba | 696 | LED2_TOGGLE; |
emh203 | 0:6b1e6c9e48ba | 697 | |
emh203 | 0:6b1e6c9e48ba | 698 | n = DiskProcTimer; /* 100Hz decrement timer */ |
emh203 | 0:6b1e6c9e48ba | 699 | if (n) DiskProcTimer = --n; |
emh203 | 0:6b1e6c9e48ba | 700 | |
emh203 | 0:6b1e6c9e48ba | 701 | n = pv; |
emh203 | 0:6b1e6c9e48ba | 702 | pv = COMPACT_FLASH_CARD_DETECTED ; /* Sapmle socket switch */ |
emh203 | 0:6b1e6c9e48ba | 703 | |
emh203 | 0:6b1e6c9e48ba | 704 | if (n == pv) { /* Have contacts stabled? */ |
emh203 | 0:6b1e6c9e48ba | 705 | if (!COMPACT_FLASH_CARD_DETECTED ) |
emh203 | 0:6b1e6c9e48ba | 706 | { /* CD1 or CD2 is high (Socket empty) */ |
emh203 | 0:6b1e6c9e48ba | 707 | Stat |= (STA_NODISK | STA_NOINIT); |
emh203 | 0:6b1e6c9e48ba | 708 | SET_DATA_BUS_TO_INPUTS; /* Float D0-D7 */ |
emh203 | 0:6b1e6c9e48ba | 709 | COMPACT_FLASH_RESET_ACTIVE; /* Assert RESET# */ |
emh203 | 0:6b1e6c9e48ba | 710 | COMPACT_FLASH_POWER_DISABLE; /* Power OFF */ |
emh203 | 0:6b1e6c9e48ba | 711 | LED1_OFF; |
emh203 | 0:6b1e6c9e48ba | 712 | |
emh203 | 0:6b1e6c9e48ba | 713 | } else { /* CD1 and CD2 are low (Card inserted) */ |
emh203 | 0:6b1e6c9e48ba | 714 | Stat &= ~STA_NODISK; |
emh203 | 0:6b1e6c9e48ba | 715 | LED1_ON; |
emh203 | 0:6b1e6c9e48ba | 716 | } |
emh203 | 0:6b1e6c9e48ba | 717 | } |
emh203 | 0:6b1e6c9e48ba | 718 | } |
emh203 | 0:6b1e6c9e48ba | 719 | |
emh203 | 0:6b1e6c9e48ba | 720 | |
emh203 | 0:6b1e6c9e48ba | 721 | DWORD get_fattime(void) |
emh203 | 0:6b1e6c9e48ba | 722 | { |
emh203 | 0:6b1e6c9e48ba | 723 | time_t CurrentTimeStamp; |
emh203 | 0:6b1e6c9e48ba | 724 | tm *CurrentLocalTime; |
emh203 | 0:6b1e6c9e48ba | 725 | DWORD FATFSTimeCode; |
emh203 | 0:6b1e6c9e48ba | 726 | |
emh203 | 0:6b1e6c9e48ba | 727 | CurrentTimeStamp = time(NULL); |
emh203 | 0:6b1e6c9e48ba | 728 | CurrentLocalTime = localtime(&CurrentTimeStamp); |
emh203 | 0:6b1e6c9e48ba | 729 | |
emh203 | 0:6b1e6c9e48ba | 730 | //Map the tm struct time into the FatFs time code |
emh203 | 0:6b1e6c9e48ba | 731 | FATFSTimeCode = ((CurrentLocalTime->tm_year-80)<<25) | |
emh203 | 0:6b1e6c9e48ba | 732 | ((CurrentLocalTime->tm_mon+1)<<21) | |
emh203 | 0:6b1e6c9e48ba | 733 | ((CurrentLocalTime->tm_mday)<<16) | |
emh203 | 0:6b1e6c9e48ba | 734 | ((CurrentLocalTime->tm_hour)<<11) | |
emh203 | 0:6b1e6c9e48ba | 735 | ((CurrentLocalTime->tm_min)<<5) | |
emh203 | 0:6b1e6c9e48ba | 736 | ((CurrentLocalTime->tm_sec)); |
emh203 | 0:6b1e6c9e48ba | 737 | |
emh203 | 0:6b1e6c9e48ba | 738 | return FATFSTimeCode; |
emh203 | 0:6b1e6c9e48ba | 739 | } |