Compare commits
3 Commits
wip/ahci
...
cja/spi-wi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e51e0b8e3 | ||
|
|
945308fe03 | ||
|
|
11fd254c58 |
17
platform/stm32f7xx/include/platform/spi.h
Normal file
17
platform/stm32f7xx/include/platform/spi.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <err.h>
|
||||
#include <platform/stm32.h>
|
||||
#include <kernel/mutex.h>
|
||||
|
||||
struct spi_bus {
|
||||
SPI_TypeDef *spi;
|
||||
mutex_t lock;
|
||||
};
|
||||
|
||||
#define INVALID_SPI_BUS -1
|
||||
|
||||
status_t spi_init (SPI_HandleTypeDef *handle);
|
||||
status_t spi_write(SPI_HandleTypeDef *handle, uint8_t *data, size_t len, uint32_t cs);
|
||||
status_t spi_read(SPI_HandleTypeDef *handle, uint8_t *data, size_t len, uint32_t cs);
|
||||
status_t spi_transaction(SPI_HandleTypeDef *handle, uint8_t *wdata, uint8_t *rdata, size_t len, uint32_t cs);
|
||||
|
||||
@@ -48,11 +48,12 @@ MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/usbc.c \
|
||||
$(LOCAL_DIR)/vectab.c \
|
||||
$(LOCAL_DIR)/sdram.c \
|
||||
$(LOCAL_DIR)/spi.c \
|
||||
$(LOCAL_DIR)/qspi.c
|
||||
|
||||
# use a two segment memory layout, where all of the read-only sections
|
||||
# of the binary reside in rom, and the read/write are in memory. The
|
||||
# ROMBASE, MEMBASE, and MEMSIZE make variables are required to be set
|
||||
# use a two segment memory layout, where all of the read-only sections
|
||||
# of the binary reside in rom, and the read/write are in memory. The
|
||||
# ROMBASE, MEMBASE, and MEMSIZE make variables are required to be set
|
||||
# for the linker script to be generated properly.
|
||||
#
|
||||
LINKER_SCRIPT += \
|
||||
|
||||
312
platform/stm32f7xx/spi.c
Normal file
312
platform/stm32f7xx/spi.c
Normal file
@@ -0,0 +1,312 @@
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <target/gpioconfig.h>
|
||||
#include <platform/spi.h>
|
||||
#include <platform/stm32.h>
|
||||
|
||||
static struct spi_bus spi_busses[] = {
|
||||
{ .spi = SPI1 },
|
||||
{ .spi = SPI2 },
|
||||
{ .spi = SPI3 },
|
||||
{ .spi = SPI4 },
|
||||
{ .spi = SPI5 },
|
||||
{ .spi = SPI6 }
|
||||
};
|
||||
|
||||
static inline int get_bus_idx(SPI_TypeDef *spi)
|
||||
{
|
||||
for (unsigned int i = 0; i < (sizeof(spi_busses)/sizeof(spi_busses[0])); i++) {
|
||||
if (spi_busses[i].spi == spi) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_SPI_BUS;
|
||||
}
|
||||
|
||||
static bool wait_for_bus_ready(SPI_HandleTypeDef *handle)
|
||||
{
|
||||
size_t timeout = 1024;
|
||||
while (timeout && (HAL_SPI_GetState(handle) != HAL_SPI_STATE_READY)) {
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (timeout == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
status_t spi_init (SPI_HandleTypeDef *handle)
|
||||
{
|
||||
DEBUG_ASSERT(handle);
|
||||
|
||||
status_t ret = NO_ERROR;
|
||||
int bus = get_bus_idx(handle->Instance);
|
||||
|
||||
if (bus == INVALID_SPI_BUS) {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
mutex_init(&(spi_busses[bus].lock));
|
||||
if (HAL_SPI_Init(handle) != HAL_OK) {
|
||||
ret = ERR_GENERIC;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t spi_write(SPI_HandleTypeDef *handle, uint8_t *data, size_t len, uint32_t cs)
|
||||
{
|
||||
DEBUG_ASSERT(handle);
|
||||
DEBUG_ASSERT(data);
|
||||
DEBUG_ASSERT(len);
|
||||
|
||||
status_t ret = NO_ERROR;
|
||||
int bus = get_bus_idx(handle->Instance);
|
||||
|
||||
if (bus == INVALID_SPI_BUS) {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
mutex_acquire(&(spi_busses[bus].lock));
|
||||
if (handle->Init.NSS == SPI_NSS_SOFT) {
|
||||
gpio_set(cs, (handle->Init.CLKPolarity == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef foo;
|
||||
|
||||
/* The lock may have been released while the hardware is still processing a transaction */
|
||||
/*if (!wait_for_bus_ready(handle)) {
|
||||
ret = ERR_BUSY;
|
||||
} else {*/
|
||||
if ((foo = HAL_SPI_Transmit(handle, data, len, HAL_MAX_DELAY)) != HAL_OK) {
|
||||
printf("foo %d\n", foo);
|
||||
ret = ERR_IO;
|
||||
}
|
||||
// }
|
||||
|
||||
if (handle->Init.NSS == SPI_NSS_SOFT) {
|
||||
gpio_set(cs, (handle->Init.CLKPolarity == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
}
|
||||
mutex_release(&(spi_busses[bus].lock));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t spi_read(SPI_HandleTypeDef *handle, uint8_t *data, size_t len, uint32_t cs)
|
||||
{
|
||||
DEBUG_ASSERT(handle);
|
||||
DEBUG_ASSERT(data);
|
||||
DEBUG_ASSERT(len);
|
||||
|
||||
status_t ret = NO_ERROR;
|
||||
int bus = get_bus_idx(handle->Instance);
|
||||
|
||||
if (bus == INVALID_SPI_BUS) {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
mutex_acquire(&(spi_busses[bus].lock));
|
||||
if (handle->Init.NSS == SPI_NSS_SOFT) {
|
||||
gpio_set(cs, (handle->Init.CLKPolarity == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
if (HAL_SPI_Receive(handle, data, len, HAL_MAX_DELAY) != HAL_OK) {
|
||||
ret = ERR_IO;
|
||||
}
|
||||
|
||||
if (handle->Init.NSS == SPI_NSS_SOFT) {
|
||||
gpio_set(cs, (handle->Init.CLKPolarity == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
}
|
||||
mutex_release(&(spi_busses[bus].lock));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t spi_transaction(SPI_HandleTypeDef *handle, uint8_t *wdata, uint8_t *rdata, size_t len, uint32_t cs)
|
||||
{
|
||||
DEBUG_ASSERT(handle);
|
||||
DEBUG_ASSERT(wdata);
|
||||
DEBUG_ASSERT(rdata);
|
||||
DEBUG_ASSERT(len);
|
||||
|
||||
status_t ret = NO_ERROR;
|
||||
int bus = get_bus_idx(handle->Instance);
|
||||
|
||||
if (bus == INVALID_SPI_BUS) {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
mutex_acquire(&(spi_busses[bus].lock));
|
||||
if (handle->Init.NSS == SPI_NSS_SOFT) {
|
||||
gpio_set(cs, (handle->Init.CLKPolarity == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
if (HAL_SPI_TransmitReceive(handle, wdata, rdata, len, HAL_MAX_DELAY) != HAL_OK) {
|
||||
ret = ERR_IO;
|
||||
}
|
||||
|
||||
if (handle->Init.NSS == SPI_NSS_SOFT) {
|
||||
gpio_set(cs, (handle->Init.CLKPolarity == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
}
|
||||
mutex_release(&(spi_busses[bus].lock));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if WITH_LIB_CONSOLE
|
||||
#include <lib/console.h>
|
||||
|
||||
/* Bus configurations for testing. Although it requires a recompilation per setting tweaked,
|
||||
* it saves us from having to write a great deal of configuration code via an awkward console
|
||||
* interface with many arguments.
|
||||
*
|
||||
* XXX: This doesn't handle soft NSS on its own.
|
||||
*/
|
||||
|
||||
// This test code is primarily for DartuinoP0 and the GPIO will only exist for that target
|
||||
#define STM32F7_SPI_BUS_CNT 6
|
||||
static SPI_HandleTypeDef handles[STM32F7_SPI_BUS_CNT] = {
|
||||
[0] = { 0 },
|
||||
[1] = {
|
||||
.Instance = SPI2,
|
||||
.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4,
|
||||
.Init.Direction = SPI_DIRECTION_1LINE,
|
||||
.Init.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.Init.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.Init.DataSize = SPI_DATASIZE_8BIT,
|
||||
.Init.FirstBit = SPI_FIRSTBIT_LSB,
|
||||
.Init.TIMode = SPI_TIMODE_DISABLE,
|
||||
.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.Init.CRCPolynomial = 7,
|
||||
.Init.NSS = SPI_NSS_SOFT,
|
||||
.Init.Mode = SPI_MODE_MASTER,
|
||||
},
|
||||
[2] = { 0 },
|
||||
[3] = { 0 },
|
||||
[4] = { 0 },
|
||||
[5] = {
|
||||
.Instance = SPI5,
|
||||
.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4,
|
||||
.Init.Direction = SPI_DIRECTION_1LINE,
|
||||
.Init.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.Init.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.Init.DataSize = SPI_DATASIZE_8BIT,
|
||||
.Init.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.Init.TIMode = SPI_TIMODE_DISABLE,
|
||||
.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.Init.CRCPolynomial = 7,
|
||||
.Init.NSS = SPI_NSS_SOFT,
|
||||
.Init.Mode = SPI_MODE_MASTER,
|
||||
},
|
||||
};
|
||||
|
||||
// GPIO to whack for soft chip select
|
||||
static unsigned int handle_nss[STM32F7_SPI_BUS_CNT] = {
|
||||
[5] = GPIO(GPIO_PORT_K, 0), // NRF_CS on Dartuino P0
|
||||
};
|
||||
|
||||
|
||||
/* Check if bus is valid, initialize it if needed */
|
||||
static inline bool check_bus(uint8_t bus)
|
||||
{
|
||||
if (bus < STM32F7_SPI_BUS_CNT && handles[bus].Instance == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HAL_SPI_GetState(&handles[bus]) == HAL_SPI_STATE_RESET) {
|
||||
HAL_SPI_Init(&handles[bus]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void print_spi_usage(void)
|
||||
{
|
||||
printf("spi read <bus> <len>\n");
|
||||
printf("\tRead <len> bytes from <bus>\n");
|
||||
printf("spi spew <bus> <len> <n> <delay>\n");
|
||||
printf("\tWrite <len> bytes <n> times with a delay of <delay> ms between over <bus>\n");
|
||||
}
|
||||
|
||||
#define IS_CMD(_str, _argc) (argc >= _argc && (strcmp(_str, argv[1].str) == 0))
|
||||
static int cmd_spi(int argc, const cmd_args *argv)
|
||||
{
|
||||
status_t ret = NO_ERROR;
|
||||
// spi read <bus> <len>
|
||||
if (IS_CMD("read", 4)) {
|
||||
uint8_t bus = argv[2].i;
|
||||
size_t len = MIN(1024, argv[3].i);
|
||||
uint8_t *data = (uint8_t *)malloc(len);
|
||||
|
||||
if (!data) {
|
||||
ret = ERR_NO_MEMORY;
|
||||
goto read_err;
|
||||
}
|
||||
|
||||
if (!check_bus(bus)) {
|
||||
printf("Error: bus %u is invalid\n", bus);
|
||||
ret = ERR_INVALID_ARGS;
|
||||
goto read_err;
|
||||
}
|
||||
|
||||
if (spi_read(&handles[bus], data, len, handle_nss[bus]) != NO_ERROR) {
|
||||
printf("spi read error\n");
|
||||
ret = ERR_IO;
|
||||
goto read_err;
|
||||
}
|
||||
|
||||
hexdump8(data, len);
|
||||
|
||||
read_err:
|
||||
free(data);
|
||||
|
||||
// spi spew <bus> <len> <iterations> <delay>
|
||||
} else if (IS_CMD("spew", 6)) {
|
||||
uint8_t bus = argv[2].i;
|
||||
size_t len = MIN(1024, argv[3].i);
|
||||
uint32_t cnt = argv[4].i;
|
||||
uint32_t delay = argv[5].i;
|
||||
uint8_t *data = (uint8_t *)malloc(len);
|
||||
|
||||
if (cnt == 0) {
|
||||
cnt = UINT32_MAX;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
data[i] = i % 255;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < cnt; i++) {
|
||||
int spi_ret;
|
||||
if ((spi_ret = spi_write(&handles[bus], data, len, handle_nss[bus])) != NO_ERROR) {
|
||||
printf("spi write error: %d\n", spi_ret);
|
||||
ret = ERR_IO;
|
||||
goto spew_err;
|
||||
}
|
||||
|
||||
if (delay > 0) {
|
||||
thread_sleep(delay);
|
||||
}
|
||||
}
|
||||
|
||||
spew_err:
|
||||
free(data);
|
||||
} else {
|
||||
print_spi_usage();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC_COMMAND_START
|
||||
STATIC_COMMAND("spi", "spi commands for stm32f7", &cmd_spi)
|
||||
STATIC_COMMAND_END(spi);
|
||||
|
||||
|
||||
|
||||
#endif // WITH_LIB_CONSOLE
|
||||
@@ -3,5 +3,5 @@
|
||||
export PROJECT=dartuinoP0-test
|
||||
|
||||
make -j8 &&
|
||||
openocd -f interface/stlink-v2.cfg -f board/stm32756g_eval.cfg \
|
||||
openocd -f interface/stlink-v2.cfg -f target/stm32f7x.cfg \
|
||||
-c "program build-$PROJECT/lk.bin reset exit 0x08000000"
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
export PROJECT=stm32f746g-disco-test
|
||||
|
||||
make -j8 &&
|
||||
openocd -f interface/stlink-v2-1.cfg -f board/stm32756g_eval.cfg \
|
||||
openocd -f interface/stlink-v2-1.cfg -f board/stm32f7discovery.cfg \
|
||||
-c "program build-$PROJECT/lk.bin reset exit 0x08000000"
|
||||
|
||||
@@ -132,7 +132,9 @@ void target_init(void)
|
||||
|
||||
qspi_flash_init(N25Q128A_FLASH_SIZE);
|
||||
|
||||
memory_lcd_init();
|
||||
if (memory_lcd_init() != NO_ERROR) {
|
||||
printf("error initializing memory_lcd\n");
|
||||
}
|
||||
|
||||
#if WITH_LIB_MINIP
|
||||
uint8_t mac_addr[6];
|
||||
@@ -207,6 +209,19 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
|
||||
/*##-3- Configure the NVIC for SPI #########################################*/
|
||||
/* NVIC for SPI */
|
||||
HAL_NVIC_EnableIRQ(SPI2_IRQn);
|
||||
} else if (hspi->Instance == SPI5) {
|
||||
/* SPI5
|
||||
* PF6 SPI5_NSS
|
||||
* PF7 SPI5_SCK
|
||||
* PF8 SPI5_MISO
|
||||
* PF9 SPI5_MOSI
|
||||
*/
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_SPI5_CLK_ENABLE();
|
||||
gpio_config(GPIO_SPI5_SCK, GPIO_STM32_AF | GPIO_STM32_AFn(GPIO_AF5_SPI5) | GPIO_PULLUP);
|
||||
gpio_config(GPIO_SPI5_MISO, GPIO_STM32_AF | GPIO_STM32_AFn(GPIO_AF5_SPI5) | GPIO_PULLUP);
|
||||
gpio_config(GPIO_SPI5_MOSI, GPIO_STM32_AF | GPIO_STM32_AFn(GPIO_AF5_SPI5) | GPIO_PULLUP);
|
||||
HAL_NVIC_EnableIRQ(SPI5_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ PLATFORM := stm32f7xx
|
||||
SDRAM_SIZE := 0x00800000
|
||||
SDRAM_BASE := 0xc0000000
|
||||
|
||||
DISPLAY_PANEL_TYPE ?= LS013B7DH06
|
||||
DISPLAY_PANEL_TYPE ?= LS027B7DH01
|
||||
|
||||
GLOBAL_DEFINES += \
|
||||
ENABLE_UART3=1 \
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
#include <err.h>
|
||||
#include <kernel/mutex.h>
|
||||
#include <platform/gpio.h>
|
||||
#include <platform/spi.h>
|
||||
#include <target/gpioconfig.h>
|
||||
#include <target/bmi055.h>
|
||||
#include <target/sensor_bus.h>
|
||||
#include <dev/accelerometer.h>
|
||||
|
||||
static mutex_t sensorbus_mutex;
|
||||
static SPI_HandleTypeDef spi_handle;
|
||||
|
||||
static uint8_t tx_buff[16];
|
||||
@@ -49,19 +49,7 @@ status_t acc_read_xyz(position_vector_t *pos_vector_p)
|
||||
|
||||
status_t acc_flush(uint8_t *tbuff, uint8_t *rbuff, uint8_t numbytes)
|
||||
{
|
||||
status_t ret_status;
|
||||
|
||||
mutex_acquire(&sensorbus_mutex);
|
||||
|
||||
gpio_set(GPIO_ACC_nCS,GPIO_PIN_RESET);
|
||||
|
||||
ret_status = HAL_SPI_TransmitReceive(&spi_handle, tbuff, rbuff, numbytes, 5000);
|
||||
|
||||
gpio_set(GPIO_ACC_nCS,GPIO_PIN_SET);
|
||||
|
||||
mutex_release(&sensorbus_mutex);
|
||||
|
||||
return ret_status;
|
||||
return spi_transaction(&spi_handle, tbuff, rbuff, numbytes, GPIO_ACC_nCS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,11 +59,6 @@ status_t acc_flush(uint8_t *tbuff, uint8_t *rbuff, uint8_t numbytes)
|
||||
status_t sensor_bus_init_early(void)
|
||||
{
|
||||
__HAL_SENSOR_BUS_GPIO_CLK_ENABLE();
|
||||
__HAL_RCC_SPI5_CLK_ENABLE();
|
||||
|
||||
gpio_config(GPIO_SPI5_SCK, GPIO_STM32_AF | GPIO_STM32_AFn(GPIO_AF5_SPI5) | GPIO_PULLUP);
|
||||
gpio_config(GPIO_SPI5_MISO, GPIO_STM32_AF | GPIO_STM32_AFn(GPIO_AF5_SPI5) | GPIO_PULLUP);
|
||||
gpio_config(GPIO_SPI5_MOSI, GPIO_STM32_AF | GPIO_STM32_AFn(GPIO_AF5_SPI5) | GPIO_PULLUP);
|
||||
|
||||
gpio_config(GPIO_NRF_CS, GPIO_OUTPUT );
|
||||
gpio_config(GPIO_NRF_INT, GPIO_INPUT | GPIO_PULLUP);
|
||||
@@ -109,11 +92,8 @@ status_t sensor_bus_init_early(void)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sensor_bus_init(void)
|
||||
{
|
||||
mutex_init(&sensorbus_mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ GLOBAL_DEFINES += \
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/init.c \
|
||||
$(LOCAL_DIR)/lcd.c \
|
||||
$(LOCAL_DIR)/spi.c \
|
||||
$(LOCAL_DIR)/usb.c
|
||||
|
||||
MODULE_DEPS += \
|
||||
|
||||
Reference in New Issue
Block a user