changeset 3142:43793d6f613a

Add STM32 F2/F4 support, use new variant-provided DMA, and use new variant-provided definitions.
author jlarmour
date Sun, 01 Apr 2012 02:02:33 +0000
parents 180ded1a8753
children ceb1113eb4bd
files packages/devs/spi/cortexm/stm32/current/ChangeLog packages/devs/spi/cortexm/stm32/current/cdl/spi_stm32.cdl packages/devs/spi/cortexm/stm32/current/include/spi_stm32.h packages/devs/spi/cortexm/stm32/current/src/spi_stm32.c
diffstat 4 files changed, 304 insertions(+), 309 deletions(-) [+]
line wrap: on
line diff
--- 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  <jifl@eCosCentric.com>
+
+	* src/spi_stm32.c (bus3_rx_bbuf): Fix typo in attribute.
+
+2012-03-23  James Smith  <jsmith@ecoscentric.com>
+
+	* 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  <jsmith@ecoscentric.com>
+
+	* 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  <jsmith@ecoscentric.com>
+
+	* 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  <nickg@ecoscentric.com>
+
+	* 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  <jifl@eCosCentric.com>
+
+	* cdl/spi_stm32.cdl: For now, only allow this package to be
+	active with F1 family processors.
+
 2011-09-27  Ilija Stanislevik  <ilijas@siva.mk>
 
 	* src/spi_stm32.c: Add support for CYG_IO_GET_CONFIG_SPI_CLOCKRATE and
@@ -8,11 +47,38 @@ 2011-03-10  John Dallaway  <john@dallawa
 
 	* cdl/spi_stm32.cdl: Add build options for CFLAGS and loopback test.
 
+2009-10-22  Nick Garnett  <nickg@ecoscentric.com>
+
+	* 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  <simon.kallweit@intefo.ch>
 
 	* cdl/spi_stm32.cdl: added testcase.
 	* include/spi_stm32.h: initializing spi_cr1_val with zero.
 
+2009-06-29  Nick Garnett  <nickg@ecoscentric.com>
+
+	* 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  <nickg@ecoscentric.com>
+
+	* cdl/spi_stm32.cdl: Fix up a few oddities.
+
+	* src/spi_stm32.c (spi_diag): Add some diagnostics.
+
 2009-02-10  Bart Veer  <bartv@ecoscentric.com>
 
 	* src/spi_stm32.c (cyg_spi_cortexm_stm32_init): mark as
--- 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" : "" } 
--- 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 <cyg/hal/drv_api.h>
 #include <cyg/io/spi.h>
 
+#include <cyg/hal/var_dma.h>
+
 //-----------------------------------------------------------------------------
 // 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.
--- 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 <string.h>
 
 //-----------------------------------------------------------------------------
-// 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 :