Need help in fixing Arm Mbed C++ Program Error

On Nucleo F429ZI, Arm Mbed C++,
I need help in fixing small program I am writing please:

Program has three files: slow_fast_main.cpp, ShiftOut.h, ShiftOut.cpp

Program is giving following error;

Type X to LED ON
Type y to LED OFF

Setting to fast:


++ MbedOS Error Info ++
Error Status: 0x80010133 Code: 307 Module: 1
Error Message: Mutex: 0x20006ADC, Not allowed in ISR context
Location: 0x801CF49
Error Value: 0x20006ADC
Current Thread: main Id: 0x200064EC Entry: 0x8019D8D StackSize: 0x1000 StackMem: 0x20004F80 SP: 0x2002FEA0 
For more info, visit: https://mbed.com/s/error?error=0x80010133&tgt=NUCLEO_F429ZI
-- MbedOS Error Info --

= System will be rebooted due to a fatal error =
= Reboot count(=2) reached maximum, system will halt after rebooting =

Below are C++ files:

// slow_fast.cpp

#include "mbed.h"
#include <iostream>
#include <string>
#include <map>
#include <tuple>

#include "ShiftOut.h"

using std::map;
using std::pair;
using std::string;
using std::tuple;

typedef pair<int, int> pair_key;
typedef tuple<int, int, int> tuple_vals;
typedef map< pair<int, int>, tuple<int, int, int> > pair_tuple_map_type;


pair_tuple_map_type lookup_pins
{       // Brd, BNK, srclk, rclk, ser_data
        {   {1,0}, {(PD_13), (PD_12),  (PE_15)}     },  { {1,1}, {(PD_13), (PD_12),  (PF_13)} },
        {   {2,0}, {(PD_14), (PD_15),  (PF_14)}     },  { {2,1}, {(PD_14), (PD_15),  (PF_15)} },
};

UnbufferedSerial uartUsb(USBTX, USBRX, 115200);


void uartTask();
void onSerialRx();
void serial_str_write( const char* str );
void serial_int_write( const int x );
void show_menu();
void reset_to_slow();
void set_to_fast();

PwmOut pwm_clk();
PwmOut pwm_pulse();

DigitalOut ser0();
DigitalOut ser1();
ShiftOut reg();

int main()
{
    uartUsb.attach(&onSerialRx);

    serial_str_write("\n"); show_menu();

    while (true) {

    }
}


void onSerialRx()
{
    char chIn;
    if (uartUsb.readable())
    {
        uartUsb.read( &chIn, 1 );
        switch (chIn)
        {
            case 'x': case 'X': set_to_fast(); break;
            case 'y': case 'Y': reset_to_slow(); break;
            default: 
                    show_menu();
                break;
        }
    }
}

void reset_to_slow()
{

    serial_str_write("\n");
    serial_str_write( "Resetting to slow:\r\n" );

}

void set_to_fast()
{
    serial_str_write("\n");
    serial_str_write( "Setting to fast:\n" );

    for (const auto &lookup_row : lookup_pins)
    {
        auto key_pair = lookup_row.first;
        // auto [srclk, rclk, ser_data] = lookup_row.second;

        auto map_vals = lookup_row.second;
        static int sr = get<0>(map_vals);
        static int rc = get<1>(map_vals);
        static int s0 = get<2>(map_vals);

        serial_str_write("\n");    serial_str_write( "Sr: " );    serial_int_write(sr);  serial_str_write("\n"); 
        serial_str_write("\n");    serial_str_write( "Rc: " );    serial_int_write(rc);  serial_str_write("\n"); 
        serial_str_write("\n");    serial_str_write( "S0: " );    serial_int_write(s0);  serial_str_write("\n"); 
    }

}


void serial_int_write( const int x )
{
    char buffer[20];

    sprintf(buffer, "%d", x);
    uartUsb.write( buffer, strlen(buffer) );
}



void serial_str_write( const char* str )
{
    uartUsb.write( str, strlen(str) );
}

void show_menu()
{
    serial_str_write("\nType X to LED ON\n");
    serial_str_write("Type y to LED OFF\n");   
}



// ShiftOut.h
/*
 * Copyright 2015 Benjamin R. Moeklegaard
 *
 * 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.
*/
 
#ifndef SHIFT_H
#define SHIFT_H

#include "mbed.h"
 
//Constant for managing n-numbers of registers, Function supported (writeByte, writeBit, writeBitAtPos)
// #define REGISTER_CNT 1 
#define REGISTER_CNT 1 
/**
 *  This is a library for easy interfacing with the SN74HC595N 8-bit Shift Register.
 *  The library includes functions for writing bits, bytes and animation array to the register.
 *  The Functions are mainly based for writting 8-bits or one byte and can be moddified to work
 *  with multiple shift registers.
 *@code
 * #include "mbed.h"
 * #include "ShiftOut.h"
 * ShiftOut reg(PA_8, PA_9, PC_7, PB_6, D1);
 *
 * int main(){              
 *    while(1){
 *     reg.writeBitAtPos(3, 1);
 *     wait(2);
 *     reg.writeByte(0x30);
 *     wait(2);
 *    }
 * }@endcode
 */
 
class ShiftOut
{
public:
 
    /** Create a ShiftOut interface
      *
      * @param ser      Serial data line
      * @param srclk    Data register clock
      * @param rclk     Output register clock
      * @param oe       Output enable (Active Low)
      * @param reset    Reset line for data register (Active Low)
      * Writing Byte Example:
      * @code
      * #include "mbed.h"
      * #include "ShiftOut.h"
      *
      * ShiftOut reg(PA_8, PA_9, PC_7, PB_6, D1);
      * int main()
      * {
      *     reg.writeByte(0x00); //Writes each bit to the SN74HC595N
      *     while(1) {
      *         wait_ms(300);
      *     }
      * }
      * @endcode
      */
// Shift register pins
// pin 14 (data in), pin 11 (clock), Pin 12 (reset/latch)
ShiftOut(PinName ser, PinName srclk, PinName rclk);
// ,
//         PinName oe, PinName reset);
 
/**
 * Writes a byte to the shift register
 * @param byte   0xXX or numbers from 0-255
 */
void writeByte(unsigned char);
 
/**
 * Writes a bit to the first output on the shift register
 * @param bit   0 or 1
 */
 
void writeBit(unsigned char);
 
/**
 * Writes bits from an 2D array, with configurable delay
 * @param int array, int lines, int delay_ms 
 * writes a 2D array with n-lines with a configurable delay in ms 
 * @code
 * #include "mbed.h"
 * #include "ShiftOut.h"
 * ShiftOut reg(PA_8, PA_9, PC_7, PB_6, D1);
 *
 * int main(){
 *   int strobe[][8]= {{1,0,0,0,0,0,0,0},
 *                    {0,1,0,0,0,0,0,0},
 *                    {0,0,1,0,0,0,0,0},
 *                    {0,0,0,1,0,0,0,0},
 *                    {0,0,0,0,1,0,0,0},
 *                    {0,0,0,0,0,1,0,0},
 *                    {0,0,0,0,0,0,1,0},
 *                    {0,0,0,0,0,0,0,1}};
 *      while(1){           
 *          reg.animate(strobe, 8, 200);
 *      }
 *  }
 * @endcode
 */
 
void animate(int[][8], int, int);
 
/**
 *  Demonstrates two animation examples by using the animate function
 */
 
void animationExample(void);
 
/**
 *   Writes the desired state to the output on the shift register
 *   @param  char output, state
 */
 
void writeBitAtPos(unsigned char, bool);
 
/**
 *   Writes the corresponding array item to the output on the shift register
 *   @param  char array   writes to the output from a state array
 */
 
void writeArray(char[8]);
 
public:
void updateRegister(void);
void updateOutput(void);
void clearStateArray(void);
DigitalOut DSERIAL, SRCLK, RCLK; //, SRCLK, RESET; 
};
 
#endif

/*
A library for interfacing with the SN74HC595N Shift register.
Includes functions for writing bits, bytes, animation and bits at spesified positions.
*/

#include “mbed.h”
#include “ShiftOut.h”

#define SET_LATCH() (LATCH = 0)
#define RESET_LATCH() (LATCH = 1)

#define ENABLE_RESET() (RESET = 0)
#define DISABLE_RESET() (RESET = 1)

static char stateArr[8*REGISTER_CNT] = {0};
static bool hasChanged = false;

// Shift register pins
// pin 14 (data in), pin 11 (clock), Pin 12 (rclk/latch pulse), pin 13 (OE output enable), pin 10
// serial data line, clock, pulse, output enable (ground), reset (latch)
ShiftOut::ShiftOut(PinName ser, PinName srclk, PinName rclk) : DSERIAL(ser), SRCLK(srclk), RCLK(rclk)
{
writeByte(0x00); // Reset the values of the registers to 0
// if(RESET != NC)
// {
// DISABLE_RESET();
// }
// LATCH = 0;
// RESET = 1;
}

//Pulses the register
void ShiftOut::updateRegister(){
SRCLK = 1;
wait_us(2);
SRCLK = 0;
}
//Updates the output register
void ShiftOut::updateOutput(){
RCLK = 1;
wait_us(2);
RCLK = 0;
}
//Writes a byte to the shift register
void ShiftOut::writeByte(unsigned char byte){
hasChanged = true;
for(int i = 0; i<8*REGISTER_CNT; i++){
DSERIAL = (byte & 0x01<<i)>>i;

    updateRegister();    
} 

// updateOutput();
}

//Writes a bit to the shift register
void ShiftOut::writeBit(unsigned char bit){
DSERIAL = bit & 0x01;
updateRegister();
updateOutput();
}
//Writes multiple bits from an array to create an animation
void ShiftOut::animate(int arr[8], int lines, int delay_ms){
hasChanged = true;
for(int i = 0; i < lines; i++){
for(int j = 0; j < 8; j++){
writeBit(arr[i][j]);
}
wait_us(1000.0 * delay_ms);
}
}

void ShiftOut::animationExample(){
hasChanged = true;
int strobe[8]= {{1,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0},
{0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0},
{0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,1}};

int nightrider[18][8]= {{1,0,0,0,0,0,0,0},
                       {1,1,0,0,0,0,0,0},
                       {1,1,1,0,0,0,0,0},
                       {0,1,1,1,0,0,0,0},
                       {0,0,1,1,1,0,0,0},
                       {0,0,0,1,1,1,0,0},
                       {0,0,0,0,1,1,1,0},
                       {0,0,0,0,0,1,1,1},
                       {0,0,0,0,0,0,1,1},
                       {0,0,0,0,0,0,0,1},
                       {0,0,0,0,0,0,1,1},
                       {0,0,0,0,0,1,1,1},
                       {0,0,0,0,1,1,1,0},
                       {0,0,0,1,1,1,0,0},
                       {0,0,1,1,1,0,0,0},
                       {0,1,1,1,0,0,0,0},
                       {1,1,1,0,0,0,0,0},
                       {1,1,0,0,0,0,0,0}};
                    
    animate(nightrider, 18, 50);
    wait_us(1e6);
    animate(strobe, 8, 200);
}

void ShiftOut::writeBitAtPos(unsigned char pin, bool state){
if(hasChanged){
clearStateArray();
hasChanged = false;
}
if(pin < 8*REGISTER_CNT){
stateArr[pin] = state;
}
writeArray(stateArr);
}

void ShiftOut::writeArray(char arr[8REGISTER_CNT]){
for(int i = (8
REGISTER_CNT)-1; i >= 0; i–) {
writeBit(arr[i]);
}

}

void ShiftOut::clearStateArray(){
for(int i = 0; i < 8*REGISTER_CNT; i++){
stateArr[i] = 0;
}
}

Hello,

when you want publish a code, use ``` before and after your code.

```
//your code here
```

It is very difficult to navigate the code, can you publish it somewhere? Mbed repository or Github.

BR, Jan

Hello JohnnyK,
How to publish on Mbed repository?
Any URL link to Mbed repository steps please?

I used code quotes for each of three files, but it took code quotes for the first two files.

Thanks,

Below is the ShiftOut.cpp code

Thanks and best regards,

/*
A library for interfacing with the SN74HC595N Shift register. 
Includes functions for writing bits, bytes, animation and bits at spesified positions.
*/


#include "mbed.h"
#include "ShiftOut.h"
 
 
#define SET_LATCH() (LATCH = 0)
#define RESET_LATCH() (LATCH = 1)
 
#define ENABLE_RESET() (RESET = 0)
#define DISABLE_RESET() (RESET = 1)
 
static char stateArr[8*REGISTER_CNT] = {0};
static bool hasChanged = false;

// Shift register pins
// pin 14 (data in), pin 11 (clock), Pin 12 (rclk/latch pulse), pin 13 (OE output enable), pin 10 
// serial data line, clock, pulse, output enable (ground), reset (latch)  
ShiftOut::ShiftOut(PinName ser, PinName srclk, PinName rclk) : DSERIAL(ser), SRCLK(srclk), RCLK(rclk)
{
    writeByte(0x00); // Reset the values of the registers to 0  
//    if(RESET != NC)
//    {  
//    DISABLE_RESET();
//    }
//        LATCH = 0;
//        RESET = 1;
}
 
//Pulses the register
void ShiftOut::updateRegister(){
    SRCLK = 1;
    wait_us(2);
    SRCLK = 0;    
}
//Updates the output register
void ShiftOut::updateOutput(){
    RCLK = 1;
    wait_us(2);
    RCLK = 0;    
}
//Writes a byte to the shift register
void ShiftOut::writeByte(unsigned char byte){
    hasChanged = true;
    for(int i = 0; i<8*REGISTER_CNT; i++){
        DSERIAL = (byte & 0x01<<i)>>i;

        updateRegister();    
    } 
//    updateOutput();   
}

//Writes a bit to the shift register
void ShiftOut::writeBit(unsigned char bit){
    DSERIAL = bit & 0x01;
    updateRegister();
    updateOutput();
    } 
//Writes multiple bits from an array to create an animation
void ShiftOut::animate(int arr[][8], int lines, int delay_ms){
    hasChanged = true;
    for(int i = 0; i < lines; i++){
        for(int j = 0; j < 8; j++){
           writeBit(arr[i][j]); 
        } 
        wait_us(1000.0 * delay_ms);   
    }
}
 
void ShiftOut::animationExample(){
    hasChanged = true;
    int strobe[][8]= {{1,0,0,0,0,0,0,0},
                     {0,1,0,0,0,0,0,0},
                     {0,0,1,0,0,0,0,0},
                     {0,0,0,1,0,0,0,0},
                     {0,0,0,0,1,0,0,0},
                     {0,0,0,0,0,1,0,0},
                     {0,0,0,0,0,0,1,0},
                     {0,0,0,0,0,0,0,1}};
                     
    int nightrider[18][8]= {{1,0,0,0,0,0,0,0},
                           {1,1,0,0,0,0,0,0},
                           {1,1,1,0,0,0,0,0},
                           {0,1,1,1,0,0,0,0},
                           {0,0,1,1,1,0,0,0},
                           {0,0,0,1,1,1,0,0},
                           {0,0,0,0,1,1,1,0},
                           {0,0,0,0,0,1,1,1},
                           {0,0,0,0,0,0,1,1},
                           {0,0,0,0,0,0,0,1},
                           {0,0,0,0,0,0,1,1},
                           {0,0,0,0,0,1,1,1},
                           {0,0,0,0,1,1,1,0},
                           {0,0,0,1,1,1,0,0},
                           {0,0,1,1,1,0,0,0},
                           {0,1,1,1,0,0,0,0},
                           {1,1,1,0,0,0,0,0},
                           {1,1,0,0,0,0,0,0}};
                        
        animate(nightrider, 18, 50);
        wait_us(1e6);
        animate(strobe, 8, 200);
    }
    
void ShiftOut::writeBitAtPos(unsigned char pin, bool state){
    if(hasChanged){
        clearStateArray();
        hasChanged = false;
    } 
    if(pin < 8*REGISTER_CNT){
        stateArr[pin] = state;        
    }
    writeArray(stateArr);
}
 
void ShiftOut::writeArray(char arr[8*REGISTER_CNT]){
    for(int i = (8*REGISTER_CNT)-1; i >= 0; i--) {
        writeBit(arr[i]);
    }       
    
}
 
void ShiftOut::clearStateArray(){
    for(int i = 0; i < 8*REGISTER_CNT; i++){
        stateArr[i] = 0;
        }
    }

Following is the output of the program:

Type X to LED ON
Type y to LED OFF

Setting to fast:


++ MbedOS Error Info ++
Error Status: 0x80010133 Code: 307 Module: 1
Error Message: Mutex: 0x20006ADC, Not allowed in ISR context
Location: 0x801CF49
Error Value: 0x20006ADC
Current Thread: main Id: 0x200064EC Entry: 0x8019D8D StackSize: 0x1000 StackMem: 0x20004F80 SP: 0x2002FEA0 
For more info, visit: https://mbed.com/s/error?error=0x80010133&tgt=NUCLEO_F429ZI
-- MbedOS Error Info --

= System will be rebooted due to a fatal error =
= Reboot count(=1) reached maximum, system will halt after rebooting =


Below is the Compiler Build output:

Thanks

Your issue is done by these lines

        static int sr = get<0>(map_vals);
        static int rc = get<1>(map_vals);
        static int s0 = get<2>(map_vals);

the get function throws the error.
So you need to find an alternative or take it out of interrupt context via a thread with a flag or EventQueue

BR, Jan

Hello Johnny,

Thank you very much for the information.

I will try to find alternate way to access triple values.

Thanks a bunch again.

Best regards,

I have searched on Google about finding the values of tuple using C++ functions that do not throw exceptions and I did not find any C++ code that can return tuple values by calling non-exception-throwing functions.

I need help in making this function work please.

Thanks and best regards,

There are many choices I think.

Hiden code with EventQueue, click here for view
#include "mbed.h"
#include <iostream>
#include <string>
#include <map>
#include <tuple>

//#include "ShiftOut.h"

using std::map;
using std::pair;
using std::string;
using std::tuple;

typedef pair<int, int> pair_key;
typedef tuple<int, int, int> tuple_vals;
typedef map< pair<int, int>, tuple<int, int, int> > pair_tuple_map_type;


pair_tuple_map_type lookup_pins
{       // Brd, BNK, srclk, rclk, ser_data
        {   {1,0}, {(PD_13), (PD_12),  (PE_15)}     },  { {1,1}, {(PD_13), (PD_12),  (PF_13)} },
        {   {2,0}, {(PD_14), (PD_15),  (PF_14)}     },  { {2,1}, {(PD_14), (PD_15),  (PF_15)} },
};

UnbufferedSerial uartUsb(USBTX, USBRX, 115200);


void uartTask();
void onSerialRx();
void serial_str_write( const char* str );
void serial_int_write( const int x );
void show_menu();
void reset_to_slow();
void set_to_fast();

PwmOut pwm_clk();
PwmOut pwm_pulse();

DigitalOut ser0();
DigitalOut ser1();
//ShiftOut reg();

EventQueue *queue = mbed_event_queue();

int main()
{
    uartUsb.attach(&onSerialRx);
    serial_str_write("\n"); show_menu();

    while (true) {

    }
}


void onSerialRx()
{
    char chIn;
    if (uartUsb.readable())
    {
        uartUsb.read( &chIn, 1 );
        switch (chIn)
        {
            case 'x': case 'X': queue->call(set_to_fast); break;
            case 'y': case 'Y': reset_to_slow(); break;
            default: 
                    
                break;
        }
    }
}

void reset_to_slow()
{

    serial_str_write("\n");
    serial_str_write( "Resetting to slow:\r\n" );
    show_menu();
}

void set_to_fast()
{
    serial_str_write("\n");
    serial_str_write( "Setting to fast:\n" );

    for (const auto &lookup_row : lookup_pins)
    {
        auto key_pair = lookup_row.first;
        // auto [srclk, rclk, ser_data] = lookup_row.second;

        auto map_vals = lookup_row.second;
        static int sr = get<0>(map_vals);
        static int rc = get<1>(map_vals);
        static int s0 = get<2>(map_vals);

        serial_str_write("\n");    serial_str_write( "Sr: " );    serial_int_write(sr);  serial_str_write("\n"); 
        serial_str_write("\n");    serial_str_write( "Rc: " );    serial_int_write(rc);  serial_str_write("\n"); 
        serial_str_write("\n");    serial_str_write( "S0: " );    serial_int_write(s0);  serial_str_write("\n");
    }
    show_menu();
}


void serial_int_write( const int x )
{
    char buffer[20];

    sprintf(buffer, "%d", x);
    uartUsb.write( buffer, strlen(buffer) );
}



void serial_str_write( const char* str )
{
    uartUsb.write( str, strlen(str) );
}

void show_menu()
{
    serial_str_write("\nType X to LED ON\n");
    serial_str_write("Type y to LED OFF\n");   
}
Hiden code just with main loop, click here for view
#include "mbed.h"
#include <iostream>
#include <string>
#include <map>
#include <tuple>

//#include "ShiftOut.h"

using std::map;
using std::pair;
using std::string;
using std::tuple;

typedef pair<int, int> pair_key;
typedef tuple<int, int, int> tuple_vals;
typedef map< pair<int, int>, tuple<int, int, int> > pair_tuple_map_type;

pair_tuple_map_type lookup_pins
{       // Brd, BNK, srclk, rclk, ser_data
        {   {1,0}, {(PD_13), (PD_12),  (PE_15)}     },  { {1,1}, {(PD_13), (PD_12),  (PF_13)} },
        {   {2,0}, {(PD_14), (PD_15),  (PF_14)}     },  { {2,1}, {(PD_14), (PD_15),  (PF_15)} },
};

UnbufferedSerial uartUsb(USBTX, USBRX, 115200);

enum Speed{
    None = 0,
    Slow = 1,
    Fast = 2
};

volatile Speed speed = None;

void uartTask();
void onSerialRx();
void serial_str_write( const char* str );
void serial_int_write( const int x );
void show_menu();
void reset_to_slow();
void set_to_fast();

PwmOut pwm_clk();
PwmOut pwm_pulse();

DigitalOut ser0();
DigitalOut ser1();
//ShiftOut reg();



int main()
{
    uartUsb.attach(&onSerialRx);
    serial_str_write("\n"); show_menu();

    while (true) {
        if(speed != None){
            switch (speed)
            {
                case Slow:  reset_to_slow();    break;
                case Fast:  set_to_fast();      break;
                default:                        break;
            }
            show_menu(); 
            speed = None;
        }

    }
}



void onSerialRx()
{
    char chIn;
    if (uartUsb.readable())
    {
        uartUsb.read( &chIn, 1 );
        switch (chIn)
        {
            case 'x': case 'X': if(speed == None) speed = Fast; break;
            case 'y': case 'Y': if(speed == None) speed = Slow; break;
            default: 
                    
                break;
        }
    }
}

void reset_to_slow()
{

    serial_str_write("\n");
    serial_str_write( "Resetting to slow:\r\n" );
}

void set_to_fast()
{
    serial_str_write("\n");
    serial_str_write( "Setting to fast:\n" );

    for (const auto &lookup_row : lookup_pins)
    {
        auto key_pair = lookup_row.first;
        // auto [srclk, rclk, ser_data] = lookup_row.second;

        auto map_vals = lookup_row.second;
        static int sr = get<0>(map_vals);
        static int rc = get<1>(map_vals);
        static int s0 = get<2>(map_vals);

        serial_str_write("\n");    serial_str_write( "Sr: " );    serial_int_write(sr);  serial_str_write("\n"); 
        serial_str_write("\n");    serial_str_write( "Rc: " );    serial_int_write(rc);  serial_str_write("\n"); 
        serial_str_write("\n");    serial_str_write( "S0: " );    serial_int_write(s0);  serial_str_write("\n");
    }
}


void serial_int_write( const int x )
{
    char buffer[20];

    sprintf(buffer, "%d", x);
    uartUsb.write( buffer, strlen(buffer) );
}



void serial_str_write( const char* str )
{
    uartUsb.write( str, strlen(str) );
}

void show_menu()
{
    serial_str_write("\nType X to LED ON\n");
    serial_str_write("Type y to LED OFF\n");   
}
  • I commented out your ShiftOut part because it is not necessary for this example.
  • With EventQueue I must place the show_menu() function to another place because of right moment of display.

You will see if something inspire you

BR, Jan

1 Like

Many, many thanks JohnnyK for your excellent help.

I have changed the map values data structure to an array ( does not throw exceptions) instead of tuple data structure that throws exception) resolved the error.

typedef pair<int, int> pair_key;
using tup_type = std::array<int, 3>; // srclk, rclk, ser_data

const std::pair< pair_key, tup_type > lookup_pins[4] =
{       // Brd, BNK, srclk, rclk, ser_data
        {   {1,0}, {(PD_13), (PD_12),  (PE_15)}     },  { {1,1}, {(PD_13), (PD_12),  (PF_13)} },
        {   {2,0}, {(PD_14), (PD_15),  (PF_14)}     },  { {2,1}, {(PD_14), (PD_15),  (PF_15)} }
};

Now I have following version of the program that gives following output:

Type X to LED ON
Type Y to LED OFF

Setting to fast:
Sr: 61
Rc: 60
S0: 79
Prior to the closing curly brace of for const auto& [first,  :
Sr: 61
Rc: 60
S0: 93
Prior to the closing curly brace of for const auto& [first,  :
Sr: 62
Rc: 63
S0: 94
Prior to the closing curly brace of for const auto& [first,  :
Sr: 62
Rc: 63
S0: 95
Prior to the closing curly brace of for const auto& [first,  :


Above output is given by following program:

// slow_fast.cpp

#include "mbed.h"
#include <iostream>
#include <string>
#include <map>
#include <tuple>
#include <array>

#include "ShiftOut.h"

using std::map;
using std::pair;
using std::string;
using std::tuple;

typedef pair<int, int> pair_key;
using tup_type = std::array<int, 3>; // srclk, rclk, ser_data

const std::pair< pair_key, tup_type > lookup_pins[4] =
{       // Brd, BNK, srclk, rclk, ser_data
        {   {1,0}, {(PD_13), (PD_12),  (PE_15)}     },  { {1,1}, {(PD_13), (PD_12),  (PF_13)} },
        {   {2,0}, {(PD_14), (PD_15),  (PF_14)}     },  { {2,1}, {(PD_14), (PD_15),  (PF_15)} }
};

/*
typedef tuple<int, int, int> tuple_vals;
typedef map< pair<int, int>, tuple<int, int, int> > pair_tuple_map_type;


pair_tuple_map_type lookup_pins
{       // Brd, BNK, srclk, rclk, ser_data
        {   {1,0}, {(PD_13), (PD_12),  (PE_15)}     },  { {1,1}, {(PD_13), (PD_12),  (PF_13)} },
        {   {2,0}, {(PD_14), (PD_15),  (PF_14)}     },  { {2,1}, {(PD_14), (PD_15),  (PF_15)} },
};
*/

UnbufferedSerial uartUsb(USBTX, USBRX, 115200);

void uartTask();
void onSerialRx();
void serial_str_write( const char* str );
void serial_int_write( const int x );
void show_menu();
void reset_to_slow();
void set_to_fast();

/*
PwmOut pwm_clk();
PwmOut pwm_pulse();

DigitalOut ser0();
DigitalOut ser1();
ShiftOut reg();
*/

int main()
{
    uartUsb.attach(&onSerialRx);

    serial_str_write("\n"); show_menu();

    while (true) {

    }
}

void onSerialRx()
{
    char chIn;
    if (uartUsb.readable())
    {
        uartUsb.read( &chIn, 1 );
        switch (chIn)
        {
            case 'x': case 'X': set_to_fast(); break;
            case 'y': case 'Y': reset_to_slow(); break;
            default: 
                    show_menu();
                break;
        }
    }
}

void reset_to_slow()
{

    serial_str_write("\n");
    serial_str_write( "Resetting to slow:\r\n" );

}

void set_to_fast()
{
    serial_str_write("\n");
    serial_str_write( "Setting to fast:\n" );

    int sr, rc, s0;

    for (const auto& [first, second] : lookup_pins)
    {
        const auto [Brd, Bnk] = first;

        const auto [sr, rc, s0] = second;

/*
        static PwmOut pwm_clk(sr);
        static PwmOut pwm_pulse(rc);

        static DigitalOut ser(s0);

        // ShiftOut(PinName ser, PinName srclk, PinName rclk);
        static ShiftOut reg(s0, sr, rc);
*/

        // serial_str_write("\n");    
        serial_str_write( "Sr: " );    serial_int_write(sr);  serial_str_write("\n"); 
        //serial_str_write("\n");    
        serial_str_write( "Rc: " );    serial_int_write(rc);  serial_str_write("\n"); 
        //serial_str_write("\n");    
        serial_str_write( "S0: " );    serial_int_write(s0);  serial_str_write("\n"); 

        // serial_str_write("\n");

/*
        pwm_pulse.period(0.1f); // 0.1 second period or 1/0.1 = 10 Hz frequency
        pwm_pulse.pulsewidth_ms(1.0f); // pulse width 1 milli second

        for (int i = 0; i < 5; i++)
        {
            reg.writeByte(0xFF);
            wait_us(20000.0);
        }  

        reg.updateOutput();
        wait_us(20000.0);
*/
        serial_str_write( "Prior to the closing curly brace of for const auto& [first,  :\n" );
    }

}


void serial_int_write( const int x )
{
    char buffer[20];

    sprintf(buffer, "%d", x);
    uartUsb.write( buffer, strlen(buffer) );
}



void serial_str_write( const char* str )
{
    uartUsb.write( str, strlen(str) );
}

void show_menu()
{
    serial_str_write("\nType X to LED ON\n");
    serial_str_write("Type Y to LED OFF\n");   
}

In the above program I need to uncomment following two groups of lines of code in function set_to_fast:

        static PwmOut pwm_clk(sr);
        static PwmOut pwm_pulse(rc);

        static DigitalOut ser(s0);

        // ShiftOut(PinName ser, PinName srclk, PinName rclk);
        static ShiftOut reg(s0, sr, rc);


        pwm_pulse.period(0.1f); // 0.1 second period or 1/0.1 = 10 Hz frequency
        pwm_pulse.pulsewidth_ms(1.0f); // pulse width 1 milli second

        for (int i = 0; i < 5; i++)
        {
            reg.writeByte(0xFF);
            wait_us(20000.0);
        }  

        reg.updateOutput();
        wait_us(20000.0);




type or paste code here

But following lines are giving compile errors as shown on the following image of screen capture:

code_lines_01a

How to fix the above compile errors shown on the screen captured code lines of set_to_fast() function, please?

Thanks and best regards,

Easy. PwmOut requres parametr pin of type PinName - Pins are normal 32 bit integer, but in Mbed it has a self type - PinName.
So you can use it like below

static PwmOut pwm_clk((PinName)sr);

or you can try change data type of your array.

Ad to previous part

I did not recommended another type of container because I do not know background.
Of course it can be done with only simple array and also directly with type of PinNames.

const PinName lookup_pins_test[4][3] = {
        {(PD_13), (PD_12),  (PE_15)}, {(PD_13), (PD_12),  (PF_13)},
        {(PD_14), (PD_15),  (PF_14)}, {(PD_14), (PD_15),  (PF_15)}
};

and use enums for more clear movement through

enum MyPin{
    Srclk = 0,
    Rclk,
    Ser_data
};
enum Option{
    Option1 = 0,
    Option2,
    Option3,
    Option4 
};

You can also create your own custom made struct

struct MyPinSettings{
    PinName srclk;
    PinName rclk;
    PinName ser_data;
};

MyPinSettings lookup_pins[4] = {
    {(PD_13), (PD_12),  (PE_15)}, {(PD_13), (PD_12),  (PF_13)},
    {(PD_14), (PD_15),  (PF_14)}, {(PD_14), (PD_15),  (PF_15)}
};

How I said, there are many options, but with these you not need include another code like - map.h, tuple.h and so on.

BR, Jan

Hello JohnnyK,
Many, many thanks for your fantastic help and suggestions.
I will work using your suggestions.
Again many thanks and best regards,

Hi JonnnyK,
Using your excellent help I have compiled the following function:

void set_to_fast()
{
    serial_str_write("\n");
    serial_str_write( "Setting to fast:\n" );

    int sr, rc, s0;

    for (const auto& [first, second] : lookup_pins)
    {
        const auto [Brd, Bnk] = first;

        const auto [sr, rc, s0] = second;


        static PwmOut pwm_clk((PinName)sr);
        static PwmOut pwm_pulse((PinName)rc);

        static DigitalOut ser((PinName)s0);

        // ShiftOut(PinName ser, PinName srclk, PinName rclk);
        static ShiftOut reg((PinName)s0, (PinName)sr, (PinName)rc);

        // serial_str_write("\n");    
        serial_str_write( "Sr: " );    serial_int_write(sr);  serial_str_write("\n"); 
        //serial_str_write("\n");    
        serial_str_write( "Rc: " );    serial_int_write(rc);  serial_str_write("\n"); 
        //serial_str_write("\n");    
        serial_str_write( "S0: " );    serial_int_write(s0);  serial_str_write("\n"); 

        // serial_str_write("\n");

        pwm_clk.period(0.1f); // 0.1 second period or 1/0.1 = 10 Hz frequency
    // pwm_out_clk.period(2.0f); // 2 seconds period or 1/2 = 0.5 Hz frequency
        pwm_clk.write(0.50f); // duty cycle 0.5 or 50% or 1 second

        pwm_pulse.period(0.1f); // 0.1 second period or 1/0.1 = 10 Hz frequency
        pwm_pulse.pulsewidth_ms(1.0f); // pulse width 1 milli second

        for (int i = 0; i < 5; i++)
        {
            reg.writeByte(0xFF);
            wait_us(20000.0);
        }  

        reg.updateOutput();
        wait_us(20000.0);

        serial_str_write( "Prior to the closing curly brace of for const auto& [first,  :\n" );
    }

}

However, above function is crashing with the following error:

Type X to LED ON
Type Y to LED OFF

Setting to fast:


++ MbedOS Error Info ++
Error Status: 0x80010133 Code: 307 Module: 1
Error Message: Mutex: 0x20006BD4, Not allowed in ISR context
Location: 0x801D91D
Error Value: 0x20006BD4
Current Thread: main Id: 0x200065E0 Entry: 0x801A139 StackSize: 0x1000 StackMem: 0x20005080 SP: 0x2002FE90 
For more info, visit: https://mbed.com/s/error?error=0x80010133&tgt=NUCLEO_F429ZI
-- MbedOS Error Info --

= System will be rebooted due to a fatal error =
= Reboot count(=2) reached maximum, system will halt after rebooting =

It is crashing on this code line:

       static PwmOut pwm_clk((PinName)sr);

How to fix this set_to_fast function’s crash please?

Unless you do not plan to use anything from the RTOS, which include the mutex, then you can try a bare metal profile. The Bare metal profile = no RTOS = no Mutex = no crash about the Mutex. In a list on Full API list you can find what APIs are available under the Bare metal profile.
Another option is what I already wrote above, You must move the processing of that code part out of interrupt context - my first example with the Hiden code with EventQueue above.

Actually I am not sure about how you did it in general, but I am not software engineer, so take it as tips.
When we look to your whole program, there si nothing what is running in the main thread and all tasks are processed in interrupt context. This is not good practice, not recommended. The interruption should be as short as possible for many reasons, that means, do only necessary things inside the interrupt - my second example Hiden code just with main loop above.

BR, Jan