Author Topic: ARM CMSIS SPI without RTOS  (Read 5168 times)

0 Members and 1 Guest are viewing this topic.

Offline dizgahTopic starter

  • Regular Contributor
  • *
  • Posts: 61
  • Country: 00
ARM CMSIS SPI without RTOS
« on: October 18, 2015, 04:56:14 am »
I'm trying to drive SPI peripheral of my LPC17xx MCU with the latest CMSIS libraries(CMSIS-Driver Version 2.03). I am using its example code described in the SPI Interface. The example used RTOS for driving but I want to use it in bare metal state & because of it I must find a alter for line:
Code: [Select]
osEvent evt;
that defined an evt structure in the RTX,which used to notify the events. as you know CMSIS libraries in this version has comprehensive changes & therefor earlier versions tutorial are not useful.

Example Code:
Code: [Select]
#include "Driver_SPI.h"

#include "cmsis_os.h"                   // ARM::CMSIS:RTOS:Keil RTX




void mySPI_Thread(void const *argument);

osThreadId tid_mySPI_Thread;


/* SPI Driver */

extern ARM_DRIVER_SPI Driver_SPI0;


void mySPI_callback(uint32_t event)
{
    switch (event)
    {
    case ARM_SPI_EVENT_TRANSFER_COMPLETE:
                          /* Success: Wakeup Thread */
        osSignalSet(tid_mySPI_Thread, 0x01);
        break;
    case ARM_SPI_EVENT_DATA_LOST:
        /*  Occurs in slave mode when data is requested/sent by master
            but send/receive/transfer operation has not been started
            and indicates that data is lost. */
                    __breakpoint(0);  /* Error: Call debugger or replace with custom error handling */
        break;
    case ARM_SPI_EVENT_MODE_FAULT:
        /*  Occurs in master mode when Slave Select is deactivated and
            indicates Master Mode Fault. */
                    __breakpoint(0);  /* Error: Call debugger or replace with custom error handling */
        break;
    }
}

/* Test data buffers */
const uint8_t testdata_out[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
uint8_t       testdata_in [8];

void mySPI_Thread(void const* arg)
{
    ARM_DRIVER_SPI* SPIdrv = &Driver_SPI0;
          osEvent evt;

#ifdef DEBUG
    ARM_DRIVER_VERSION   version;
    ARM_SPI_CAPABILITIES drv_capabilities;

    version = SPIdrv->GetVersion();
    if (version.api < 0x200) /* requires at minimum API version 2.00 or higher */
    {                        /* error handling                                 */
        return;
    }

    drv_capabilities = SPIdrv->GetCapabilities();
    if (drv_capabilities.event_mode_fault == 0)
    {                        /* error handling */
        return;
    }
#endif

    /* Initialize the SPI driver */
    SPIdrv->Initialize(mySPI_callback);
    /* Power up the SPI peripheral */
    SPIdrv->PowerControl(ARM_POWER_FULL);
    /* Configure the SPI to Master, 8-bit mode @10000 kBits/sec */
    SPIdrv->Control(ARM_SPI_MODE_MASTER | ARM_SPI_CPOL1_CPHA1 | ARM_SPI_MSB_LSB | ARM_SPI_SS_MASTER_SW | ARM_SPI_DATA_BITS(8), 10000000);

    /* SS line = INACTIVE = HIGH */
    SPIdrv->Control(ARM_SPI_CONTROL_SS, ARM_SPI_SS_INACTIVE);

    /* thread loop */
    while (1)
    {
        /* SS line = ACTIVE = LOW */
        SPIdrv->Control(ARM_SPI_CONTROL_SS, ARM_SPI_SS_ACTIVE);
        /* Transmit some data */
        SPIdrv->Send(testdata_out, sizeof(testdata_out));
        /* Wait for completion */
        evt = osSignalWait(0x01, 100);
        if (evt.status == osEventTimeout) {
            __breakpoint(0); /* Timeout error: Call debugger */
        }
        /* SS line = INACTIVE = HIGH */
        SPIdrv->Control(ARM_SPI_CONTROL_SS, ARM_SPI_SS_INACTIVE);
        /* SS line = ACTIVE = LOW */
        SPIdrv->Control(ARM_SPI_CONTROL_SS, ARM_SPI_SS_ACTIVE);
        /* Receive 8 bytes of reply */
        SPIdrv->Receive(testdata_in, 8);
        evt = osSignalWait(0x01, 100);
        if (evt.status == osEventTimeout) {
            __breakpoint(0); /* Timeout error: Call debugger */
        }
        /* SS line = INACTIVE = HIGH */
        SPIdrv->Control(ARM_SPI_CONTROL_SS, ARM_SPI_SS_INACTIVE);
    }
}
My other question is about this type of programming? I am familiar with structures or pointers but I cannot understand why don't they use simple function in normal instead of :
Code: [Select]
extern ARM_DRIVER_SPI Driver_SPI0;
ARM_DRIVER_SPI* SPIdrv = &Driver_SPI0;
SPIdrv->Send(testdata_out, sizeof(testdata_out));
As I said I can understand what above codes do ,but I can't understand why don't they use them in usual mode? for example:
Code: [Select]
int32_t ARM_SPI_Send    (   const void *    data,   uint32_t    num )   
WBR.


Happiness can be found, even in the darkest of times, if one only remembers to turn on the light.
Albus Dumbledore
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: ARM CMSIS SPI without RTOS
« Reply #1 on: October 18, 2015, 06:14:39 am »
I don't think that normal CMSIS has "simple bare metal" (ie hardware abstraction) functions.  That was attempted in an earlier version of CMSIS, and they sort-of gave up.  You're looking at examples that work with the newer "CMSIS RTOS layer", which has a lot more to do with interfacing to the RTOS (spec) than interfacing to the SPI hardware.   I think.
Quote
SPIdrv->Send
lets you easily have multiple SPIdrv instances in a program, not all of which have to have the same underlying hardware.  (SPI here, SPI on USART there, bit-banged access for another one...)  CMSIS (last I looked) doesn't actually implement ANY of those; it provides a framework for telling you HOW to implement it so that it will be maximally compatible with "other CMSIS stuff."

(OTOH, CMSIS seems to mutate a lot from one version to the next, so I could be out-of-date.)
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: ARM CMSIS SPI without RTOS
« Reply #2 on: October 18, 2015, 11:00:53 am »
The object-oriented model is more flexible. You can have as many driver instances as you have peripherals, and they don't even have to be identical (eg. if a chip has both UARTs and USARTs they can implement the same interface, even if they need different initialization).

An osEvent is a generic data structure for passing information. Depending on the context it can contain a 32-bit value, a pointer or a bitmask of signal flags.

Offline richardman

  • Frequent Contributor
  • **
  • Posts: 427
  • Country: us
Re: ARM CMSIS SPI without RTOS
« Reply #3 on: October 19, 2015, 02:54:39 am »
(OTOH, CMSIS seems to mutate a lot from one version to the next, so I could be out-of-date.)

The contortion that CMSIS goes through every iteration is painful to watch. I suspect we are seeing struggles of different ARM groups asserting their influence...
// richard http://imagecraft.com/
JumpStart C++ for Cortex (compiler/IDE/debugger): the fastest easiest way to get productive on Cortex-M.
Smart.IO: phone App for embedded systems with no app or wireless coding
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf