hsram1.Init.NSBank = FSMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_ENABLE;
hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_PSRAM;
- hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_8;
+ hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
/* Timing */
- // 1 clock to read the address, but since the signals aren't stable
- // at 96MHz we wait two more clocks
- Timing.AddressSetupTime = 3;
+ // 1 clock to read the address, + 3 for the synchroniser
+ Timing.AddressSetupTime = 4;
Timing.AddressHoldTime = 1;
- Timing.DataSetupTime = 5;
- // +1 clock hold time, +2 clock to let the bus settle (unstable at 96MHz)
- // +1 clock to process read, 1 clock to output
+ // 3 for synchroniser, 1 to skip hold time, 1 to process read, 1 to output
+ Timing.DataSetupTime = 6;
- // Allow a clock for us to release signals, or else we'll read
- // our own output data as an address.
- Timing.BusTurnAroundDuration = 1;
+ // Allow a clock for us to release signals, plus 3 for the synchroniser to
+ // realise the cycle has ended. Need to avoid both devices acting as outputs
+ // on the multiplexed lines at the same time.
+ Timing.BusTurnAroundDuration = 4;
Timing.CLKDivision = 16; // Ignored for async
Timing.DataLatency = 17; // Ignored for async
PE8 ------> FSMC_DA5
PE9 ------> FSMC_DA6
PE10 ------> FSMC_DA7
+ PE11 ------> FSMC_DA8
+ PE12 ------> FSMC_DA9
+ PE13 ------> FSMC_DA10
+ PE14 ------> FSMC_DA11
+ PE15 ------> FSMC_DA12
PD14 ------> FSMC_DA0
PD15 ------> FSMC_DA1
PD0 ------> FSMC_DA2
PD4 ------> FSMC_NOE
PD5 ------> FSMC_NWE
PD7 ------> FSMC_NE1
+ PD8 ------> FSMC_DA13
+ PD9 ------> FSMC_DA14
+ PD10 ------> FSMC_DA15
PB7 ------> FSMC_NL
+ PE0 ------> FSMC_NBL0
+ PE1 ------> FSMC_NBL1
*/
/* GPIO_InitStruct */
- GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
+ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1
- |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7;
+ |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
PE8 ------> FSMC_DA5
PE9 ------> FSMC_DA6
PE10 ------> FSMC_DA7
+ PE11 ------> FSMC_DA8
+ PE12 ------> FSMC_DA9
+ PE13 ------> FSMC_DA10
+ PE14 ------> FSMC_DA11
+ PE15 ------> FSMC_DA12
PD14 ------> FSMC_DA0
PD15 ------> FSMC_DA1
PD0 ------> FSMC_DA2
PD4 ------> FSMC_NOE
PD5 ------> FSMC_NWE
PD7 ------> FSMC_NE1
+ PD8 ------> FSMC_DA13
+ PD9 ------> FSMC_DA14
+ PD10 ------> FSMC_DA15
PB7 ------> FSMC_NL
+ PE0 ------> FSMC_NBL0
+ PE1 ------> FSMC_NBL1
*/
- HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);
+ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1
- |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7);
+ |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
dmaBytes = bytesPerSector % SD_SECTOR_SIZE;\r
if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;\r
}\r
- for (int k = 0; k < dmaBytes; ++k)\r
+\r
+ uint16_t* scsiDmaData = (uint16_t*) &(scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);\r
+ for (int k = 0; k < (dmaBytes + 1) / 2; ++k)\r
{\r
- scsiPhyTx(scsiDev.data[SD_SECTOR_SIZE * (i % buffers) + k]);\r
+ scsiPhyTx(scsiDmaData[k]);\r
}\r
i++;\r
while (!scsiPhyComplete() && !scsiDev.resetFlag) {}\r
scsiPhyFifoFlip();\r
+ scsiSetDataCount(dmaBytes);\r
}\r
#endif\r
}\r
}\r
}\r
\r
-static void\r
-startScsiRx(uint32_t count)\r
+void\r
+scsiSetDataCount(uint32_t count)\r
{\r
*SCSI_DATA_CNT_HI = count >> 8;\r
*SCSI_DATA_CNT_LO = count & 0xff;\r
assertFail();\r
}\r
#endif\r
- startScsiRx(1);\r
+ scsiSetDataCount(1);\r
\r
trace(trace_spinPhyRxFifo);\r
while (!scsiPhyComplete() && likely(!scsiDev.resetFlag)) {}\r
static void\r
scsiReadPIO(uint8_t* data, uint32_t count)\r
{\r
- for (int i = 0; i < count; ++i)\r
+ uint16_t* fifoData = (uint16_t*)data;\r
+ for (int i = 0; i < (count + 1) / 2; ++i)\r
{\r
- data[i] = scsiPhyRx();\r
+ fifoData[i] = scsiPhyRx(); // TODO ASSUMES LITTLE ENDIAN\r
}\r
// TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();\r
}\r
scsiTxDMAComplete = 1; // TODO not used much\r
scsiRxDMAComplete = 0; // TODO not used much\r
\r
- HAL_DMA_Start(&fsmcToMem, (uint32_t) SCSI_FIFO_DATA, (uint32_t) data, count);\r
+ HAL_DMA_Start(\r
+ &fsmcToMem,\r
+ (uint32_t) SCSI_FIFO_DATA,\r
+ (uint32_t) data,\r
+ (count + 1) / 2);\r
}\r
\r
int\r
chunk = chunk & 0xFFFFFFF8;\r
}\r
#endif\r
- startScsiRx(chunk);\r
+ scsiSetDataCount(chunk);\r
\r
while (i < count && likely(!scsiDev.resetFlag))\r
{\r
#endif\r
if (nextChunk > 0)\r
{\r
- startScsiRx(nextChunk);\r
+ scsiSetDataCount(nextChunk);\r
}\r
\r
#ifdef SCSI_FSMC_DMA\r
scsiPhyTx(value);\r
scsiPhyFifoFlip();\r
\r
+ scsiSetDataCount(1);\r
+\r
trace(trace_spinTxComplete);\r
while (!scsiPhyComplete() && likely(!scsiDev.resetFlag)) {}\r
\r
static void\r
scsiWritePIO(const uint8_t* data, uint32_t count)\r
{\r
- for (int i = 0; i < count; ++i)\r
+ uint16_t* fifoData = (uint16_t*)data;\r
+ for (int i = 0; i < (count + 1) / 2; ++i)\r
{\r
- scsiPhyTx(data[i]);\r
+ scsiPhyTx(fifoData[i]);\r
}\r
}\r
\r
#endif\r
\r
scsiPhyFifoFlip();\r
+ scsiSetDataCount(chunk);\r
i += chunk;\r
}\r
while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
*SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;\r
\r
// DMA Benchmark code\r
- // Currently 6.6MB/s. Assume 13MB/s is achievable with 16 bits\r
+ // Currently 11MB/s.\r
#ifdef DMA_BENCHMARK\r
while(1)\r
{\r
&fsmcToMem,\r
(uint32_t) SCSI_FIFO_DATA,\r
(uint32_t) &scsiDev.data[0],\r
- SCSI_FIFO_DEPTH);\r
+ SCSI_FIFO_DEPTH / 2);\r
\r
HAL_DMA_PollForTransfer(\r
&fsmcToMem,\r
memToFSMC.Init.PeriphInc = DMA_PINC_ENABLE;\r
memToFSMC.Init.MemInc = DMA_MINC_DISABLE;\r
memToFSMC.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;\r
- memToFSMC.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;\r
+ memToFSMC.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;\r
memToFSMC.Init.Mode = DMA_NORMAL;\r
memToFSMC.Init.Priority = DMA_PRIORITY_LOW;\r
// FIFO mode is needed to allow conversion from 32bit words to the\r
- // 8bit FSMC interface.\r
+ // 16bit FSMC interface.\r
memToFSMC.Init.FIFOMode = DMA_FIFOMODE_ENABLE;\r
\r
// We only use 1 word (4 bytes) in the fifo at a time. Normally it's\r
fsmcToMem.Init.Direction = DMA_MEMORY_TO_MEMORY;\r
fsmcToMem.Init.PeriphInc = DMA_PINC_DISABLE;\r
fsmcToMem.Init.MemInc = DMA_MINC_ENABLE;\r
- fsmcToMem.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;\r
+ fsmcToMem.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;\r
fsmcToMem.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;\r
fsmcToMem.Init.Mode = DMA_NORMAL;\r
fsmcToMem.Init.Priority = DMA_PRIORITY_LOW;\r
#define SCSIPHY_H
#define SCSI_CTRL_IDMASK ((volatile uint8_t*)0x60000000)
-#define SCSI_CTRL_PHASE ((volatile uint8_t*)0x60000001)
-#define SCSI_CTRL_BSY ((volatile uint8_t*)0x60000002)
-#define SCSI_FIFO_SEL ((volatile uint8_t*)0x60000003)
-#define SCSI_DATA_CNT_HI ((volatile uint8_t*)0x60000004)
-#define SCSI_DATA_CNT_LO ((volatile uint8_t*)0x60000005)
-#define SCSI_DATA_CNT_SET ((volatile uint8_t*)0x60000006)
-#define SCSI_CTRL_DBX ((volatile uint8_t*)0x60000007)
-#define SCSI_CTRL_SYNC_OFFSET ((volatile uint8_t*)0x60000008)
-#define SCSI_CTRL_TIMING ((volatile uint8_t*)0x60000009)
-#define SCSI_CTRL_TIMING2 ((volatile uint8_t*)0x6000000A)
-
-#define SCSI_STS_FIFO ((volatile uint8_t*)0x60000010)
-#define SCSI_STS_ALTFIFO ((volatile uint8_t*)0x60000011)
-#define SCSI_STS_FIFO_COMPLETE ((volatile uint8_t*)0x60000012)
-#define SCSI_STS_SELECTED ((volatile uint8_t*)0x60000013)
-#define SCSI_STS_SCSI ((volatile uint8_t*)0x60000014)
-#define SCSI_STS_DBX ((volatile uint8_t*)0x60000015)
-
-#define SCSI_FIFO_DATA ((volatile uint8_t*)0x60000020)
+#define SCSI_CTRL_PHASE ((volatile uint8_t*)0x60000002)
+#define SCSI_CTRL_BSY ((volatile uint8_t*)0x60000004)
+#define SCSI_FIFO_SEL ((volatile uint8_t*)0x60000006)
+#define SCSI_DATA_CNT_HI ((volatile uint8_t*)0x60000008)
+#define SCSI_DATA_CNT_LO ((volatile uint8_t*)0x6000000A)
+#define SCSI_DATA_CNT_SET ((volatile uint8_t*)0x6000000C)
+#define SCSI_CTRL_DBX ((volatile uint8_t*)0x6000000E)
+#define SCSI_CTRL_SYNC_OFFSET ((volatile uint8_t*)0x60000010)
+#define SCSI_CTRL_TIMING ((volatile uint8_t*)0x60000012)
+#define SCSI_CTRL_TIMING2 ((volatile uint8_t*)0x60000014)
+
+#define SCSI_STS_FIFO ((volatile uint8_t*)0x60000020)
+#define SCSI_STS_ALTFIFO ((volatile uint8_t*)0x60000022)
+#define SCSI_STS_FIFO_COMPLETE ((volatile uint8_t*)0x60000024)
+#define SCSI_STS_SELECTED ((volatile uint8_t*)0x60000026)
+#define SCSI_STS_SCSI ((volatile uint8_t*)0x60000028)
+#define SCSI_STS_DBX ((volatile uint8_t*)0x6000002A)
+
+#define SCSI_FIFO_DATA ((volatile uint16_t*)0x60000040)
#define SCSI_FIFO_DEPTH 512
void scsiEnterPhase(int phase);
void scsiEnterBusFree(void);
+void scsiSetDataCount(uint32_t count);
+
void scsiWrite(const uint8_t* data, uint32_t count);
void scsiRead(uint8_t* data, uint32_t count);
void scsiWriteByte(uint8_t value);
void sdTmpRead(uint8_t* data, uint32_t lba, int sectors);
void sdTmpWrite(uint8_t* data, uint32_t lba, int sectors);
-#if 0
-
-// Contains the odd-parity flag for a given 8-bit value.
-extern const uint8_t Lookup_OddParity[256];
-
-#endif
extern volatile uint8_t scsiRxDMAComplete;
extern volatile uint8_t scsiTxDMAComplete;