6 years 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
NEW 6 years ago
There is a Benchmark: http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/
and also this https://www.raspberrypi.org/forums/viewtopic.php?t=26907
Maybe this can help you.
NEW 6 years 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 >.<
ripper121
6 years 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
NEW 6 years 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