MMC_SPI shared with other multiple/devices

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
User avatar
Chudik
Posts: 152
Joined: Fri Jan 16, 2015 7:51 am
Has thanked: 7 times
Been thanked: 1 time

Re: MMC_SPI shared with other multiple/devices

Post by Chudik »

I'm lost somewhere in SPI :-(
Based on experience with Serial interface I thought that system would care about all hardware pins, wrote SPI based interface to my display board, but it does not work. Went through source codes, found that pins are not initialized and added settings for the pins. I did not help :(
What else did I miss?
Here is my initialization
In mcuconfig.h

Code: Select all

/*
 * SPI driver system settings.
 */
#define STM32_SPI_USE_SPI1                  FALSE
#define STM32_SPI_USE_SPI2                  TRUE    // FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY         1
#define STM32_SPI_SPI2_DMA_PRIORITY         1
#define STM32_SPI_SPI1_IRQ_PRIORITY         10
#define STM32_SPI_SPI2_IRQ_PRIORITY         10
#define STM32_SPI_DMA_ERROR_HOOK(spip)      chSysHalt()


ui_driver.c

Code: Select all

static const SPIConfig display_cfg =
{
   NULL,   // we use master mode
   DISPLAY_CS_PORT,
   DISPLAY_CS_PIN,
   BR_VALUE      // Since CPHA and CPOL are 0, we don't need to set any control for it
} ;

static const SPIConfig ui_cfg =
{
   NULL,   // we use master mode
   BUTTON_CS_PORT,
   BUTTON_CS_PIN,
   BR_VALUE      // Since CPHA and CPOL are 0, we don't need to set any control for it
};


uint8_t DisplayInitSequence[] =      //used sequence from NHD-2.23-12832UCY3 datasheet
{
   DISPLAYOFF,            // Display Off (0x00/0x01)
   DISPLAYCLK_C,0x10,      // Set Clock as 160 Frames/Sec

...
// my additional init to fill memory with 0
   MEMADDRESSMODE_C, 0x00,      // Horizontal Addressing Mode
   COLUMNADDRESS_C, 0x00, 0x7F,    // Set borders of cleaning columns
   PAGEADDRESS_C, 0x00, 0x7F      // Set borders of cleaning rows

   // finish with
   // Fill_RAM(0x00);    // Clear Screen
   // DISPLAYON       // Display On (0x00/0x01
};

/*===========================================================================*/
/* Driver local functions.                                                   */
/*===========================================================================*/
//const DisplayFont F8x5 = { (uint8_t *)Font8x5, 8, 5};

/*===========================================================================*/
/* Driver exported functions.                                                */
/*===========================================================================*/

/**
 * @brief   UI Driver initialization.
 * @note    This function is implicitly invoked by @p halInit(), there is
 *          no need to explicitly initialize the driver.
 *
 * @init
 */


void UIInit(void)
{ uint16_t i;
  uint8_t data ;

    {   // UI (Display, Buttons, LEDs) hardware initialization
        palSetPadMode(UI_RST_PORT, UI_RST_PIN, PAL_STM32_MODE_OUTPUT | PAL_MODE_OUTPUT_PUSHPULL);   // reset pin for the all display board
        palSetPadMode(DISPLAY_CTRL_PORT, DISPLAY_DC_PIN | DISPLAY_CS_PIN | BUTTON_CS_PIN | HEN1_PIN | HEN2_PIN,   // hardware control pins
                      PAL_STM32_MODE_OUTPUT | PAL_MODE_OUTPUT_PUSHPULL);

        palSetPadMode(INT_BUT_PORT, INT_BUT_PIN, PAL_STM32_MODE_INPUT | PAL_STM32_PUDR_PULLUP); // just input yet. Will be used for interrupts from buttons

        palSetPadMode(DISPLAY_CTRL_PORT, SPI2_MOSI | SPI2_MISO | SPI2_SCK, PAL_STM32_MODE_ALTERNATE | PAL_STM32_ALTERNATE(5));  // hardware SPI pins

    }


//  spiInit();  done in halinit()
// Display Init.
 {
//   spiObjectInit(&Display);    it is only for SPI2 and called in spiInit()

   spiStart(&Display, &display_cfg);
   palClearPad(DISPLAY_DC_PORT, DISPLAY_DC_PIN);   // display sending commands mode
   spiSelect(&Display);
   [b]spiSend(&Display, sizeof(DisplayInitSequence), DisplayInitSequence);[/b]  // <<--- stops in here!!!

// Fill Memory with 0
....
   spiUnselect(&Display);
 }
// End of display init
}


chsys.c

Code: Select all

#include "ch.h"

#if !CH_NO_IDLE_THREAD || defined(__DOXYGEN__)
WORKING_AREA(_idle_thread_wa, PORT_IDLE_THREAD_STACK_SIZE);

void _idle_thread(void *p) {

  (void)p;
  chRegSetThreadName("idle");
  while (TRUE) {
    port_wait_for_interrupt();
    IDLE_LOOP_HOOK();
  }                                                // <<< ----------------------- Actually stops here.
}
#endif /* CH_NO_IDLE_THREAD */
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: MMC_SPI shared with other multiple/devices

Post by Giovanni »

Probably a problem with pins setup. Never mix PAL_MODE_ and PAL_STM32_. Also check if SPI2 is already mapped in board.h.

Giovanni
User avatar
Chudik
Posts: 152
Joined: Fri Jan 16, 2015 7:51 am
Has thanked: 7 times
Been thanked: 1 time

Re: MMC_SPI shared with other multiple/devices

Post by Chudik »

No, in boards.h SPI2 is not defined.
So, does it mean, that instead of setting pins in the program I should use boards.h for that?

Regarding never mixing... That style was in the original program template for blinking LED and I also used it for getting clock on output. Was it wrong as well?
What should I use then? palSetPad() and palClearPad()?
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: MMC_SPI shared with other multiple/devices

Post by Giovanni »

Some combinations are not possible. This is how it is done in the STM32F4 SPI demo:

Code: Select all

/*
    ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "ch.h"
#include "hal.h"

/*
 * Maximum speed SPI configuration (21MHz, CPHA=0, CPOL=0, MSb first).
 */
static const SPIConfig hs_spicfg = {
  NULL,
  GPIOB,
  12,
  0
};

/*
 * Low speed SPI configuration (328.125kHz, CPHA=0, CPOL=0, MSb first).
 */
static const SPIConfig ls_spicfg = {
  NULL,
  GPIOB,
  12,
  SPI_CR1_BR_2 | SPI_CR1_BR_1
};

/*
 * SPI TX and RX buffers.
 */
static uint8_t txbuf[512];
static uint8_t rxbuf[512];

/*
 * SPI bus contender 1.
 */
static WORKING_AREA(spi_thread_1_wa, 256);
static msg_t spi_thread_1(void *p) {

  (void)p;
  chRegSetThreadName("SPI thread 1");
  while (TRUE) {
    spiAcquireBus(&SPID2);              /* Acquire ownership of the bus.    */
    palSetPad(GPIOD, GPIOD_LED5);       /* LED ON.                          */
    spiStart(&SPID2, &hs_spicfg);       /* Setup transfer parameters.       */
    spiSelect(&SPID2);                  /* Slave Select assertion.          */
    spiExchange(&SPID2, 512,
                txbuf, rxbuf);          /* Atomic transfer operations.      */
    spiUnselect(&SPID2);                /* Slave Select de-assertion.       */
    spiReleaseBus(&SPID2);              /* Ownership release.               */
  }
  return 0;
}

/*
 * SPI bus contender 2.
 */
static WORKING_AREA(spi_thread_2_wa, 256);
static msg_t spi_thread_2(void *p) {

  (void)p;
  chRegSetThreadName("SPI thread 2");
  while (TRUE) {
    spiAcquireBus(&SPID2);              /* Acquire ownership of the bus.    */
    palClearPad(GPIOD, GPIOD_LED5);     /* LED OFF.                         */
    spiStart(&SPID2, &ls_spicfg);       /* Setup transfer parameters.       */
    spiSelect(&SPID2);                  /* Slave Select assertion.          */
    spiExchange(&SPID2, 512,
                txbuf, rxbuf);          /* Atomic transfer operations.      */
    spiUnselect(&SPID2);                /* Slave Select de-assertion.       */
    spiReleaseBus(&SPID2);              /* Ownership release.               */
  }
  return 0;
}

/*
 * Application entry point.
 */
int main(void) {
  unsigned i;

  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * SPI2 I/O pins setup.
   */
  palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) |
                           PAL_STM32_OSPEED_HIGHEST);       /* New SCK.     */
  palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5) |
                           PAL_STM32_OSPEED_HIGHEST);       /* New MISO.    */
  palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(5) |
                           PAL_STM32_OSPEED_HIGHEST);       /* New MOSI.    */
  palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL |
                           PAL_STM32_OSPEED_HIGHEST);       /* New CS.      */
  palSetPad(GPIOB, 12);

  /*
   * Prepare transmit pattern.
   */
  for (i = 0; i < sizeof(txbuf); i++)
    txbuf[i] = (uint8_t)i;

  /*
   * Starting the transmitter and receiver threads.
   */
  chThdCreateStatic(spi_thread_1_wa, sizeof(spi_thread_1_wa),
                    NORMALPRIO + 1, spi_thread_1, NULL);
  chThdCreateStatic(spi_thread_2_wa, sizeof(spi_thread_2_wa),
                    NORMALPRIO + 1, spi_thread_2, NULL);

  /*
   * Normal main() thread activity, in this demo it does nothing.
   */
  while (TRUE) {
    chThdSleepMilliseconds(500);
  }
  return 0;
}


This used to work.

Giovanni
User avatar
Chudik
Posts: 152
Joined: Fri Jan 16, 2015 7:51 am
Has thanked: 7 times
Been thanked: 1 time

Re: MMC_SPI shared with other multiple/devices

Post by Chudik »

Giovanni, thanks again.

There were two mistakes in my code (or may be some problems with the system)
1. palSetPadMode() works with only one pin at the time. I used some example code for lcd3310 display and it had combined group of pins. Checked the source code of it, it seemed like managing a complex mask for group of bits to be set. In reality it is not working. So, I did change my code to multiple calls of palSetPadMode().
2. I tried to use my own SPI driver based driver. Basically, just copy of the standard SPI driver with its own name. Definitely it went wrong. When I changed the name to SPID2 everything started to work. This one is definitely my own error. I think this way also should work, I just need more experience with the system.

And originally I wanted to initialize all hardware for my interface before creating a thread that will work with my display. Is it wrong way? Will the function spiSend() work if it called without creating a thread, or outside of the thread?

Now I created a thread and do all spi hardware and additonal pins initialization inside the thread. May be it is right thing anyway :-)
Post Reply