SPI1 on STM32F103

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
AnSc
Posts: 17
Joined: Tue Mar 29, 2022 4:16 pm
Has thanked: 1 time
Been thanked: 2 times

SPI1 on STM32F103

Postby AnSc » Tue Mar 29, 2022 5:13 pm

Hi,

I'm new to STM32 development. I did some projects in the past with Atmel controllers, but started a new project using the STM32F103.
I built a keyboard with this processor last year and the firmware for this uses Chibios too. And I got it up and running after a bit of research and support from various people. So I thought I can use it in a new project without to much trouble…

I'm now several days looking why I cannot get the SPI1 interface running.
I have a small demo running using NIL which toggles two LEDs and sends some text via UART.

But as soon as I try to do anything on SPI the controller stops. The debugger (hoping I use it correctly) says something about unhandled exception in this state.

When I build the project I get a warning that gives me no clue:
c:\chibistudio\chibios2111\os\hal\ports\stm32\lld\gpiov1\hal_pal_lld.h:81:3: warning: initialization of 'void (*)(SPIDriver *)' {aka 'void (*)(struct hal_spi_driver *)'} from 'long unsigned int' makes pointer from integer without a cast [-Wint-conversion]

I tried several projects that use SPI in some way but could not find a good starting point since none seems to use SPI1.

I'm not sure if I found all required points I need to address to get it running.
What I did regarding SPI:

./board/board.c:

Code: Select all

void boardInit(void) {
  //JTAG-DP Disabled and SW-DP Enabled
  AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE;
  AFIO->MAPR |= AFIO_MAPR_TIM3_REMAP_FULLREMAP; //map timer 3 to port C
  AFIO->MAPR |= AFIO_MAPR_SPI1_REMAP; // enable SPI1
}


./board/board.h:

Code: Select all

#define LINE_SPI1_NSS       PAL_LINE(GPIOA,  4)    // pin 20


/*
 * Port A setup.
 * Everything input with pull-up except:
 * PA0..4       - Normal output, PA4 SPI NSS
 * PA5,7        - Alternate output SPI SCK, MOSI
 * PA9          - Output USART
 * PA10         - Input USART
 * PA11,12      - USB
 */
#define VAL_GPIOACRL            0xB8B33333      /*  PA7...PA0 */
#define VAL_GPIOACRH            0x888884B8      /* PA15...PA8 */
#define VAL_GPIOAODR            0xffffffff


./cfg/halconf.ha

Code: Select all

/**
 * @brief   Enables the SPI subsystem.
 */
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI                         TRUE
#endif

/*===========================================================================*/
/* SPI driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Enables synchronous APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT                        TRUE
#endif

/**
 * @brief   Inserts an assertion on function errors before returning.
 */
#if !defined(SPI_USE_ASSERT_ON_ERROR) || defined(__DOXYGEN__)
#define SPI_USE_ASSERT_ON_ERROR             TRUE
#endif

/**
 * @brief   Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION            FALSE
#endif

/**
 * @brief   Handling method for SPI CS line.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
//#define SPI_SELECT_MODE                     SPI_SELECT_MODE_PAD
#define SPI_SELECT_MODE                     SPI_SELECT_MODE_LINE
#endif

(As a side note: when I set SPI_USE_WAIT to FALSE I get a compile error: "../../../Chibistudio/chibios2111/os/hal/ports/STM32/LLD/SPIv1/hal_spi_v2_lld.c:239:50: error: macro "__spi_wakeup_isr" passed 2 arguments, but takes just 1")

./cfg/mcuconf.h

Code: Select all

#define STM32F103_MCUCONF

#define STM32_SPI_USE_SPI1                  TRUE


./main.c

Code: Select all

/** Maximum speed SPI configuration (9MHz, CPHA=0, CPOL=0, MSb first).   */
static const SPIConfig hs_spicfg = {
  false,  // disable circular mode
  NULL,   // no callback
  LINE_SPI1_NSS,  // CS line, requires SPI_SELECT_MODE SPI_SELECT_MODE_LINE in halconf.h
  SPI_CR1_BR_0,  // BR0 set for 9 MHz (STM32_PPRE1/4)
  0    // use ChibiOS defaults
};

THD_WORKING_AREA(waThread4, 128);
THD_FUNCTION(Thread4, arg) {
  (void)arg;
  /* enable power to OLED */
  palSetLine(LINE_LCD_EN);
  /* disable CS line */
  palSetLine(LINE_SPI1_NSS);
  /*
   * Activates SPI driver 1 using the driver default configuration.
   */
  static const uint8_t payload[1] = {0xa5}; // dummy buffer
  /* initialize SPI port 1 */
  spiStart(&SPID1, &hs_spicfg);
  /* reset OLED */
  //oledReset();

  while (true) {
    oledReset(); // pull down Reset, wait 500 ms, pull up Reset
//    spiSelect(&SPID1);  // if enabled this line causes the controller to stop
//    spiSend(&SPID1, 1, &payload);
 //   spiUnselect(&SPID1);
    chThdSleepMilliseconds(2000);
  }
}

THD_TABLE_BEGIN
  THD_TABLE_THREAD(0, "blinker1", waThread1, Thread1, NULL)
  THD_TABLE_THREAD(1, "blinker2", waThread2, Thread2, NULL)
  THD_TABLE_THREAD(2, "hello",    waThread3, Thread3, NULL)
  THD_TABLE_THREAD(3, "spi",      waThread4, Thread4, NULL)
THD_TABLE_END


I hope that helps to locate my error or where I need to add something.

As an aside: I tried to implement this as RT also but this did not even run with just a blinker task. From the debugger it looked to me that it was stuck in the (empty) main loop. Therefore, I try to implement it in NIL.

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: SPI1 on STM32F103

Postby Giovanni » Tue Mar 29, 2022 6:10 pm

Hi,

Which version are you using?

The demo in /testhal/STM32/multi/SPI uses SPI1 on the F1 and compiles fine (testing the latest code in trunk).

Examples of configurations:

Code: Select all

/*
 * Circular SPI configuration (18MHz, CPHA=0, CPOL=0, MSb first).
 */
const SPIConfig c_spicfg = {
  .circular         = true,
  .slave            = false,
  .data_cb          = spi_circular_cb,
  .error_cb         = spi_error_cb,
  .ssport           = GPIOA,
  .sspad            = GPIOA_SPI1NSS,
  .cr1              = 0U,
  .cr2              = 0U
};

/*
 * Maximum speed SPI configuration (18MHz, CPHA=0, CPOL=0, MSb first).
 */
const SPIConfig hs_spicfg = {
  .circular         = false,
  .slave            = false,
  .data_cb          = NULL,
  .error_cb         = spi_error_cb,
  .ssport           = GPIOA,
  .sspad            = GPIOA_SPI1NSS,
  .cr1              = 0U,
  .cr2              = 0U
};

/*
 * Low speed SPI configuration (281.250kHz, CPHA=0, CPOL=0, MSb first).
 */
const SPIConfig ls_spicfg = {
  .circular         = false,
  .slave            = false,
  .data_cb          = NULL,
  .error_cb         = spi_error_cb,
  .ssport           = GPIOA,
  .sspad            = GPIOA_SPI1NSS,
  .cr1              = SPI_CR1_BR_2 | SPI_CR1_BR_1,
  .cr2              = 0U
};


Try starting from that demo configurations, also look at settings in halconf.h and mcuconf.h.

Giovanni

AnSc
Posts: 17
Joined: Tue Mar 29, 2022 4:16 pm
Has thanked: 1 time
Been thanked: 2 times

Re: SPI1 on STM32F103

Postby AnSc » Tue Mar 29, 2022 10:18 pm

Hi Giovanni,

thanks for the feedback, I'm using version 21.11.

Found it and will do some reading. Looks like a RT implementation, I hope to learn from this.
I will give it a try in the next days. :)

André

AnSc
Posts: 17
Joined: Tue Mar 29, 2022 4:16 pm
Has thanked: 1 time
Been thanked: 2 times

Re: SPI1 on STM32F103

Postby AnSc » Wed Mar 30, 2022 6:44 pm

I gave it a try today.
I took the "olimex" port and adapted it to my board.

The LED is flashing and the SPI threads seem to run alternatively according to the debugger.

However, I cannot measure any signal change on the corresponding signals. No clock and no data is sent out. Chip select is toggled, however.

An additional trhead I inserted sends successfully data over UART1.

Is there anything I'm missing? Are there any settings I could check that maybe collide and prevent the SPI data being sent out?

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: SPI1 on STM32F103

Postby Giovanni » Wed Mar 30, 2022 7:20 pm

Hi,

I would check GPIO/AFIO settings. Make sure to create proper "board files" with all your GPIO initialization data.

Giovanni

AnSc
Posts: 17
Joined: Tue Mar 29, 2022 4:16 pm
Has thanked: 1 time
Been thanked: 2 times

Re: SPI1 on STM32F103

Postby AnSc » Thu Mar 31, 2022 1:21 pm

Thanks for the pointer. This helped me a lot. :)

I found that setting the appropriate bits in board.h already yields the desired result.
However, when I set

Code: Select all

AFIO->MAPR |= AFIO_MAPR_SPI1_REMAP;
I see no output. Leaving this line out it works.

Do I interpret this correctly that by just setting the output to Alternate the first alternate in the datasheet/signal list is active?

But then, what does AFIO_MAPR_SPI1_REMAP achieve? Is this only required when SPI1 is used on port B where it is declared in the Remap column?

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: SPI1 on STM32F103

Postby Giovanni » Thu Mar 31, 2022 1:42 pm

Hi,

This mess is caused by the old remap mechanism on ST32F1, there are also some errata about it.

In general if you don't do any remap then the alternate pin is the default one.

Giovanni


Return to “ChibiOS/HAL”

Who is online

Users browsing this forum: No registered users and 4 guests