Skip to content

Commit 8ee428b

Browse files
committed
!squash: pbio/drv/block_device: Add EV3 driver.
For now it is modeled after the W25Qxx driver for STM32. This could be a useful starting point.
1 parent a157d7f commit 8ee428b

File tree

1 file changed

+94
-120
lines changed

1 file changed

+94
-120
lines changed

lib/pbio/drv/block_device/block_device_ev3.c

Lines changed: 94 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
#include "../core.h"
1515

1616
#include <pbdrv/block_device.h>
17+
#include <pbdrv/gpio.h>
18+
19+
#include <tiam1808/spi.h>
20+
#include <tiam1808/psc.h>
21+
#include <tiam1808/hw/soc_AM1808.h>
22+
#include <tiam1808/hw/hw_types.h>
23+
#include <tiam1808/hw/hw_syscfg0_AM1808.h>
24+
#include <tiam1808/armv5/am1808/interrupt.h>
25+
26+
#include "../drv/gpio/gpio_ev3.h"
1727

1828
#include <pbio/error.h>
1929
#include <pbio/int_math.h>
@@ -58,75 +68,65 @@ typedef struct {
5868
* The block device driver state.
5969
*/
6070
static struct {
61-
/** Platform-specific data */
62-
const pbdrv_block_device_ev3_platform_data_t *pdata;
63-
/** HAL SPI data */
64-
SPI_HandleTypeDef hspi;
6571
/** HAL Transfer status */
6672
volatile spi_status_t spi_status;
67-
/** DMA for sending SPI commands and data */
68-
DMA_HandleTypeDef tx_dma;
69-
/** DMA for receiving SPI data */
70-
DMA_HandleTypeDef rx_dma;
73+
//
74+
// Any state variables can go here as needed. We don't need pdata in platform.c
75+
// since this driver is going to only ever be used with EV3
76+
//
7177
} bdev;
7278

73-
/**
74-
* Interrupt handler for SPI IRQ. Called from IRQ handler in platform.c.
75-
*/
76-
void pbdrv_block_device_ev3_spi_handle_tx_dma_irq(void) {
77-
HAL_DMA_IRQHandler(&bdev.tx_dma);
78-
}
79-
80-
/**
81-
* Interrupt handler for SPI IRQ. Called from IRQ handler in platform.c.
82-
*/
83-
void pbdrv_block_device_ev3_spi_handle_rx_dma_irq(void) {
84-
HAL_DMA_IRQHandler(&bdev.rx_dma);
85-
}
86-
87-
/**
88-
* Interrupt handler for SPI IRQ. Called from IRQ handler in platform.c.
89-
*/
90-
void pbdrv_block_device_ev3_spi_irq(void) {
91-
HAL_SPI_IRQHandler(&bdev.hspi);
92-
}
9379

9480
/**
95-
* Tx transfer complete. Called from IRQ handler in platform.c.
81+
* Tx transfer complete. // Leaving this here for inspiration as hook for TI API. Delete if not needed.
9682
*/
9783
void pbdrv_block_device_ev3_spi_tx_complete(void) {
9884
bdev.spi_status = SPI_STATUS_COMPLETE;
9985
pbio_os_request_poll();
10086
}
10187

10288
/**
103-
* Rx transfer complete. Called from IRQ handler in platform.c.
89+
* Rx transfer complete. // Leaving this here for inspiration as hook for TI API. Delete if not needed.
10490
*/
10591
void pbdrv_block_device_ev3_spi_rx_complete(void) {
10692
bdev.spi_status = SPI_STATUS_COMPLETE;
10793
pbio_os_request_poll();
10894
}
10995

11096
/**
111-
* Transfer error. Called from IRQ handler in platform.c.
97+
* Transfer error. // Leaving this here for inspiration as hook for TI API. Delete if not needed.
11298
*/
11399
void pbdrv_block_device_ev3_spi_error(void) {
114100
bdev.spi_status = SPI_STATUS_ERROR;
115101
pbio_os_request_poll();
116102
}
117103

104+
// ADC / Flash SPI0 data MOSI
105+
static const pbdrv_gpio_t pin_spi0_mosi = PBDRV_GPIO_EV3_PIN(3, 15, 12, 8, 5);
106+
107+
// ADC / Flash SPI0 data MISO
108+
static const pbdrv_gpio_t pin_spi0_miso = PBDRV_GPIO_EV3_PIN(3, 11, 8, 8, 6);
109+
110+
// LCD SPI0 Clock
111+
static const pbdrv_gpio_t pin_spi0_clk = PBDRV_GPIO_EV3_PIN(3, 3, 0, 1, 8);
112+
113+
// ADC / Flash SPI0 chip select (active low).
114+
static const pbdrv_gpio_t pin_spi0_ncs3 = PBDRV_GPIO_EV3_PIN(3, 27, 24, 8, 2);
115+
static const pbdrv_gpio_t pin_spi0_ncs0 = PBDRV_GPIO_EV3_PIN(4, 7, 4, 1, 6);
116+
118117
/**
119-
* Sets or clears the chip select line. This is required for various operations
120-
* of the w25qxx
118+
* Sets or clears the chip select line.
119+
*
120+
* // REVISIT: TI API also seems to have ways of having the peripheral do this for us. Whatever works is fine.
121121
*
122122
* @param [in] set Whether to set (true) or clear (false) CS.
123123
*/
124124
static void spi_chip_select(bool set) {
125125
// Active low, so set CS means set /CS low.
126126
if (set) {
127-
pbdrv_gpio_out_low(&bdev.pdata->pin_ncs);
127+
pbdrv_gpio_out_low(&pin_spi0_ncs0);
128128
} else {
129-
pbdrv_gpio_out_high(&bdev.pdata->pin_ncs);
129+
pbdrv_gpio_out_high(&pin_spi0_ncs0);
130130
}
131131
}
132132

@@ -152,25 +152,32 @@ static pbio_error_t spi_begin(const spi_command_t *cmd) {
152152
// Set status to wait and start receiving.
153153
bdev.spi_status = SPI_STATUS_WAIT;
154154

155-
// Start SPI operation.
156-
HAL_StatusTypeDef err;
157-
if (cmd->operation == SPI_RECV) {
158-
err = HAL_SPI_Receive_DMA(&bdev.hspi, cmd->buffer, cmd->size);
159-
} else {
160-
err = HAL_SPI_Transmit_DMA(&bdev.hspi, cmd->buffer, cmd->size);
161-
}
162-
163-
// Handle HAL errors.
164-
switch (err) {
165-
case HAL_OK:
166-
return PBIO_SUCCESS;
167-
case HAL_ERROR:
168-
return PBIO_ERROR_INVALID_ARG;
169-
case HAL_BUSY:
170-
return PBIO_ERROR_BUSY;
171-
default:
172-
return PBIO_ERROR_IO;
173-
}
155+
// REPLACE WITH TI AM1808 SPI DMA operation
156+
//
157+
//
158+
// // Start SPI operation.
159+
// HAL_StatusTypeDef err;
160+
// if (cmd->operation == SPI_RECV) {
161+
// err = HAL_SPI_Receive_DMA(&bdev.hspi, cmd->buffer, cmd->size);
162+
// } else {
163+
// err = HAL_SPI_Transmit_DMA(&bdev.hspi, cmd->buffer, cmd->size);
164+
// }
165+
166+
// // Handle HAL errors.
167+
// switch (err) {
168+
// case HAL_OK:
169+
// return PBIO_SUCCESS;
170+
// case HAL_ERROR:
171+
// return PBIO_ERROR_INVALID_ARG;
172+
// case HAL_BUSY:
173+
// return PBIO_ERROR_BUSY;
174+
// default:
175+
// return PBIO_ERROR_IO;
176+
// }
177+
178+
// REVISIT: DELETE ME. Here for now until we implement a real transfer.
179+
bdev.spi_status = SPI_STATUS_COMPLETE;
180+
return PBIO_SUCCESS;
174181
}
175182

176183
/**
@@ -203,31 +210,27 @@ static pbio_error_t spi_command_thread(pbio_os_state_t *state, const spi_command
203210
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
204211
}
205212

213+
//
214+
// REVISIT: Can delete this, and hardcode for N25Q128
215+
//
206216
// Select constant values based on flash device type.
207-
#if PBDRV_CONFIG_BLOCK_DEVICE_EV3_W25Q32
217+
#if 1
208218
#define W25Qxx(Q32, Q256) (Q32)
209-
#elif PBDRV_CONFIG_BLOCK_DEVICE_EV3_W25Q256
219+
#else
210220
#define W25Qxx(Q32, Q256) (Q256)
211221
#endif
212222

213-
// 3 or 4 byte addressing mode.
214-
#define FLASH_ADDRESS_SIZE (W25Qxx(3, 4))
223+
// 3 byte addressing mode.
224+
#define FLASH_ADDRESS_SIZE (3)
215225

216226
static void set_address_be(uint8_t *buf, uint32_t address) {
217-
#if PBDRV_CONFIG_BLOCK_DEVICE_EV3_W25Q32
218227
buf[0] = address >> 16;
219228
buf[1] = address >> 8;
220229
buf[2] = address;
221-
#else
222-
buf[0] = address >> 24;
223-
buf[1] = address >> 16;
224-
buf[2] = address >> 8;
225-
buf[3] = address;
226-
#endif
227230
}
228231

229232
/**
230-
* Device-specific flash commands.
233+
* Device-specific flash commands. // REVISIT: Hardcode for N25Q128
231234
*/
232235
enum {
233236
FLASH_CMD_GET_STATUS = 0x05,
@@ -239,7 +242,7 @@ enum {
239242
};
240243

241244
/**
242-
* Flash sizes.
245+
* Flash sizes. // REVISIT: for N25Q128
243246
*/
244247
enum {
245248
FLASH_SIZE_ERASE = 4 * 1024, // Limited by W25QXX operation
@@ -248,14 +251,14 @@ enum {
248251
};
249252

250253
/**
251-
* Flash status flags.
254+
* Flash status flags. // REVISIT: for N25Q128
252255
*/
253256
enum {
254257
FLASH_STATUS_BUSY = 0x01,
255258
FLASH_STATUS_WRITE_ENABLED = 0x02,
256259
};
257260

258-
// W25Qxx manufacturer and device ID.
261+
// W25Qxx manufacturer and device ID. // REVISIT: for N25Q128
259262
static const uint8_t device_id[] = {0xEF, 0x40, W25Qxx(0x16, 0x19)};
260263

261264
// Request flash device ID.
@@ -487,10 +490,10 @@ pbio_error_t pbdrv_block_device_ev3_init_process_thread(pbio_os_state_t *state,
487490
return err;
488491
}
489492

490-
// Verify flash device ID
491-
if (memcmp(device_id, id_data, sizeof(id_data))) {
492-
return PBIO_ERROR_FAILED;
493-
}
493+
// Verify flash device ID // REVISIT: Fix up id_data so we can memcmp
494+
// if (memcmp(device_id, id_data, sizeof(id_data))) {
495+
// return PBIO_ERROR_FAILED;
496+
// }
494497

495498
// Initialization done.
496499
pbdrv_init_busy_down();
@@ -500,55 +503,26 @@ pbio_error_t pbdrv_block_device_ev3_init_process_thread(pbio_os_state_t *state,
500503

501504
void pbdrv_block_device_init(void) {
502505

503-
bdev.pdata = &pbdrv_block_device_ev3_platform_data;
504506
bdev.spi_status = SPI_STATUS_COMPLETE;
505507

506-
bdev.tx_dma.Instance = bdev.pdata->tx_dma;
507-
bdev.tx_dma.Init.Channel = bdev.pdata->tx_dma_ch;
508-
bdev.tx_dma.Init.Direction = DMA_MEMORY_TO_PERIPH;
509-
bdev.tx_dma.Init.PeriphInc = DMA_PINC_DISABLE;
510-
bdev.tx_dma.Init.MemInc = DMA_MINC_ENABLE;
511-
bdev.tx_dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
512-
bdev.tx_dma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
513-
bdev.tx_dma.Init.Mode = DMA_NORMAL;
514-
bdev.tx_dma.Init.Priority = DMA_PRIORITY_HIGH;
515-
bdev.tx_dma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
516-
bdev.tx_dma.Init.MemBurst = DMA_MBURST_SINGLE;
517-
bdev.tx_dma.Init.PeriphBurst = DMA_PBURST_SINGLE;
518-
HAL_DMA_Init(&bdev.tx_dma);
519-
HAL_NVIC_SetPriority(bdev.pdata->tx_dma_irq, 5, 0);
520-
HAL_NVIC_EnableIRQ(bdev.pdata->tx_dma_irq);
521-
__HAL_LINKDMA(&bdev.hspi, hdmatx, bdev.tx_dma);
522-
523-
bdev.rx_dma.Instance = bdev.pdata->rx_dma;
524-
bdev.rx_dma.Init.Channel = bdev.pdata->rx_dma_ch;
525-
bdev.rx_dma.Init.Direction = DMA_PERIPH_TO_MEMORY;
526-
bdev.rx_dma.Init.PeriphInc = DMA_PINC_DISABLE;
527-
bdev.rx_dma.Init.MemInc = DMA_MINC_ENABLE;
528-
bdev.rx_dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
529-
bdev.rx_dma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
530-
bdev.rx_dma.Init.Mode = DMA_NORMAL;
531-
bdev.rx_dma.Init.Priority = DMA_PRIORITY_HIGH;
532-
bdev.rx_dma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
533-
bdev.rx_dma.Init.MemBurst = DMA_MBURST_SINGLE;
534-
bdev.rx_dma.Init.PeriphBurst = DMA_PBURST_SINGLE;
535-
HAL_DMA_Init(&bdev.rx_dma);
536-
HAL_NVIC_SetPriority(bdev.pdata->rx_dma_irq, 5, 0);
537-
HAL_NVIC_EnableIRQ(bdev.pdata->rx_dma_irq);
538-
__HAL_LINKDMA(&bdev.hspi, hdmarx, bdev.rx_dma);
539-
540-
bdev.hspi.Instance = bdev.pdata->spi;
541-
bdev.hspi.Init.Mode = SPI_MODE_MASTER;
542-
bdev.hspi.Init.Direction = SPI_DIRECTION_2LINES;
543-
bdev.hspi.Init.DataSize = SPI_DATASIZE_8BIT;
544-
bdev.hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
545-
bdev.hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
546-
bdev.hspi.Init.NSS = SPI_NSS_SOFT;
547-
bdev.hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
548-
bdev.hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
549-
HAL_SPI_Init(&bdev.hspi);
550-
HAL_NVIC_SetPriority(bdev.pdata->irq, 6, 2);
551-
HAL_NVIC_EnableIRQ(bdev.pdata->irq);
508+
// Configure the GPIO pins.
509+
pbdrv_gpio_alt(&pin_spi0_mosi, SYSCFG_PINMUX3_PINMUX3_15_12_SPI0_SIMO0);
510+
pbdrv_gpio_alt(&pin_spi0_miso, SYSCFG_PINMUX3_PINMUX3_11_8_SPI0_SOMI0);
511+
pbdrv_gpio_alt(&pin_spi0_clk, SYSCFG_PINMUX3_PINMUX3_3_0_SPI0_CLK);
512+
513+
// REVISIT: Do we want to have the peripheral control CS or do it manually
514+
// like we did in the W25QXX STM32 driver? If so, just set it high just
515+
// like the next pin below.
516+
pbdrv_gpio_alt(&pin_spi0_ncs0, SYSCFG_PINMUX4_PINMUX4_7_4_NSPI0_SCS0);
517+
518+
// Is this sufficient to disable ADC SPI?
519+
pbdrv_gpio_out_high(&pin_spi0_ncs3);
520+
521+
//
522+
// REVISIT: Init SPI and DMA with TI AM1808 API
523+
//
524+
// See display_ev3.c for inspiration and adapt settings as needed.
525+
//
552526

553527
pbdrv_init_busy_up();
554528
pbio_os_process_start(&pbdrv_block_device_ev3_init_process, pbdrv_block_device_ev3_init_process_thread, NULL);

0 commit comments

Comments
 (0)