Skip to content

Support to work with the official Arduino STM32 core #57

@rtek1000

Description

@rtek1000

I tried to compile (STM32F103C8T6) but the first error that occurred seems to be relative to the interrupt register definition.

c:\arduino ide\arduino-1.8.10-windows-portable\portable\sketchbook\libraries\dyn_swi\dyn_swi.h:106:2: error: #error SWI_IRQ_NUM not defined (CMSIS)
#error SWI_IRQ_NUM not defined (CMSIS)

https://github.com/stm32duino/Arduino_Core_STM32

I found this post that might help someone identify that SPI port interrupt register:

https://os.mbed.com/forum/mbed/topic/26688/?page=1#comment-50909

Maybe it will be interesting for some MBED developers.

I explain how to extend the SPISlave class for use interrupts on STM32 MCU. With this solution we do not need to change anything in the basic SPISlave class.

First step is common and strighforward. We create instance of SPISlave class and do some configuration (format, frequency, ...). Next we setup SPI CR2 register to enable interrupts. Especially:

  • TXEIE bit to enable 'Tx buffer empty' interrupt - RXNEIE bit to enable 'RX buffer not empty' interrupt

and at last we install own ISR routine for SPI interrupts.

Some explanaition.

Because SPI work in full duplex mode we must have 'filler' (empty) character. I use null byte as filler. Send or receive null byte means that there is nothing to send (or receive). As a consequence this protocol cant be used for binary data. Null bytes must be encoded/decoded on both side (escape sequence processing).

My ISR routine cooperate with two buffers and simple API: - saveInBuf save received characters in external buffer - char2send get next byte to send from transmit buffer

Local (static) buffer 'intBuf' is used in the case when main receive buffer is (temporarily) in use and received character can't be saved.

I run test program on Nucleo-STM32F103RB (64 MHz HSI) connected to Orange Pi Lite (Armbian Linux). On Orange Pi side I use two transmission buffers and Timer interrupt to check for pending transmission (once per 100 us). I configure SPI on both side in 8 bit mode and 16 Mhz frequency.

extern uint32_t Default_Handler;
SPI_TypeDef *cspi = SPI2;
bool blockReader, blockWriter;
 
void setIRQvector(IRQn_Type it, uint32_t fa)
{
    uint32_t dh;
    if(it >= 0)
    {
        if(!fa)
        {
            NVIC_DisableIRQ(it);
            dh = (uint32_t) Default_Handler;
            NVIC_SetVector(it, dh);
        }
        else
        {
            NVIC_SetVector(it, fa);
            NVIC_EnableIRQ(it);
        }
    }
}
 
#define TXEIE_MASK  0x80
#define RXNEIE_MASK 0x40
 
void enableSPIinterrupt(bool enable)
{
    uint32_t isr = 0;
    if(enable)
    {
        isr = (uint32_t) rwSPIservice;
        cspi->CR2 |= (TXEIE_MASK | RXNEIE_MASK);
    }
    else
        cspi->CR2 &= ~(TXEIE_MASK | RXNEIE_MASK);
    setIRQvector(SPI2_IRQn, isr);
}
 
#define RXNE_MASK   1
#define TXE_MASK        2
 
void rwSPIservice(void)
{
    static char intBuf[16];
    static uint16_t cInBuf;
    int tc;
    
    if(cspi->SR & RXNE_MASK && cInBuf < sizeof(intBuf))
    {
        tc = cspi->DR;
        if(tc)
            intBuf[cInBuf++] = tc;
    }
    if(cInBuf > 0 && !blockReader)
    {
        short saved = saveInBuf(intBuf, cInBuf);
        if(saved > 0)
        {
            cInBuf -= saved;
            if(cInBuf > 0)
                memmove(intBuf, intBuf + saved, cInBuf);
        }
    }
    if(cspi->SR & TXE_MASK)
    {
        tc = 0;
        if(!blockWriter)
        {
            tc = char2send();
            if(tc < 0)
                tc = 0;
        }
        cspi->DR = tc;
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions