# HG changeset patch # User jlarmour # Date 1333245753 0 # Node ID 43793d6f613ae570d30379c6bddce2a6053251a9 # Parent 180ded1a8753eb6084406c0204fe802bac5f00e2 Add STM32 F2/F4 support, use new variant-provided DMA, and use new variant-provided definitions. diff --git a/packages/devs/spi/cortexm/stm32/current/ChangeLog b/packages/devs/spi/cortexm/stm32/current/ChangeLog --- a/packages/devs/spi/cortexm/stm32/current/ChangeLog +++ b/packages/devs/spi/cortexm/stm32/current/ChangeLog @@ -1,3 +1,42 @@ +2012-03-28 Jonathan Larmour + + * src/spi_stm32.c (bus3_rx_bbuf): Fix typo in attribute. + +2012-03-23 James Smith + + * src/spi_stm32.c (CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI): + Rename CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPI to allow the same + SPEED_SPI value to be used for F1 and F2/F4 targets. + (SPI_CS): Use new wrapper macros to provide a single common SPI_CS + manifest. + +2012-03-15 James Smith + + * src/spi_stm32.c: Use HIPERFORMANCE manifest to allow F2 and F4 + device GPIO initialisation support. + (dma_channel_setup): Avoid compiler pointer type warning. + +2012-03-05 James Smith + + * src/spi_stm32.c (spi_transaction_dma): Avoid race condition by + seting the TX and RX DMA done flags to false prior to configuring + (and starting) the DMA transfer. + +2012-01-12 Nick Garnett + + * cdl/spi_stm32.cdl: Select pin toggle rate based on STM32 + family. Define interrupt priorities to include DMA channel + priorities. Undo 2011-12-09 change, F2 now supported. + + * include/spi_stm32.h (cyg_spi_cortexm_stm32_bus_s): + * src/spi_stm32.c: Substantial reorganization to use DMA API. + NOTE: Currently only fully tested on F2 parts. + +2011-12-09 Jonathan Larmour + + * cdl/spi_stm32.cdl: For now, only allow this package to be + active with F1 family processors. + 2011-09-27 Ilija Stanislevik * src/spi_stm32.c: Add support for CYG_IO_GET_CONFIG_SPI_CLOCKRATE and @@ -8,11 +47,38 @@ 2011-03-10 John Dallaway + + * cdl/spi_stm32.cdl: Fix descriptions for chip select + options. Only build local test if SPI bus 1 is active. + + * include/spi_stm32.h (cyg_spi_cortexm_stm32_bus_setup_s): Add + spi_gpio_remap field. + + * src/spi_stm32.c (bus1_setup, bus2_setup, bus3_setup): Fix CS + number calculation, add remap to each bus. + (stm32_spi_bus_setup): Move enables to correct place. Add code to + remap SPI pins if defined. + 2009-08-24 Simon Kallweit * cdl/spi_stm32.cdl: added testcase. * include/spi_stm32.h: initializing spi_cr1_val with zero. +2009-06-29 Nick Garnett + + * cdl/spi_stm32.cdl: + * include/spi_stm32.h (cyg_spi_cortexm_stm32_bus_setup_s): + * src/spi_stm32.c: Add support for individual device clock + enables. Also change mechanism for specifying CS lines that is + more in keeping with other devices. + +2009-03-23 Nick Garnett + + * cdl/spi_stm32.cdl: Fix up a few oddities. + + * src/spi_stm32.c (spi_diag): Add some diagnostics. + 2009-02-10 Bart Veer * src/spi_stm32.c (cyg_spi_cortexm_stm32_init): mark as diff --git a/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl b/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl --- a/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl +++ b/packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl @@ -8,7 +8,7 @@ ## ####ECOSGPLCOPYRIGHTBEGIN#### ## ------------------------------------------- ## This file is part of eCos, the Embedded Configurable Operating System. -## Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. +## Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc. ## ## eCos is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free @@ -65,11 +65,11 @@ cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32 display "Pin toggle rate" description " Selects the pin toggle rate in MHz to be used for the SPI interfaces. Higher toggle - rates allow increased baud rates at the expense of power and EMI. - " + rates allow increased baud rates at the expense of power and EMI. Only certain rates + are valid on different STM32 families, check part documentation for which may be used." flavor data - default_value { 2 } - legal_values { 2 10 50 } + default_value { (CYGHWR_HAL_CORTEXM_STM32_FAMILY == "F1") ? 10 : 25 } + legal_values { 2 10 25 50 80 100 } } cdl_component CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1 { @@ -78,18 +78,17 @@ cdl_component CYGHWR_DEVS_SPI_CORTEXM_ST Enable SPI bus 1 on the STM32 device. " flavor bool - default_value false + default_value 0 cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1_CS_GPIOS { display "SPI chip selects" description " This is a comma separated list of GPIOs which are to be used as chip - select lines for the SPI bus. For the purposes of specifying - which GPIOs to use, they are numbered consecutively from 0 (A0) - through 16 (B0) to 111 (G15). + select lines for the SPI bus. Each GPIO is defined by the SPI_CS() + macro which gives the port and pin number. " flavor data - default_value { "4" } + default_value { "SPI_CS(A, 4)" } } cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE { @@ -107,13 +106,13 @@ cdl_component CYGHWR_DEVS_SPI_CORTEXM_ST cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_TXINTR_PRI { display "Transmit DMA interrupt priority" flavor data - default_value 5 + default_value 64+5 } cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_RXINTR_PRI { display "Receive DMA interrupt priority" flavor data - default_value 6 + default_value 128+6 } } @@ -123,18 +122,17 @@ cdl_component CYGHWR_DEVS_SPI_CORTEXM_ST Enable SPI bus 2 on the STM32 device. " flavor bool - default_value false + default_value 0 cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2_CS_GPIOS { display "SPI chip selects" description " This is a comma separated list of GPIOs which are to be used as chip - select lines for the SPI bus. For the purposes of specifying - which GPIOs to use, they are numbered consecutively from 0 (A0) - through 16 (B0) to 111 (G15). + select lines for the SPI bus. Each GPIO is defined by the SPI_CS() + macro which gives the port and pin number. " flavor data - default_value { "28" } + default_value { "SPI_CS(B, 12)" } } cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE { @@ -152,13 +150,13 @@ cdl_component CYGHWR_DEVS_SPI_CORTEXM_ST cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_TXINTR_PRI { display "Transmit DMA interrupt priority" flavor data - default_value 7 + default_value 64+7 } cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_RXINTR_PRI { display "Receive DMA interrupt priority" flavor data - default_value 8 + default_value 128+8 } } @@ -171,7 +169,7 @@ cdl_component CYGHWR_DEVS_SPI_CORTEXM_ST SPI bus initialisation instead. " flavor bool - default_value false + default_value 0 cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_DISABLE_DEBUG_PORT { display "Disable debug port" @@ -180,19 +178,18 @@ cdl_component CYGHWR_DEVS_SPI_CORTEXM_ST initialising SPI bus 3, freeing up the SPI interface pins. " flavor bool - default_value false + default_value 0 } cdl_option CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_CS_GPIOS { display "SPI chip selects" description " This is a comma separated list of GPIOs which are to be used as chip - select lines for the SPI bus. For the purposes of specifying - which GPIOs to use, they are numbered consecutively from 0 (A0) - through 16 (B0) to 111 (G15). + select lines for the SPI bus. Each GPIO is defined by the SPI_CS() + macro which gives the port and pin number. " flavor data - default_value { "15" } + default_value { "SPI_CS(A, 15)" } } cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE { @@ -210,13 +207,13 @@ cdl_component CYGHWR_DEVS_SPI_CORTEXM_ST cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_TXINTR_PRI { display "Transmit DMA interrupt priority" flavor data - default_value 9 + default_value 64+9 } cdl_option CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_RXINTR_PRI { display "Receive DMA interrupt priority" flavor data - default_value 10 + default_value 128+10 } } @@ -263,7 +260,8 @@ cdl_component CYGPKG_DEVS_SPI_CORTEXM_ST } cdl_option CYGPKG_DEVS_SPI_CORTEXM_STM32_TESTS { - display "STM32 SPI tests" + display "SPI tests" + active_if CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1 flavor data no_define calculated { CYGBLD_DEVS_SPI_CORTEXM_STM32_LOOPBACK_TEST ? "tests/loopback" : "" } diff --git a/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h b/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h --- a/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h +++ b/packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h @@ -10,7 +10,7 @@ // ####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 2008, 2009 Free Software Foundation, Inc. +// Copyright (C) 2008, 2009, 2012 Free Software Foundation, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -41,7 +41,7 @@ //============================================================================= //#####DESCRIPTIONBEGIN#### // -// Author(s): Chris Holgate +// Author(s): Chris Holgate, nickg // Date: 2008-11-27 // Purpose: STM32 SPI driver definitions. // Description: @@ -59,6 +59,8 @@ #include #include +#include + //----------------------------------------------------------------------------- // Macro for defining a SPI device and attaching it to the appropriate bus. // @@ -102,16 +104,14 @@ extern cyg_spi_device _name_ __attribute typedef struct cyg_spi_cortexm_stm32_bus_setup_s { - cyg_uint32 apb_freq; // Peripheral bus frequency (fp). + cyg_uint32 *apb_freq; // Peripheral bus frequency. cyg_haladdress spi_reg_base; // Base address of SPI register block. - cyg_haladdress dma_reg_base; // Base address of DMA register block. - cyg_uint8 dma_tx_channel; // TX DMA channel for this bus. - cyg_uint8 dma_rx_channel; // RX DMA channel for this bus. + + cyg_uint32 spi_enable; // SPI bus clock enable cyg_uint8 cs_gpio_num; // Number of chip selects for this bus. - const cyg_uint8* cs_gpio_list; // List of GPIOs used as chip selects. - const cyg_uint8* spi_gpio_list; // List of GPIOs used by the SPI interface. - cyg_vector_t dma_tx_intr; // Interrupt used for DMA transmit. - cyg_vector_t dma_rx_intr; // Interrupt used for DMA receive. + const cyg_uint32* cs_gpio_list; // List of GPIOs used as chip selects. + const cyg_uint32* spi_gpio_list; // List of GPIOs used by the SPI interface. + cyg_uint32 spi_gpio_remap; // Remap GPIO lines to alternate pins. cyg_priority_t dma_tx_intr_pri; // Interrupt priority for DMA transmit. cyg_priority_t dma_rx_intr_pri; // Interrupt priority for DMA receive. cyg_uint32 bbuf_size; // Size of bounce buffers. @@ -129,10 +129,9 @@ typedef struct cyg_spi_cortexm_stm32_bus const cyg_spi_cortexm_stm32_bus_setup_t* setup; // ---- Driver state (private) ---- - cyg_interrupt tx_intr_data; // DMA interrupt data (TX). - cyg_interrupt rx_intr_data; // DMA interrupt data (RX). - cyg_handle_t tx_intr_handle; // DMA interrupt handle (TX). - cyg_handle_t rx_intr_handle; // DMA interrupt handle (RX). + + hal_stm32_dma_stream dma_tx_stream; // TX DMA stream for this bus. + hal_stm32_dma_stream dma_rx_stream; // RX DMA stream for this bus. cyg_drv_mutex_t mutex; // Transfer mutex. cyg_drv_cond_t condvar; // Transfer condition variable. cyg_bool tx_dma_done; // Flags used to signal completion. diff --git a/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c b/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c --- a/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c +++ b/packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c @@ -8,7 +8,7 @@ // ####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 2008, 2009 Free Software Foundation, Inc. +// Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -39,7 +39,7 @@ //============================================================================= //#####DESCRIPTIONBEGIN#### // -// Author(s): Chris Holgate +// Author(s): Chris Holgate, nickg // Date: 2008-11-27 // Purpose: STM32 SPI driver implementation // @@ -64,12 +64,21 @@ #include //----------------------------------------------------------------------------- -// Work out the bus clock frequencies. +// Diagnostics -#define APB1_FREQ ((CYGARC_HAL_CORTEXM_STM32_INPUT_CLOCK * CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL) / \ - (CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV * CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV)) -#define APB2_FREQ ((CYGARC_HAL_CORTEXM_STM32_INPUT_CLOCK * CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL) / \ - (CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV * CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV)) +#if 0 +#define spi_diag( __fmt, ... ) diag_printf("SPI: %30s[%3d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ ); +#define spi_dump_buf( __addr, __size ) diag_dump_buf( __addr, __size ) +#else +#define spi_diag( __fmt, ... ) +#define spi_dump_buf( __addr, __size ) +#endif + +//----------------------------------------------------------------------------- +// Bus frequencies + +__externC cyg_uint32 hal_stm32_pclk1; +__externC cyg_uint32 hal_stm32_pclk2; //----------------------------------------------------------------------------- // API function call forward references. @@ -82,6 +91,12 @@ static int stm32_get_config ( static int stm32_set_config (cyg_spi_device*, cyg_uint32, const void*, cyg_uint32*); //----------------------------------------------------------------------------- +// DMA callbacks + +static void stm32_dma_tx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data ); +static void stm32_dma_rx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data ); + +//----------------------------------------------------------------------------- // Null data source and sink must be placed in the on-chip SRAM. This is // either done explicitly (bounce buffers instantiated) or implicitly (no // bounce buffers implies that the data area is already on SRAM). @@ -98,11 +113,61 @@ static cyg_uint16 dma_rx_null = 0xFFFF; #endif //----------------------------------------------------------------------------- +// Useful GPIO macros for 'dynamic' pin setup. + +#if defined (CYGHWR_HAL_CORTEXM_STM32_FAMILY_F1) + +#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 2) +#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_2MHZ + +#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 10) +#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_10MHZ + +#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 50) +#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPEED_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_50MHZ + +#else +#error "Invalid SPI bus toggle rate." +#endif + +#elif defined (CYGHWR_HAL_CORTEXM_STM32_FAMILY_HIPERFORMANCE) + +#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 2) +#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_2MHZ + +#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 25) +#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_25MHZ + +#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 50) +#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_50MHZ + +#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 80) +#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_HIGH + +#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 100) +#define CYGHWR_HAL_STM32_GPIO_OSPEED_SPEED_SPI CYGHWR_HAL_STM32_GPIO_OSPEED_HIGH + +#else +#error "Invalid SPI bus toggle rate." +#endif + +#else + +#error "Unknown STM32 family" + +#endif + +#define SPI_CS( __port, __bit ) CYGHWR_HAL_STM32_PIN_OUT( __port, __bit, PUSHPULL, NONE, SPEED_SPI ) + +//----------------------------------------------------------------------------- + // Instantiate the bus state data structures. #ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1 -static const cyg_uint8 bus1_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1_CS_GPIOS }; -static const cyg_uint8 bus1_spi_gpio_list[] = { 0x05, 0x06, 0x07 }; +static const cyg_uint32 bus1_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS1_CS_GPIOS }; +static const cyg_uint32 bus1_spi_gpio_list[] = { CYGHWR_HAL_STM32_SPI1_SCK, + CYGHWR_HAL_STM32_SPI1_MISO, + CYGHWR_HAL_STM32_SPI1_MOSI }; #if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE > 0) static cyg_uint8 bus1_tx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE] @@ -112,18 +177,16 @@ static cyg_uint8 bus1_rx_bbuf [CYGNUM_DE #endif static const cyg_spi_cortexm_stm32_bus_setup_t bus1_setup = { - .apb_freq = APB2_FREQ, + .apb_freq = &hal_stm32_pclk2, .spi_reg_base = CYGHWR_HAL_STM32_SPI1, - .dma_reg_base = CYGHWR_HAL_STM32_DMA1, - .dma_tx_channel = 3, - .dma_rx_channel = 2, - .cs_gpio_num = sizeof (bus1_cs_gpio_list), + .spi_enable = CYGHWR_HAL_STM32_SPI1_CLOCK, + .cs_gpio_num = sizeof (bus1_cs_gpio_list)/sizeof(cyg_uint32), .cs_gpio_list = bus1_cs_gpio_list, .spi_gpio_list = bus1_spi_gpio_list, - .dma_tx_intr = CYGNUM_HAL_INTERRUPT_DMA1_CH3, - .dma_rx_intr = CYGNUM_HAL_INTERRUPT_DMA1_CH2, + .spi_gpio_remap = CYGHWR_HAL_STM32_SPI1_REMAP_CONFIG, .dma_tx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_TXINTR_PRI, .dma_rx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_RXINTR_PRI, + #if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE > 0) .bbuf_size = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS1_BBUF_SIZE, .bbuf_tx = bus1_tx_bbuf, @@ -141,13 +204,26 @@ cyg_spi_cortexm_stm32_bus_t cyg_spi_stm3 .spi_bus.spi_get_config = stm32_get_config, .spi_bus.spi_set_config = stm32_set_config, .setup = &bus1_setup, - .cs_up = false + .cs_up = false, + + .dma_tx_stream.desc = CYGHWR_HAL_STM32_SPI1_DMA_TX, + .dma_tx_stream.callback = stm32_dma_tx_callback, + .dma_tx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus1, + + .dma_rx_stream.desc = CYGHWR_HAL_STM32_SPI1_DMA_RX, + .dma_rx_stream.callback = stm32_dma_rx_callback, + .dma_rx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus1, + + + }; #endif #ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2 -static const cyg_uint8 bus2_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2_CS_GPIOS }; -static const cyg_uint8 bus2_spi_gpio_list[] = { 0x1D, 0x1E, 0x1F }; +static const cyg_uint32 bus2_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS2_CS_GPIOS }; +static const cyg_uint32 bus2_spi_gpio_list[] = { CYGHWR_HAL_STM32_SPI2_SCK, + CYGHWR_HAL_STM32_SPI2_MISO, + CYGHWR_HAL_STM32_SPI2_MOSI }; #if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE > 0) static cyg_uint8 bus2_tx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE] @@ -157,18 +233,16 @@ static cyg_uint8 bus2_rx_bbuf [CYGNUM_DE #endif static const cyg_spi_cortexm_stm32_bus_setup_t bus2_setup = { - .apb_freq = APB1_FREQ, + .apb_freq = &hal_stm32_pclk1, .spi_reg_base = CYGHWR_HAL_STM32_SPI2, - .dma_reg_base = CYGHWR_HAL_STM32_DMA1, - .dma_tx_channel = 5, - .dma_rx_channel = 4, - .cs_gpio_num = sizeof (bus2_cs_gpio_list), + .spi_enable = CYGHWR_HAL_STM32_SPI2_CLOCK, + .cs_gpio_num = sizeof (bus2_cs_gpio_list)/sizeof(cyg_uint32), .cs_gpio_list = bus2_cs_gpio_list, .spi_gpio_list = bus2_spi_gpio_list, - .dma_tx_intr = CYGNUM_HAL_INTERRUPT_DMA1_CH5, - .dma_rx_intr = CYGNUM_HAL_INTERRUPT_DMA1_CH4, + .spi_gpio_remap = CYGHWR_HAL_STM32_SPI2_REMAP_CONFIG, .dma_tx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_TXINTR_PRI, .dma_rx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_RXINTR_PRI, + #if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE > 0) .bbuf_size = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS2_BBUF_SIZE, .bbuf_tx = bus2_tx_bbuf, @@ -186,34 +260,44 @@ cyg_spi_cortexm_stm32_bus_t cyg_spi_stm3 .spi_bus.spi_get_config = stm32_get_config, .spi_bus.spi_set_config = stm32_set_config, .setup = &bus2_setup, - .cs_up = false + .cs_up = false, + + .dma_tx_stream.desc = CYGHWR_HAL_STM32_SPI2_DMA_TX, + .dma_tx_stream.callback = stm32_dma_tx_callback, + .dma_tx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus2, + + .dma_rx_stream.desc = CYGHWR_HAL_STM32_SPI2_DMA_RX, + .dma_rx_stream.callback = stm32_dma_rx_callback, + .dma_rx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus2, + + }; #endif #ifdef CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3 -static const cyg_uint8 bus3_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_CS_GPIOS }; -static const cyg_uint8 bus3_spi_gpio_list[] = { 0x13, 0x14, 0x15 }; +static const cyg_uint32 bus3_cs_gpio_list[] = { CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_CS_GPIOS }; +static const cyg_uint32 bus3_spi_gpio_list[] = { CYGHWR_HAL_STM32_SPI3_SCK, + CYGHWR_HAL_STM32_SPI3_MISO, + CYGHWR_HAL_STM32_SPI3_MOSI }; #if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE > 0) static cyg_uint8 bus3_tx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE] __attribute__((aligned (2), section (".sram"))) = { 0 }; static cyg_uint8 bus3_rx_bbuf [CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE] - __attribute__((alugned (2), section (".sram"))) = { 0 }; + __attribute__((aligned (2), section (".sram"))) = { 0 }; #endif static const cyg_spi_cortexm_stm32_bus_setup_t bus3_setup = { - .apb_freq = APB1_FREQ, + .apb_freq = &hal_stm32_pclk1, .spi_reg_base = CYGHWR_HAL_STM32_SPI3, - .dma_reg_base = CYGHWR_HAL_STM32_DMA2, - .dma_tx_channel = 2, - .dma_rx_channel = 1, - .cs_gpio_num = sizeof (bus3_cs_gpio_list), + .spi_enable = CYGHWR_HAL_STM32_SPI3_CLOCK, + .cs_gpio_num = sizeof (bus3_cs_gpio_list)/sizeof(cyg_uint32), .cs_gpio_list = bus3_cs_gpio_list, .spi_gpio_list = bus3_spi_gpio_list, - .dma_tx_intr = CYGNUM_HAL_INTERRUPT_DMA2_CH2, - .dma_rx_intr = CYGNUM_HAL_INTERRUPT_DMA2_CH1, + .spi_gpio_remap = CYGHWR_HAL_STM32_SPI3_REMAP_CONFIG, .dma_tx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_TXINTR_PRI, .dma_rx_intr_pri = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_RXINTR_PRI, + #if (CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE > 0) .bbuf_size = CYGNUM_DEVS_SPI_CORTEXM_STM32_BUS3_BBUF_SIZE, .bbuf_tx = bus3_tx_bbuf, @@ -231,39 +315,18 @@ cyg_spi_cortexm_stm32_bus_t cyg_spi_stm3 .spi_bus.spi_get_config = stm32_get_config, .spi_bus.spi_set_config = stm32_set_config, .setup = &bus3_setup, - .cs_up = false -}; -#endif - -//----------------------------------------------------------------------------- -// Useful GPIO macros for 'dynamic' pin setup. + .cs_up = false, -static const cyg_uint32 stm32_gpio_port_offsets[] = { - CYGHWR_HAL_STM32_GPIOA - CYGHWR_HAL_STM32_GPIOA, - CYGHWR_HAL_STM32_GPIOB - CYGHWR_HAL_STM32_GPIOA, - CYGHWR_HAL_STM32_GPIOC - CYGHWR_HAL_STM32_GPIOA, - CYGHWR_HAL_STM32_GPIOD - CYGHWR_HAL_STM32_GPIOA, - CYGHWR_HAL_STM32_GPIOE - CYGHWR_HAL_STM32_GPIOA, - CYGHWR_HAL_STM32_GPIOF - CYGHWR_HAL_STM32_GPIOA, - CYGHWR_HAL_STM32_GPIOG - CYGHWR_HAL_STM32_GPIOA -}; + .dma_tx_stream.desc = CYGHWR_HAL_STM32_SPI3_DMA_TX, + .dma_tx_stream.callback = stm32_dma_tx_callback, + .dma_tx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus3, -#define STM32_GPIO_PINSPEC(__port, __bit, __mode, __cnf ) \ - (stm32_gpio_port_offsets[__port] | (__bit<<16) | \ - (CYGHWR_HAL_STM32_GPIO_MODE_##__mode) | \ - (CYGHWR_HAL_STM32_GPIO_CNF_##__cnf)) - -#if (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 2) -#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_2MHZ + .dma_rx_stream.desc = CYGHWR_HAL_STM32_SPI3_DMA_RX, + .dma_rx_stream.callback = stm32_dma_rx_callback, + .dma_rx_stream.data = (CYG_ADDRWORD)&cyg_spi_stm32_bus3, -#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 10) -#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_10MHZ -#elif (CYGNUM_DEVS_SPI_CORTEXM_STM32_PIN_TOGGLE_RATE == 50) -#define CYGHWR_HAL_STM32_GPIO_MODE_OUT_SPI CYGHWR_HAL_STM32_GPIO_MODE_OUT_50MHZ - -#else -#error "Invalid SPI bus toggle rate." +}; #endif //----------------------------------------------------------------------------- @@ -272,17 +335,8 @@ static const cyg_uint32 stm32_gpio_port_ static inline void stm32_spi_gpio_cs_setup (cyg_uint32 gpio_num) { - cyg_uint32 port, pin, pinspec; - - // Check that the pin number is in range (16 pins per port). - pin = gpio_num & 0xF; - port = gpio_num >> 4; - CYG_ASSERT (port < 7, "STM32 SPI : Invalid GPIO number in chip select list."); - - // Generate the pin setup specification and configure it. - pinspec = STM32_GPIO_PINSPEC (port, pin, OUT_SPI, OUT_PUSHPULL); - CYGHWR_HAL_STM32_GPIO_SET (pinspec); - CYGHWR_HAL_STM32_GPIO_OUT (pinspec, 1); + CYGHWR_HAL_STM32_GPIO_SET (gpio_num); + CYGHWR_HAL_STM32_GPIO_OUT (gpio_num, 1); } //----------------------------------------------------------------------------- @@ -291,74 +345,15 @@ static inline void stm32_spi_gpio_cs_set static inline void stm32_spi_chip_select (cyg_uint32 gpio_num, cyg_bool assert) { - cyg_uint32 port, pin, pinspec; - - // Check that the pin number is in range (16 pins per port). - pin = gpio_num & 0xF; - port = gpio_num >> 4; - CYG_ASSERT (port < 7, "STM32 SPI : Invalid GPIO number in chip select list."); - - // Generate the pin setup specification and drive it. - pinspec = STM32_GPIO_PINSPEC (port, pin, OUT_SPI, OUT_PUSHPULL); - CYGHWR_HAL_STM32_GPIO_OUT (pinspec, assert ? 0 : 1); + CYGHWR_HAL_STM32_GPIO_OUT( gpio_num, assert ? 0 : 1); } //----------------------------------------------------------------------------- -// Implement DMA ISRs. These disable the DMA channel, mask the interrupt -// condition and schedule their respective DSRs. - -static cyg_uint32 stm32_tx_ISR - (cyg_vector_t vector, cyg_addrword_t data) -{ - cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) data; - cyg_uint32 chan = stm32_bus->setup->dma_tx_channel; - cyg_haladdress reg_addr; - - // Disable the DMA channel. - cyg_drv_isr_lock (); - reg_addr = stm32_bus->setup->dma_reg_base + CYGHWR_HAL_STM32_DMA_CCR (chan); - HAL_WRITE_UINT32 (reg_addr, 0); - - // Clear down the interrupts. - reg_addr = stm32_bus->setup->dma_reg_base + CYGHWR_HAL_STM32_DMA_IFCR; - HAL_WRITE_UINT32 (reg_addr, CYGHWR_HAL_STM32_DMA_IFCR_MASK (chan)); - - cyg_drv_interrupt_acknowledge (vector); - cyg_drv_interrupt_mask (vector); - cyg_drv_isr_unlock (); - - return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED); -} +// DMA Callbacks. The DMA driver has disabled the DMA channel and +// masked the interrupt condition, here we need to wake up the client +// thread. -static cyg_uint32 stm32_rx_ISR - (cyg_vector_t vector, cyg_addrword_t data) -{ - cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) data; - cyg_uint32 chan = stm32_bus->setup->dma_rx_channel; - cyg_haladdress reg_addr; - - // Disable the DMA channel. - cyg_drv_isr_lock (); - reg_addr = stm32_bus->setup->dma_reg_base + CYGHWR_HAL_STM32_DMA_CCR (chan); - HAL_WRITE_UINT32 (reg_addr, 0); - - // Clear down the interrupts. - reg_addr = stm32_bus->setup->dma_reg_base + CYGHWR_HAL_STM32_DMA_IFCR; - HAL_WRITE_UINT32 (reg_addr, CYGHWR_HAL_STM32_DMA_IFCR_MASK (chan)); - - cyg_drv_interrupt_acknowledge (vector); - cyg_drv_interrupt_mask (vector); - cyg_drv_isr_unlock (); - - return (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED); -} - -//----------------------------------------------------------------------------- -// Implement DMA DSRs. These clear down the interrupt conditions and assert -// their respective 'transaction complete' flags. - -static void stm32_tx_DSR - (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +static void stm32_dma_tx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data ) { cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) data; @@ -368,8 +363,7 @@ static void stm32_tx_DSR cyg_drv_dsr_unlock (); } -static void stm32_rx_DSR - (cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +static void stm32_dma_rx_callback( hal_stm32_dma_stream *stream, cyg_uint32 count, CYG_ADDRWORD data ) { cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) data; @@ -387,56 +381,47 @@ static void stm32_spi_bus_setup { int i; cyg_haladdress reg_addr; - cyg_uint32 pin, pinspec, reg_data; + cyg_uint32 reg_data; + spi_diag("bus %p\n", stm32_bus ); // Set up the GPIOs for use as chip select lines. for (i = 0; i < stm32_bus->setup->cs_gpio_num; i ++) { stm32_spi_gpio_cs_setup (stm32_bus->setup->cs_gpio_list[i]); } - // Configure the SPI clock output pin. - pin = stm32_bus->setup->spi_gpio_list[0]; - pinspec = STM32_GPIO_PINSPEC ((pin >> 4), (pin & 0xF), OUT_SPI, ALT_PUSHPULL); - CYGHWR_HAL_STM32_GPIO_SET (pinspec); +#if defined (CYGHWR_HAL_CORTEXM_STM32_FAMILY_F1) + // Remap GPIO pins if required + if( stm32_bus->setup->spi_gpio_remap ) + { + CYG_ADDRESS afio = CYGHWR_HAL_STM32_AFIO; + cyg_uint32 mapr; + spi_diag("remap %08x\n", stm32_bus->setup->spi_gpio_remap ); + CYGHWR_HAL_STM32_CLOCK_ENABLE( CYGHWR_HAL_STM32_AFIO_CLOCK ); + HAL_READ_UINT32( afio+CYGHWR_HAL_STM32_AFIO_MAPR, mapr ); + mapr |= stm32_bus->setup->spi_gpio_remap; + HAL_WRITE_UINT32( afio+CYGHWR_HAL_STM32_AFIO_MAPR, mapr ); + } +#endif + + CYGHWR_HAL_STM32_GPIO_SET( stm32_bus->setup->spi_gpio_list[0] ); + CYGHWR_HAL_STM32_GPIO_SET( stm32_bus->setup->spi_gpio_list[1] ); + CYGHWR_HAL_STM32_GPIO_SET( stm32_bus->setup->spi_gpio_list[2] ); - // Configure the SPI MISO input. - pin = stm32_bus->setup->spi_gpio_list[1]; - pinspec = STM32_GPIO_PINSPEC ((pin >> 4), (pin & 0xF), IN, PULLUP); - CYGHWR_HAL_STM32_GPIO_SET (pinspec); - - // Configure the SPI MOSI output. - pin = stm32_bus->setup->spi_gpio_list[2]; - pinspec = STM32_GPIO_PINSPEC ((pin >> 4), (pin & 0xF), OUT_SPI, ALT_PUSHPULL); - CYGHWR_HAL_STM32_GPIO_SET (pinspec); + CYGHWR_HAL_STM32_CLOCK_ENABLE( stm32_bus->setup->spi_enable ); + //CYGHWR_HAL_STM32_CLOCK_ENABLE( stm32_bus->setup->dma_enable ); // Set up SPI default configuration. reg_addr = stm32_bus->setup->spi_reg_base + CYGHWR_HAL_STM32_SPI_CR2; reg_data = CYGHWR_HAL_STM32_SPI_CR2_TXDMAEN | CYGHWR_HAL_STM32_SPI_CR2_RXDMAEN; HAL_WRITE_UINT32 (reg_addr, reg_data); - // Ensure that the DMA clocks are enabled. - reg_addr = CYGHWR_HAL_STM32_RCC + CYGHWR_HAL_STM32_RCC_AHBENR; - HAL_READ_UINT32 (reg_addr, reg_data); - if (stm32_bus->setup->dma_reg_base == CYGHWR_HAL_STM32_DMA1) - reg_data |= CYGHWR_HAL_STM32_RCC_AHBENR_DMA1; - else - reg_data |= CYGHWR_HAL_STM32_RCC_AHBENR_DMA2; - HAL_WRITE_UINT32 (reg_addr, reg_data); - // Initialise the synchronisation primitivies. cyg_drv_mutex_init (&stm32_bus->mutex); cyg_drv_cond_init (&stm32_bus->condvar, &stm32_bus->mutex); - // Hook up the ISRs and DSRs. - cyg_drv_interrupt_create (stm32_bus->setup->dma_tx_intr, stm32_bus->setup->dma_tx_intr_pri, - (cyg_addrword_t) stm32_bus, stm32_tx_ISR, stm32_tx_DSR, &stm32_bus->tx_intr_handle, - &stm32_bus->tx_intr_data); - cyg_drv_interrupt_attach (stm32_bus->tx_intr_handle); - - cyg_drv_interrupt_create (stm32_bus->setup->dma_rx_intr, stm32_bus->setup->dma_rx_intr_pri, - (cyg_addrword_t) stm32_bus, stm32_rx_ISR, stm32_rx_DSR, &stm32_bus->rx_intr_handle, - &stm32_bus->rx_intr_data); - cyg_drv_interrupt_attach (stm32_bus->rx_intr_handle); + // Initialize DMA streams + hal_stm32_dma_init( &stm32_bus->dma_tx_stream, stm32_bus->setup->dma_tx_intr_pri ); + hal_stm32_dma_init( &stm32_bus->dma_rx_stream, stm32_bus->setup->dma_rx_intr_pri ); // Call upper layer bus init. CYG_SPI_BUS_COMMON_INIT(&stm32_bus->spi_bus); @@ -450,59 +435,22 @@ static void dma_channel_setup { cyg_spi_cortexm_stm32_bus_t* stm32_bus = (cyg_spi_cortexm_stm32_bus_t*) device->spi_bus; cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device; - - cyg_uint32 chan, reg_data; - cyg_haladdress dma_reg_base, spi_reg_base, dma_addr, reg_addr; + hal_stm32_dma_stream *stream = is_tx ? &stm32_bus->dma_tx_stream : &stm32_bus->dma_rx_stream; - // Extract address and channel information. - dma_reg_base = stm32_bus->setup->dma_reg_base; - spi_reg_base = stm32_bus->setup->spi_reg_base; - chan = is_tx ? stm32_bus->setup->dma_tx_channel : stm32_bus->setup->dma_rx_channel; + hal_stm32_dma_configure( stream, + stm32_device->bus_16bit ? 16 : 8, + (data_buf==NULL), + polled ); - // Default options for the DMA channel. - reg_data = CYGHWR_HAL_STM32_DMA_CCR_EN; - - // Do not enable interrupts in polled mode. - if (!polled) - reg_data |= CYGHWR_HAL_STM32_DMA_CCR_TCIE | CYGHWR_HAL_STM32_DMA_CCR_TEIE; - - // Set DMA channel direction and priority level. The receive channel has higher - // priority so that the inbound buffer is always cleared first. - if (is_tx) - reg_data |= CYGHWR_HAL_STM32_DMA_CCR_DIR | CYGHWR_HAL_STM32_DMA_CCR_PLMEDIUM; - else - reg_data |= CYGHWR_HAL_STM32_DMA_CCR_PLHIGH; + if( data_buf == NULL ) + data_buf = (cyg_uint8 *)(is_tx ? &dma_tx_null : &dma_rx_null); + + hal_stm32_dma_start( stream, + data_buf, + stm32_bus->setup->spi_reg_base+CYGHWR_HAL_STM32_SPI_DR, + count ); - // Set the correct transfer size. - if (stm32_device->bus_16bit) - reg_data |= CYGHWR_HAL_STM32_DMA_CCR_PSIZE16 | CYGHWR_HAL_STM32_DMA_CCR_MSIZE16; - else - reg_data |= CYGHWR_HAL_STM32_DMA_CCR_PSIZE8 | CYGHWR_HAL_STM32_DMA_CCR_MSIZE8; - - // Do not use memory address incrementing for dummy data. - if (data_buf != NULL) { - reg_data |= CYGHWR_HAL_STM32_DMA_CCR_MINC; - dma_addr = (cyg_haladdress) data_buf; - } - else - dma_addr = (cyg_haladdress) (is_tx ? &dma_tx_null : &dma_rx_null); - - // Program up the DMA memory address. - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_CMAR (chan); - HAL_WRITE_UINT32 (reg_addr, dma_addr); - - // Program up the peripheral memory address. - dma_addr = spi_reg_base + CYGHWR_HAL_STM32_SPI_DR; - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_CPAR (chan); - HAL_WRITE_UINT32 (reg_addr, dma_addr); - - // Program up the data buffer size. - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_CNDTR (chan); - HAL_WRITE_UINT32 (reg_addr, count); - - // Enable the DMA via the configuration register. - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_CCR (chan); - HAL_WRITE_UINT32 (reg_addr, reg_data); + hal_stm32_dma_show( stream ); } //----------------------------------------------------------------------------- @@ -516,11 +464,10 @@ static void spi_transaction_dma cyg_spi_cortexm_stm32_device_t* stm32_device = (cyg_spi_cortexm_stm32_device_t*) device; cyg_haladdress reg_addr; - cyg_uint32 chan, reg_data; - cyg_haladdress dma_reg_base = stm32_bus->setup->dma_reg_base; cyg_haladdress spi_reg_base = stm32_bus->setup->spi_reg_base; + spi_diag("device %p\n", device ); // Ensure the chip select is asserted, inserting inter-transaction guard // time if required. Note that when ticking the device we do not touch the CS. if (!stm32_bus->cs_up && !tick_only) { @@ -530,58 +477,30 @@ static void spi_transaction_dma CYGACC_CALL_IF_DELAY_US (stm32_device->cs_up_udly); } + // Clear done flags prior to configuring DMA: + stm32_bus->tx_dma_done = false; + stm32_bus->rx_dma_done = false; + // Set up the DMA channels. dma_channel_setup (device, (cyg_uint8*) tx_data, count, true, polled); dma_channel_setup (device, rx_data, count, false, polled); // Run the DMA (polling for completion). if (polled) { - cyg_bool transfer_done = false; - // Enable the SPI controller. reg_addr = spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1; HAL_WRITE_UINT32 (reg_addr, stm32_device->spi_cr1_val | CYGHWR_HAL_STM32_SPI_CR1_SPE); - // Spin waiting on both DMA status flags. Trap bus errors and assert in - // debug builds or return garbage in production builds. - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_ISR; - do { - HAL_READ_UINT32 (reg_addr, reg_data); - if ((reg_data & CYGHWR_HAL_STM32_DMA_ISR_TEIF (stm32_bus->setup->dma_tx_channel)) || - (reg_data & CYGHWR_HAL_STM32_DMA_ISR_TEIF (stm32_bus->setup->dma_rx_channel))) { - CYG_ASSERT (false, "STM32 SPI : DMA bus fault - enable bounce buffers."); - transfer_done = true; - } - if ((reg_data & CYGHWR_HAL_STM32_DMA_ISR_TCIF (stm32_bus->setup->dma_tx_channel)) && - (reg_data & CYGHWR_HAL_STM32_DMA_ISR_TCIF (stm32_bus->setup->dma_rx_channel))) { - transfer_done = true; - } - } while (!transfer_done); - - // Disable the DMA channels on completion and clear the status flags. - chan = stm32_bus->setup->dma_tx_channel; - reg_data = CYGHWR_HAL_STM32_DMA_IFCR_MASK (chan); - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_CCR (chan); - HAL_WRITE_UINT32 (reg_addr, 0); - - chan = stm32_bus->setup->dma_rx_channel; - reg_data |= CYGHWR_HAL_STM32_DMA_IFCR_MASK (chan); - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_CCR (chan); - HAL_WRITE_UINT32 (reg_addr, 0); - - reg_addr = dma_reg_base + CYGHWR_HAL_STM32_DMA_IFCR; - HAL_WRITE_UINT32 (reg_addr, reg_data); + while( !(stm32_bus->tx_dma_done && stm32_bus->rx_dma_done) ) + { + hal_stm32_dma_poll( &stm32_bus->dma_tx_stream ); + hal_stm32_dma_poll( &stm32_bus->dma_rx_stream ); + } } - // Run the DMA (interrupt driven). else { cyg_drv_mutex_lock (&stm32_bus->mutex); cyg_drv_dsr_lock (); - stm32_bus->tx_dma_done = false; - stm32_bus->rx_dma_done = false; - - cyg_drv_interrupt_unmask (stm32_bus->setup->dma_tx_intr); - cyg_drv_interrupt_unmask (stm32_bus->setup->dma_rx_intr); // Enable the SPI controller. reg_addr = spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1; @@ -596,6 +515,7 @@ static void spi_transaction_dma cyg_drv_mutex_unlock (&stm32_bus->mutex); } + // Disable the SPI controller. reg_addr = spi_reg_base + CYGHWR_HAL_STM32_SPI_CR1; HAL_WRITE_UINT32 (reg_addr, stm32_device->spi_cr1_val); @@ -616,7 +536,7 @@ static int calculate_br_bits cyg_uint32 divided_clk; // Calculate the maximum viable bus speed. - divided_clk = bus->setup->apb_freq / 2; + divided_clk = *bus->setup->apb_freq / 2; for (*br = 0; (*br < 7) && (divided_clk > *target_clockrate); (*br)++) divided_clk >>= 1; @@ -632,6 +552,7 @@ static int calculate_br_bits static void CYGBLD_ATTRIB_C_INIT_PRI(CYG_INIT_BUS_SPI) stm32_spi_init(void) { + spi_diag("\n"); #if defined(CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3) && \ defined(CYGHWR_DEVS_SPI_CORTEXM_STM32_BUS3_DISABLE_DEBUG_PORT) // Disable debug port, freeing up SPI bus 3 pins. @@ -667,6 +588,7 @@ static void stm32_transaction_begin cyg_haladdress reg_addr; cyg_uint32 reg_data, br; + spi_diag("\n"); // On the first transaction, generate the values to be programmed into the // SPI configuration registers for this device and cache them. This avoids // having to recalculate the prescaler for every transaction. @@ -708,6 +630,9 @@ static void stm32_transaction_transfer // Check for unsupported transactions. CYG_ASSERT (count > 0, "STM32 SPI : Null transfer requested."); + spi_diag("count %d\n", count); + if( tx_data ) spi_dump_buf(tx_data, count ); + // We check that the buffers are half-word aligned and that count is a // multiple of two in order to carry out the 16-bit transfer. if (stm32_device->bus_16bit) { @@ -743,6 +668,10 @@ static void stm32_transaction_transfer else { spi_transaction_dma (device, false, polled, count, tx_data, rx_data, drop_cs); } + + spi_diag("done\n"); + if( rx_data ) spi_dump_buf(rx_data, count ); + } //----------------------------------------------------------------------------- @@ -757,6 +686,8 @@ static void stm32_transaction_tick // Check for unsupported transactions. CYG_ASSERT (count > 0, "STM32 SPI : Null transfer requested."); + spi_diag("count %d\n", count); + // We check that count is a multiple of two in order to carry out the 16-bit transfer. if (stm32_device->bus_16bit) { CYG_ASSERT (!(count & 1), @@ -778,6 +709,7 @@ static void stm32_transaction_end cyg_haladdress reg_addr; + spi_diag("\n"); // Ensure that the chip select is deasserted. if (stm32_bus->cs_up) { CYGACC_CALL_IF_DELAY_US (stm32_device->cs_dw_udly); @@ -815,7 +747,7 @@ static int stm32_get_config return -1; } - *data_p = stm32_bus->setup->apb_freq >> ((( stm32_device->spi_cr1_val >> 3 ) & 7) + 1 ) ; + *data_p = *stm32_bus->setup->apb_freq >> ((( stm32_device->spi_cr1_val >> 3 ) & 7) + 1 ) ; return 0; default :