Attempting to sniff the SPI bus

General

Sorunome

10 months ago

So.....I'm attempting to sniff the SPI bus for a possible HDMI out using a raspberry pi.....the problem is, that my code only works well for clock speeds up to 2MHz, and our display is clocked at 24MHz. I thought maybe one of you has more experience with the raspberry pi and its GPIOs, as this is literally the first time i worked with that!

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */


int  mem_fd;
void *gpio_map;

// I/O access
volatile unsigned *gpio;


// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))

#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0

#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH

#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock

void setup_io();

const int pin_clock = 11;
const int pin_input = 9;

const int frame_threashold = 107058;

typedef unsigned char BYTE;

BYTE get_byte() {
        BYTE b = 0;
        int i;
        for (i = 0; i < 8; i++) {
                while(!GET_GPIO(pin_clock));
                b <<= 1;
                b |= (GET_GPIO(pin_input)?1:0);
                while(GET_GPIO(pin_clock));
        }
        return b;
}

void find_start() {
        int max = 0;
        while(!GET_GPIO(pin_clock));
        while(GET_GPIO(pin_clock));
        unsigned start_time = (unsigned)time(NULL);
        int i;
        do {
                i = 0;
                while(!GET_GPIO(pin_clock))i++;
                if (i > max) max = i;
                while(GET_GPIO(pin_clock));
        } while (start_time + 2 >= (unsigned)time(NULL));
        max -= (max/10);

        do {
                i = 0;
                while(!GET_GPIO(pin_clock))i++;
                while(GET_GPIO(pin_clock));
        } while (i < max);
        for (i = 0; i < 7; i++) { // read the remaining byte
                while(!GET_GPIO(pin_clock));
                while(GET_GPIO(pin_clock));
        }
}

int main(int argc, char **argv) {
        setup_io();

        INP_GPIO(pin_input);
        INP_GPIO(pin_clock);

        find_start();

        BYTE data[10];
/*
        while(1) {
                if(get_byte() != 0x2A) continue;
                if (get_byte() != 0) continue;
                if (get_byte() != (160-1)) continue;
                data[0] = 0x2A;
                data[1] = 0;
                data[2] = 160-1;
                break;
        }
*/
        int i;
        for (i = 0; i < 10; i++) {
                data[i] = get_byte();
        }

        for (i = 0; i < 10; i++) {
                printf("%02x ", data[i]);
        }
        printf("\n");
        return 0;
}

void setup_io() {
        if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
                printf("can't open /dev/mem \n");
                exit(-1);
        }

        /* mmap GPIO */
        gpio_map = mmap(
                NULL,             //Any adddress in our space will do
                BLOCK_SIZE,       //Map length
                PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
                MAP_SHARED,       //Shared with other processes
                mem_fd,           //File to map
                GPIO_BASE         //Offset to GPIO peripheral
        );

        close(mem_fd); //No need to keep mem_fd open after mmap

        if (gpio_map == MAP_FAILED) {
                printf("mmap error %d\n", (int)gpio_map);//errno also set!
                exit(-1);
        }

        // Always use volatile pointer!
        gpio = (volatile unsigned *)gpio_map;
}


find_start is for finding the start of a byte, as what if we start the program in the middle of a byte being sent? It is based on that on some byte eventually there will be a longer pause than between bytes, which is true, as we aren't using the SPI bus 100% of the time in any sketches.

As test sketch i used the following with the METAs library custom yeild function disabled (as that would cause delay() to sometimes do SPI stuff):

#include <Gamebuino-Meta.h>

static SPISettings mySPISettings;

void setup() {
    gb.begin();
    mySPISettings = SPISettings(2000000, MSBFIRST, SPI_MODE0);
    SPI.beginTransaction(mySPISettings);
    while(1) {
        SPI.transfer(0x12);
        SPI.transfer(0x34);
        delay(1);
    }
    SPI.endTransaction();
}

void loop() {
    
}


So yeah, as I already said, I'm basically stuck currently as the receiving part on the raspberry pi only works well up to 2MHz but the screen is at 24MHz

ripper121

NEW 10 months ago

Sorunome

10 months ago

Thank you for the links, i'll look more into it once i have time. Me having a gen 1 raspberry pi probably doesn't help this, then >.<

Sorunome

NEW 10 months ago

ripper121 ripper121

Thank you for the links, i'll look more into it once i have time. Me having a gen 1 raspberry pi probably doesn't help this, then >.<

ripper121

10 months ago

But I dont think you need to use SoftSPI, the HW spi goes up to 125MHz:

 cdiv    speed

    2      125.0 MHz

https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md

ripper121

NEW 10 months ago

Sorunome Sorunome

But I dont think you need to use SoftSPI, the HW spi goes up to 125MHz:

 cdiv    speed

    2      125.0 MHz

https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md

You must be logged in in order to post a message on the forum

Log in