6 years, 3 months ago.

SPI.transfer and EthernetInterface mutually exclusive. Bug?

Hi there fam,

I've got what seems like a really strange bug where SPI::transfer and EthernetInterface (which I would think would be decoupled) break each other in strange ways. Here's a code snippet. Look at "@ Note {1...3}" commented lines to see what I'm talking about.

It always compiles. The issue is that at runtime either the EthernetInterface::connect call fails (does not attain IP address). Or the SPI::transfer command does not put out any data.

I think this may have to do with MBED underlying RTOS. (this build needs the 'PIO_FRAMEWORK_MBED_RTOS_PRESENT' compile flag)

I wonder if this issue is related to: https://os.mbed.com/forum/bugs-suggestions/topic/28418/

Heisen Bug

#include "mbed.h"

#include "EthernetInterface.h"
// #include <UDPSocket.h>

#define IP "10.200.1.123"
#define MASK "255.255.255.0"
#define GATEWAY "10.200.1.1"
// #define LED_FREQ 400000 // spi

#define OPC_PORT 7890

volatile int count = 1;

uint8_t firmware_version = 42;
//uint8_t mac_addr_address = 0xFA;
typedef unsigned char _enet_address[6];
_enet_address mac_addr;

SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK);
typedef struct
{
    const unsigned int start = 0;
} start_frame_t;

// a single LED frame
typedef struct
{
    unsigned char brightness;
    unsigned char blue;
    unsigned char green;
    unsigned char red;
} APARGB_t;

typedef struct
{
    const unsigned int end = 0xffffffff;
} end_frame_t;

typedef struct
{
    start_frame_t start_frame;
    APARGB_t LED_frames[LED_NUM];
    end_frame_t end_frame;
} APA_buffer_t;

APA_buffer_t sum_buf;

// @ NOTE 1: This block is mutually exclusive with runtime function of EthernetInterface
void transfer()
{
    for (int i = 0; i < LED_NUM; i++)
    {
        sum_buf.LED_frames[i].brightness = ((0x7 << 5) | LED_GLOBAL);
        sum_buf.LED_frames[i].red = (led_buf[i] & 0xff);
        sum_buf.LED_frames[i].green = ((led_buf[i] >> 8) & 0xff); // G
        sum_buf.LED_frames[i].blue = ((led_buf[i] >> 16) & 0xff); // B
    }
    spi.transfer((const void *)&sum_buf, sizeof(sum_buf), (void *)NULL, 0, bit_width, NULL, 0);
    // the following call also breaks
    //   spi.write((const char*)&sum_buf, sizeof(sum_buf), (char*)NULL, 0);

    // @ NOTE 2: I can use the following block no matter what but it is too slow for my application
    //   int i;

    //   // start frame
    //   for (i = 0; i < 4; i ++) {
    //     spi.write(0);
    //   }
    //   // led frame
    //   for (i = 0; i < LED_NUM; i ++) {
    //     spi.write((0x7 << 5) | LED_GLOBAL);
    //     spi.write(led_buf[i] & 0xff); // R
    //     // spi.write(packet.values[i].blue);
    //     spi.write((led_buf[i] >> 8) & 0xff); // G
    //     // spi.write(packet.values[i].green);
    //     spi.write((led_buf[i] >> 16) & 0xff); // B
    //     // spi.write(packet.values[i].red); // R
    //   }
    //   // end frame
    //   for (i = 0; i < 4; i ++) {
    //     spi.write(1);
    //   }
}

int main()
{
    int tswitch = 0;
    APA102_strip strip;
    strip.testStrip();

    EthernetInterface net;
    int network_status = net.set_network(IP, MASK, GATEWAY);
    if (network_status != 0)
    {
        printf("ERROR: Network Status: %d\n", network_status);
    }
    net.connect();
    const char *ip = net.get_ip_address();
    printf("IP address is: %s\n", ip ? ip : "No IP");

    while (tswitch < 7)
    {
        wait(0.05);
        if ((tswitch++) & 1)
        {
            strip.allRed();
            strip.transferStrip();
        }
        else
        {
            strip.allGreen();
            strip.transferStrip();
        }
    }

    // Open a socket on the network interface, and create a TCP connection to mbed.org
    UDPSocket socket;
    socket.open(&net);
    socket.bind(OPC_PORT); //port to use

    SocketAddress address(&net, NULL, NULL);

    // // OPC Message object
    OPC_message message;

    // @ NOTE 3: commenting or uncommenting the following line will determine whether or not SPI::transfer works at runtime
    socket.recvfrom(&address, &message.packet, sizeof message.packet);
};

Which dev board and which Mbed OS version does this occur? Any shared pins between Eth interface and SPI?

posted by Jan Jongboom 10 Jan 2018
Be the first to answer this question.