mbed API for Raspberry Pi boards.
mbedPi
This is an attempt to implement a limited number of mbed APIs for Raspberry Pi single-board computers. The project was inspired by and based on the arduPi library developed for the Arduino by Cooking Hacks .
Specifications
- Chip: Broadcom BCM2836 SoC
- Core architecture: Quad-core ARM Cortex-A7
- CPU frequency: 900 MHz
- GPU: Dual Core VideoCore IV® Multimedia Co-Processor
- Memory: 1GB LPDDR2
- Operating System: Boots from Micro SD card, running a version of the Linux operating system
- Power: Micro USB socket 5V, 2A
Connectors
- Ethernet: 10/100 BaseT Ethernet socket
- Video Output: HDMI (rev 1.3 & 1.4)
- Audio Output: 3.5mm jack, HDMI
- USB: 4 x USB 2.0 Connector
- GPIO Connector: 40-pin 2.54 mm (100 mil) expansion header: 2x20 strip providing 27 GPIO pins as well as +3.3 V, +5 V and GND supply lines
- Camera Connector: 15-pin MIPI Camera Serial Interface (CSI-2)
- JTAG: Not populated
- Display Connector: Display Serial Interface (DSI) 15 way flat flex cable connector with two data lanes and a clock lane
- Memory Card Slot: Micro SDIO
GPIO connector pinout
Information
Only the labels printed in blue/white or green/white (i.e. p3, gpio2 ...) must be used in your code. The other labels are given as information (alternate-functions, power pins, ...).
Building programs for the Raspberry Pi with mbedPi
I use Qt Creator for development, however you can use any other IDE available on the Raspberry Pi (e.g. Geany) if you like. For a quick try:
- Install Qt and the Qt Creator onto your Raspberry Pi. Then create a new "Blinky" Plain non-Qt C++ Project as follows:
- Change the main code as below:
main.cpp
#include "mbedPi.h" int main() { DigitalOut myled(p7); while(1) { myled = 1; // LED is ON wait(0.2); // 200 ms myled = 0; // LED is OFF wait(1.0); // 1 sec printf("Blink\r\n"); } }
- Copy the mbedPi.zip file into your project's folder and unzip.
- Add the mbedPi.h and mbedPi.cpp files to your project by right clicking on the "Blinky" project and then clicking on the "Add Existing Files..." option in the local menu:
- Double click on Blinky.pro to open it for editing and add new libraries by inserting a new line as follows:
- Compile the project.
- Connect an LED through a 1k resistor to pin 7 and the ground on the Raspberry Pi GPIO connector.
- Run the binary as sudo (sudo ./Blinky) and you should see the LED blinking.
- Press Ctrl+c to stop running the application.
source/Serial.cpp
- Committer:
- hudakz
- Date:
- 22 months ago
- Revision:
- 2:131555dc6fb7
- Parent:
- 1:1f2d9982fa8c
File content as of revision 2:131555dc6fb7:
#include "mbed.h" #include <stdarg.h> /** * @brief * @note * @param * @retval */ Serial::Serial() { //if((tx == gpio14) && (tx == gpio15)) { REV = getBoardRev(); serialPort = "/dev/ttyAMA0"; timeOut = 1000; //baud(9600); //} } /** * @brief * @note * @param * @retval */ void Serial::baud(int baudrate) { switch (baudrate) { case 50: speed = B50; break; case 75: speed = B75; break; case 110: speed = B110; break; case 134: speed = B134; break; case 150: speed = B150; break; case 200: speed = B200; break; case 300: speed = B300; break; case 600: speed = B600; break; case 1200: speed = B1200; break; case 1800: speed = B1800; break; case 2400: speed = B2400; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; default: speed = B230400; break; } if ((sd = open(serialPort, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) { fprintf(stderr, "Unable to open the serial port %s - \n", serialPort); exit(-1); } fcntl(sd, F_SETFL, O_RDWR); tcgetattr(sd, &options); cfmakeraw(&options); cfsetispeed(&options, speed); cfsetospeed(&options, speed); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; tcsetattr(sd, TCSANOW, &options); ioctl(sd, TIOCMGET, &status); status |= TIOCM_DTR; status |= TIOCM_RTS; ioctl(sd, TIOCMSET, &status); unistd::usleep(10000); } /** * @brief * @note * @param * @retval */ void Serial::printf(const char* format, ...) { char* buf; va_list args; va_start(args, format); vasprintf(&buf, format, args); va_end(args); unistd::write(sd, buf, strlen(buf)); free(buf); } /* Writes binary data to the serial port. This data is sent as a byte * Returns: number of bytes written */ int Serial::write(uint8_t message) { unistd::write(sd, &message, 1); return 1; } /* Writes binary data to the serial port. This data is sent as a series * of bytes * Returns: number of bytes written */ int Serial::write(const char* message) { int len = strlen(message); unistd::write(sd, &message, len); return len; } /* Writes binary data to the serial port. This data is sent as a series * of bytes placed in an buffer. It needs the length of the buffer * Returns: number of bytes written */ int Serial::write(char* message, int size) { unistd::write(sd, message, size); return size; } /** * @brief * @note * @param * @retval */ int Serial::readable() { int nbytes = 0; if (ioctl(sd, FIONREAD, &nbytes) < 0) { fprintf(stderr, "Failed to get byte count on serial.\n"); exit(-1); } return(nbytes > 0 ? 1 : 0); } /* Reads 1 byte of incoming serial data * Returns: first byte of incoming serial data available */ char Serial::read() { unistd::read(sd, &c, 1); return c; } /* Reads characters from th serial port into a buffer. The function * terminates if the determined length has been read, or it times out * Returns: number of bytes readed */ int Serial::readBytes(char message[], int size) { clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); int count; for (count = 0; count < size; count++) { if (readable()) unistd::read(sd, &message[count], 1); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); timespec t = timeDiff(time1, time2); if ((t.tv_nsec / 1000) > timeOut) break; } return count; } /* Reads characters from the serial buffer into an array. * The function terminates if the terminator character is detected, * the determined length has been read, or it times out. * Returns: number of characters read into the buffer. */ int Serial::readBytesUntil(char character, char buffer[], int length) { char lastReaded = character + 1; //Just to make lastReaded != character int count = 0; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); while (count != length && lastReaded != character) { if (readable()) unistd::read(sd, &buffer[count], 1); lastReaded = buffer[count]; count++; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); timespec t = timeDiff(time1, time2); if ((t.tv_nsec / 1000) > timeOut) break; } return count; } /** * @brief * @note * @param * @retval */ bool Serial::find(const char* target) { findUntil(target, NULL); } /* Reads data from the serial buffer until a target string of given length * or terminator string is found. * Returns: true if the target string is found, false if it times out */ bool Serial::findUntil(const char* target, const char* terminal) { int index = 0; int termIndex = 0; int targetLen = strlen(target); int termLen = strlen(terminal); char readed; timespec t; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); if (*target == 0) return true; // return true if target is a null string do { if (readable()) { unistd::read(sd, &readed, 1); if (readed != target[index]) index = 0; // reset index if any char does not match if (readed == target[index]) { if (++index >= targetLen) { // return true if all chars in the target match return true; } } if (termLen > 0 && c == terminal[termIndex]) { if (++termIndex >= termLen) return false; // return false if terminate string found before target string } else { termIndex = 0; } } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); t = timeDiff(time1, time2); } while ((t.tv_nsec / 1000) <= timeOut); return false; } /* returns the first valid (long) integer value from the current position. * initial characters that are not digits (or the minus sign) are skipped * function is terminated by the first character that is not a digit. */ long Serial::parseInt() { bool isNegative = false; long value = 0; char c; //Skip characters until a number or - sign found do { c = peek(); if (c == '-') break; if (c >= '0' && c <= '9') break; unistd::read(sd, &c, 1); // discard non-numeric } while (1); do { if (c == '-') isNegative = true; else if (c >= '0' && c <= '9') // is c a digit? value = value * 10 + c - '0'; unistd::read(sd, &c, 1); // consume the character we got with peek c = peek(); } while (c >= '0' && c <= '9'); if (isNegative) value = -value; return value; } /** * @brief * @note * @param * @retval */ float Serial::parseFloat() { boolean isNegative = false; boolean isFraction = false; long value = 0; char c; float fraction = 1.0; //Skip characters until a number or - sign found do { c = peek(); if (c == '-') break; if (c >= '0' && c <= '9') break; unistd::read(sd, &c, 1); // discard non-numeric } while (1); do { if (c == '-') isNegative = true; else if (c == '.') isFraction = true; else if (c >= '0' && c <= '9') { // is c a digit? value = value * 10 + c - '0'; if (isFraction) fraction *= 0.1; } unistd::read(sd, &c, 1); // consume the character we got with peek c = peek(); } while ((c >= '0' && c <= '9') || (c == '.' && isFraction == false)); if (isNegative) value = -value; if (isFraction) return value * fraction; else return value; } // Returns the next byte (character) of incoming serial data without removing it from the internal serial buffer. char Serial::peek() { //We obtain a pointer to FILE structure from the file descriptor sd FILE* f = fdopen(sd, "r+"); //With a pointer to FILE we can do getc and ungetc c = getc(f); ungetc(c, f); return c; } // Remove any data remaining on the serial buffer void Serial::flush() { while (readable()) { unistd::read(sd, &c, 1); } } /* Sets the maximum milliseconds to wait for serial data when using SerialPI::readBytes() * The default value is set to 1000 */ void Serial::setTimeout(long millis) { timeOut = millis; } //Closes serial communication void Serial::close() { unistd::close(sd); } /******************* * Private methods * *******************/ //Returns a timespec struct with the time elapsed between start and end timespecs timespec Serial::timeDiff(timespec start, timespec end) { timespec temp; if ((end.tv_nsec - start.tv_nsec) < 0) { temp.tv_sec = end.tv_sec - start.tv_sec - 1; temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; } else { temp.tv_sec = end.tv_sec - start.tv_sec; temp.tv_nsec = end.tv_nsec - start.tv_nsec; } return temp; }