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.