ARM CMSIS SPI without RTOS - Page 1
Forum section: electronics / general

author: dizgah
author_rank: Regular Contributor
timestamp: October 18, 2015, 04:56:14 am
content: 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: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:#include "Driver_SPI.h"#include "cmsis_os.h" // ARM::CMSIS:RTOS:Keil RTXvoid 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 masterbut send/receive/transfer operation has not been startedand 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 andindicates Master Mode Fault. */__breakpoint(0); /* Error: Call debugger or replace with custom error handling */break;}}/* Test data buffers */const uint8_t testdata_out = { 0, 1, 2, 3, 4, 5, 6, 7 };uint8_t testdata_in ;void mySPI_Thread(void const* arg){ARM_DRIVER_SPI* SPIdrv = &Driver_SPI0;osEvent evt;#ifdef DEBUGARM_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: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:int32_t ARM_SPI_Send ( const void * data, uint32_t num )WBR.

author: westfw
author_rank: Super Contributor
timestamp: October 18, 2015, 06:14:39 am
content: 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.Quotelets 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.)

author: andersm
author_rank: Super Contributor
timestamp: October 18, 2015, 11:00:53 am
content: 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.

author: richardman
author_rank: Frequent Contributor
timestamp: October 19, 2015, 02:54:39 am
content: Quote from: westfw on October 18, 2015, 06:14:39 amThe contortion that CMSIS goes through every iteration is painful to watch. I suspect we are seeing struggles of different ARM groups asserting their influence...