Gehard, thank you very much!

Considering the code you've provided, I understand that:

   -  I need these header files:


#include <sys/types.h>      
#include <stdio.h>           
#include <stdlib.h>          
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "ltcsrv.h"
#include "pru_if.h"


   - A file descriptor must be used for /dev/mem:


int dev_mem_fd;
dev_mem_fd = open("/dev/mem",O_RDWR | O_SYNC);


   - Shared RAM is mapped (prepared for use) by this line:


 shared_ram = (int *) mmap(NULL, 12*1024, PROT_READ | PROT_WRITE, 
MAP_SHARED, dev_mem_fd, 0x4A300000 + 0x10000);


   - Here follows examples of usage (in this case, writing to shared ram 
   memory): 


 shared_ram[0] = ...   ; //write to 0x4A310000
 shared_ram[1] = ...   ; //write to 0x4A310004
 shared_ram[1] = ...   ; //write to 0x4A310008

Am I right?

Regarding header files, I noticed the pru related headerfile has been 
included as #include "pru_if.h". Is it a local file from your project or a 
header file referred to a lib? In case of being referred to a lib, it could 
be included as #include <pru_if.h>, right?


Best Regards,
Pedro Bertoleti

Em segunda-feira, 18 de janeiro de 2021 às 02:03:13 UTC-3, 
g...@hoffmann-hochfrequenz.de escreveu:

>
> Am 18.01.21 um 04:03 schrieb phfbertoleti:
> > I'll write the newest iamge on my BBGW. I think after that everything 
> > will back to normal.
> >
> > Regarding PRUs, I think you can answer me the following: I was able to 
> > write data succesfully to shared data segment using PRU0, to confirm 
> > I've checked memory using devmem2. However, I'm not so sure on how I 
> > can read it from host (Linux) side, once Linux side uses virtual 
> > memory (= no physical memory address are referred there, per my 
> > understanding).
> >
> > How do you recommend me to read (or write) data to shared memory from 
> > host (Linux) side in C? Is there any special library for this? I 
> > assume this is the easiest (maybe the only, as I've understood so far) 
> > way to communicate Linux side and PRUs side.
>
> I have mostly made a FFT analyzer from a BBB. There are up to 3 LTC2500 
> ADCs sampling analog
>
> data at 1MSPS, 32 Bits per sample. I got my Agilent 89441A back to work, 
> therefore this here is idle
>
> for >> 1 year.  I started that with PRU0, but PRU1 has more usable pins.
>
>
> PRU 1 was reading the data with the help of an external CPLD that 
> converted SPI to Bytes since even
>
> the PRU could not read SPI at 3*100 MBit. There is a 12 KB dual port 
> buffer somewhere accessible to
>
> both the ARM and the PRU. The lowest words of the buffer make a 
> command/status interface between
>
> ARM and PRU (command, status, 3 parameters, 3 test results, etc). The 
> rest of the buffer is used to
>
> transfer long  time series to the ARM in a ping-pong way. (The way I 
> used it.)
>
>
> The shared buffer has a fixed address on the PRU side, and also on the 
> ARM side. You cannot use
>
> this address in your ARM program but you can mmap() it into the virtual 
> memory space of the ARM.
>
> That is a standard system call.
>
>
> The following source code was not meant for publication, it is 
> half-done. Don't hit me too hard.
>
> But the access to the shared ram works from both sides, this here is the 
> ARM side.
>
> It seems you have the PRU side already. What you need is probably 
> openpru().
>
> Sorry for the semi-German in the source.
>
>
> regards, Gerhard
>
>
>
>
>
>
> -----------------------------------------------
>
> // pru_if.h
> //
> // extern int         init_spi_pins(void);
>
> extern int         open_pru(void);
> extern int         close_pru(void);
> extern void     run_pru_cmnd( int pru_argc, char **pru_argv);
> extern int         do_aquisition_cmnd( int n_samples);
>
> #define ADC_BUFFER_SIZE (32*1024)
> extern int         adc_buffer[ADC_BUFFER_SIZE];
>
> -----------------------------------------------
>
> pru_if.c
>
>
> #include <sys/types.h>        /* type definitions used by many programs */
> #include <stdio.h>            /* standard IO functions */
> #include <stdlib.h>            /* commonly used functions, EXIT_SUCCESS 
> and EXIT_FAILURE */
> #include <errno.h>
> #include <string.h>
> #include <math.h>
> #include <sys/time.h>        /* setitimer(2)  and getitimer(2)  */
> #include <unistd.h>
> #include <fcntl.h>
> #include <sys/mman.h>
>
> #include <unistd.h>            /* for nice system call */
>
> #include "ltcsrv.h"            /* for panic() */
> #include "pru_if.h"            /* to enforce consistency with .c */
>
> #include "cmnd_stat_codes.h"
>
>
> int adc_buffer[ADC_BUFFER_SIZE];
>
>
> int                dev_mem_fd;
> volatile int    *shared_ram;
> volatile int    *pru_ram;            // the 8 KB local data = 2 KWORDS
>
> int                cmnd_to_send;
>
>
> int init_BBB_pins(){
>
>     // printf("initializing pins for SPI and PRU\n");
>     // 2> stderr umleiten   &> stdout und stderr umleiten
>     system("/bin/rm -f spitest.log");
>
>     // this here worked from bash, never change a winning team.
>     if (system("/usr/bin/config-pin  p8.45 pruin  2> spitest.log")) 
> return 1;    // PRU1.0      q0
>     if (system("/usr/bin/config-pin  p8.46 pruin  2> spitest.log")) 
> return 1;    // PRU1.1      q1
>     if (system("/usr/bin/config-pin  p8.43 pruin  2> spitest.log")) 
> return 1;    // PRU1.2      q2
>     if (system("/usr/bin/config-pin  p8.44 pruin  2> spitest.log")) 
> return 1;    // PRU1.3      q3
>     if (system("/usr/bin/config-pin  p8.41 pruin  2> spitest.log")) 
> return 1;    // PRU1.4      q4
>     if (system("/usr/bin/config-pin  p8.42 pruin  2> spitest.log")) 
> return 1;    // PRU1.5      q5
>     if (system("/usr/bin/config-pin  p8.39 pruin  2> spitest.log")) 
> return 1;    // PRU1.6      q6
>     if (system("/usr/bin/config-pin  p8.40 pruin  2> spitest.log")) 
> return 1;    // PRU1.7      q7
>
>     if (system("/usr/bin/config-pin  p8.27 pruout 2> spitest.log")) 
> return 1;    // PRU1.8      qsel0       cpld.19 könnte auch zusätzlich 
> SDI sein
>     if (system("/usr/bin/config-pin  p8.29 pruout 2> spitest.log")) 
> return 1;    // PRU1.9      qsel1       cpld.16
>     if (system("/usr/bin/config-pin  p8.28 pruout 2> spitest.log")) 
> return 1;    // PRU1.10     prog_clk    cpld.36
>     if (system("/usr/bin/config-pin  p8.30 pruout 2> spitest.log")) 
> return 1;    // PRU1.11     prog_data / sdi
>
>     if (system("/usr/bin/config-pin  p9.26 pruin  2> spitest.log")) 
> return 1;    // PRU1.16_in  data available from CPLD.12 ( Busy or DRL, 
> depending chan B/A)
>     if (system("/usr/bin/config-pin  p9.22 out    2> spitest.log")) 
> return 1;    // GPIO0.2     prog_ena    cpld.39
>     if (system("/usr/bin/config-pin  p9.18 out    2> spitest.log")) 
> return 1;    // GPIO0.4     use_chan_b  cpld.8
>     // printf("done with initializing pins.\n");
>     return 0;
> }
>
>
>
> void copy_shared_ram_to_file(char *fn){
>
>     FILE * phyle;
>     int i, j;
>
>     phyle = fopen(fn, "w");        // FIXME return value
>     fprintf(phyle, "%s\n", fn);
>     fprintf(phyle, "byte index dec byte index hex  word index 
> content\n\n");
>     for (i=0; i< 3*1024; i++){   // 12 KB are 3 Kwords
>         fprintf(phyle, "\n%12d   %8x   %8x  = 0x%8x    %12d", 4*i, 4*i, 
> i, shared_ram[i], shared_ram[i]);
>         switch(i){
>             case 0:                fprintf(phyle, "  unused"); break;
>             case COMMAND:        fprintf(phyle, "  command"); break;
>             case STATUS:        fprintf(phyle, "  status"); break;
>             case PARAM1:        fprintf(phyle, "  param1"); break;
>             case PARAM2:        fprintf(phyle, "  param2"); break;
>             case PARAM3:        fprintf(phyle, "  param3"); break;
>             case TEST1:            fprintf(phyle, "  test1"); break;
>             case TEST2:            fprintf(phyle, "  test2"); break;
>             case TEST3:            fprintf(phyle, "  test3"); break;
>             case PING_FULL:        fprintf(phyle, "  ping_full"); break;
>             case PONG_FULL:        fprintf(phyle, "  pong_full"); break;
>             case PING:            fprintf(phyle, "  ping buffer 
> start"); break;
>             case PONG:            fprintf(phyle, "  pong buffer 
> start"); break;
>         }
>     }
>     fclose(phyle);      // FIXME return value
>
> }
>
>
> void copy_pru_ram_to_file(char *fn){
>     FILE * phyle;
>     int i, j;
>     phyle = fopen(fn, "w");        // FIXME return value
>     fprintf(phyle, "%s\n", fn);
>     fprintf(phyle, "byte index  word index  content   all hex\n\n");
>     fprintf(phyle, "stack lowest and data nil pointer\n");
>     for (i=0; i< 4*1024; i++){   // 2 * 8 KB are 4 Kwords
>         if      (0x100/4 == i)    { fprintf(phyle, "\nstack highest - 
> heap lowest\n"); }
>         else if (0x200/4 == i)    { fprintf(phyle, "\nheap highest\n"); }
>         fprintf(phyle, "%8x   %8x = %8x\n", 4*i, i, pru_ram[i]);
>     }
>     fclose(phyle);      // FIXME return value
> }
>
>
>
> void display_cmnd( int cmnd){
>     printf(" <%c> %d = ", cmnd, cmnd);
>     switch (cmnd){
>         case CMND_NONE:                printf("none\n"); break;
>         case CMND_HALT:                printf("halt\n"); break;
>         case CMND_BLINK_FAST:        printf("blink fast\n"); break;
>         case CMND_BLINK_SLOWLY:        printf("blink slowly\n"); break;
>         case CMND_CHAN:                printf("Channel select 1=B\n"); 
> break;
>         case CMND_INIT_ADC:            printf("init ADC\n"); break;
>         case CMND_START_AQUISITION: printf("start_aquisition\n"); break;
>         case CMND_CLEAR_RAM:        printf("wipe out the rams\n"); break;
>         case CMND_XMIT_WORD:        printf("xmit word via spi\n"); break;
>         case CMND_TEST:                printf("test\n"); break;
>         case CMND_WRITE_ADDRESS:    printf("write address\n"); break;
>         case CMND_READ_ADDRESS:        printf("read address\n"); break;
>         case CMND_UIUIUI:            printf("uiuiui\n"); break;
>         case CMND_READ_ADC:            printf("read ADC\n"); break;
>         default:                    printf("????\n");
>     }
> }  // display_cmnd()
>
>
> // %i matches 0XABC 0xabc as hex , 0777 as oct, the rest in decimal
> // octal may come as a surprise! I still love the PDP-11.
> // %i funktioniert irgendwie nicht mit großen Zahlen wie 0xDEADBEEF, da 
> kommt 7fff ffff raus.
> // so we do it without %i  and without octal.
>
> int num_to_int(const char *s){
>
>     int result;
>     if ((*s == '0') && (*(s+1) == 'x')){ // *s+1 kann das Null-byte sein!
>         sscanf(s, "%x", &result);
>     } else {
>         sscanf(s, "%d", &result);
>     }
> //    sscanf(s, "%i", &result);
>     return result;
> }
>
>
> // display status cannot have the state as param since it must do busy 
> waiting.
>
> void display_status(){
>
>     if (shared_ram[STATUS] == STAT_BUSY){
>         printf("PRU program is Busy. Waiting...\n");
>         while (shared_ram[STATUS] == STAT_BUSY){};
>     }
>
>     printf("status = %08x = ", shared_ram[STATUS]);
>     switch (shared_ram[STATUS]){
>         case STAT_CLEARED:        printf("cleared"); break;
>         case STAT_RDY_FOR_CMND:    printf("ready for command"); break;
>         case STAT_INITIALIZING:    printf("initializing"); break;
>         case STAT_BUSY:            printf("busy"); break;
>         default:                printf("stat_unknown");
>     }
>
>     printf("error = %08x = ", shared_ram[ERRCODE]);
>     switch (shared_ram[ERRCODE]){
>         case ERR_NONE:                printf("none\n"); break;
>         case ERR_HALTED:            printf("halted\n"); break;
>         case ERR_BAD_CMND:            printf("bad command\n"); break;
>         case ERR_BAD_PARAM:            printf("bad parameter\n"); break;
>         case ERR_PIPO_OVERRUN:        printf("ping pong buffer 
> overflow\n"); break;
>         case ERR_SPI_OVERRUN:        printf("SPI overrun\n"); break;
> //        case ERR_UNEXPECTED_BUSY:    printf("unexpected busy\n"); break;
>         default:                    printf("error_unknown\n");
>     }
>
> }  // display_status()
>
>
> // this is now the aquisition command for the client command interpreter.
> // Nevertheless it can return PRU error codes.
> // TODO analoge Vcc überwachen, Timeout einbauen
>
> int do_aquisition_cmnd( int n_samples){
>
>     // FILE * phyle;
>     int i;
>     int *adc_buf_p;                // pointer into adc buffer for data 
> collection
>     volatile int * ppp;            // ping pong pointer
>     int words_transferred;
>
>     printf("do aqu - on entry %d n_samples\n", n_samples);
>
>
>     adc_buf_p             = adc_buffer;    // destination in ARM RAM
>     words_transferred    = 0;
>     // should not be busy when we start aquisition. cannot happen, really.
>     if (shared_ram[STATUS] != STAT_RDY_FOR_CMND){
>         return shared_ram[ERRCODE];
>     }
>
>     // That can be timelimited by setitimer(2) and getitimer(2),
>     // avoid checking faster for done than PRU notes that it has work to do
>     // den Sinn sehe ich gerade nicht ein  FIXME 
> ?????????????????????????????????????????????????
>     shared_ram[STATUS]  = STAT_CLEARED;
>
>
>     shared_ram[PARAM1]  = compose_adc_ctl();    // 1 word from SCPI options
>     shared_ram[COMMAND] = CMND_INIT_ADC;
>     // Wait util PRU is done with initializing the ADC.
>     // FIXME  can take forever if ADC has no power or clock
>     while (shared_ram[STATUS] != STAT_RDY_FOR_CMND){};
>
>
>     shared_ram[PARAM1]  = use_chan_b;            // Set 1 MSPS or 
> decimated output
>     shared_ram[COMMAND] = CMND_CHAN;
>     while (shared_ram[STATUS] != STAT_RDY_FOR_CMND){};
>
>     printf("\nentering nice mode - starting aquisition n_samples = 
> %d\n, n_samples");
>     nice (-19);
>
>     shared_ram[STATUS]  = STAT_CLEARED;
>     shared_ram[PARAM1]    = n_samples;
>     shared_ram[COMMAND] = CMND_START_AQUISITION;
>
>     while (    words_transferred <= n_samples) {
>
>         if (shared_ram[PING_FULL] = 1){
>             printf("i");
>             ppp = & shared_ram[PING];        // + 0x400
>             i = 1024;
>             while (i--){
>                 *adc_buf_p++ = *ppp++;
>             }
>             shared_ram[PING_FULL] = 0;    // we got the contents, can 
> now be re-used
>             words_transferred += 1024;
>
>         } // ping buffer full
>
>         if (shared_ram[PONG_FULL] = 1){
>             printf("o");
>             ppp = & shared_ram[PONG];        // + 0x800
>             i = 1024;
>             while (i--){
>                 *adc_buf_p++ = 48;    //  FIXME *ppp++;
>             }
>             shared_ram[PONG_FULL] = 0;    // we got the contents, can 
> now be re-used
>             words_transferred += 1024;
>
>         } // pong buffer full
>
>     } // while()
>
>     nice(0);
>     printf ("     transferred %d words\n", words_transferred );
>     if ( ERR_PIPO_OVERRUN == shared_ram[STATUS]) return ERR_PIPO_OVERRUN;
>     if ( ERR_SPI_OVERRUN  == shared_ram[STATUS]) return 
> ERR_SPI_OVERRUN;    // cannot happen now.
>
>
>
>     phyle = fopen("adc_result.txt", "w");        // FIXME return value
>     fprintf(phyle, "word index  content\n\n");
>     for (i=0; i< words_transferred; i++){   // 12 KB are 3 Kwords
>         fprintf(phyle, "%12d  0x%8x = %8x  %12d\n", i, i, 
> adc_buffer[i], adc_buffer[i]);
>     }
>     fclose(phyle);      // FIXME return value
>
>     return 0;
> }  // do_aquisition_cmnd()
>
>
>
> int pr_val(unsigned u, unsigned bit){
>     return (u & (1<<bit) ? '1' : '0');
> }
>
>
> // some commands may need some postprocessing to display meaningful 
> results etc
>
> void command_postprocessing(){
>
>     // int t1, t2, t3;
>
>     if (cmnd_to_send == CMND_START_AQUISITION) {    // that must go 
> fast now. No inspection by hand.
>         printf("\npostprocessing aquisition command\n");
>         do_aquisition_cmnd(32000);
>
>     } else if ( cmnd_to_send == CMND_WRITE_ADDRESS){
>         printf("\nPRU data space at 0x%08x written with 0x%08x check 
> read = 0x%08x\n",
>                     shared_ram[PARAM1], shared_ram[PARAM2], 
> shared_ram[PARAM3]);
>
>     } else if ( cmnd_to_send == CMND_READ_ADDRESS) {
>         printf("\nPRU data space 0x%08x reads  0x%08x    dec %d\n",
>                     shared_ram[PARAM1], shared_ram[PARAM3], 
> shared_ram[PARAM3]);
>         //decode_some_registers(shared_ram[PARAM1], shared_ram[PARAM3]);
>     }
> }
>
>
> void disp_shared_ram_state(){
>     //printf("share0 = %10d 0x%08x\n",    shared_ram[0     ], 
> shared_ram[0     ] );
>     printf("param1 = %12d 0x%08x",    shared_ram[PARAM1], 
> shared_ram[PARAM1] );
>     printf("      test1  = %12d 0x%08x\n", shared_ram[TEST1], 
> shared_ram[TEST1] );
>     printf("param2 = %12d 0x%08x",    shared_ram[PARAM2], 
> shared_ram[PARAM2] );
>     printf("      test2  = %12d 0x%08x\n", shared_ram[TEST2], 
> shared_ram[TEST2] );
>     printf("param3 = %12d 0x%08x",    shared_ram[PARAM3], 
> shared_ram[PARAM3] );
>     printf("      test3  = %12d 0x%08x\n", shared_ram[TEST3], 
> shared_ram[TEST3] );
> }
>
>
> // when there are arguments given to the ltcsrv, they are commands for 
> the pru and up to 3 parameters
> // Just numbers. pass them on to the PRU and display the results.
>
> void run_pru_cmnd( int argc, char *argv[]){
>
>     int i;
>     // printf("entered run_pru_cmnd()\n");
>     // printf("\nStatus before running PRU command: "); // Cannot be 
> done later b/c we might change params for
>                                                     // a prog that 
> still might run.
>     // display_status();                            // this will wait 
> until PRU program is no longer busy.
>     if (shared_ram[STATUS] == STAT_BUSY){
>         printf("PRU program is already busy. Try to abort? (y/ any 
> key)\n");
>         if (getchar() == 'y'){
>             shared_ram[COMMAND] = CMND_ABORT;
>             printf("trying to abort it and exit\n");
>             exit (-1);
>         } else {
>             printf("waiting...\n");
>             while (shared_ram[STATUS] == STAT_BUSY) {};
>         }
>     }
>     //printf("Leftover command word before launching new command: ");
>     //display_cmnd(shared_ram[COMMAND]);
>
>     cmnd_to_send = argv[1][0];                            // atoi(argv[1]);
>     printf("\ncommand to send: ");
>     display_cmnd(cmnd_to_send);
>
>
>      if (cmnd_to_send == CMND_CLEAR_RAM){
>         // this works locally just to fill it with FFFF.
>         // The PRU will need a restart after that.
>         for (i=0; i < 3*1024; i++) shared_ram[i] = 0xffffffff;
>         for (i=0; i < 4*1024; i++) pru_ram[i]    = 0xfffffff0;
>         printf("\nthat was no real command, just wiped out PRU data and 
> shared RAM\n");
>         printf("to make a nice background for the memory dumps. restart 
> the PRU.\n");
>         printf("exiting.\n");
>         exit (0);
>     }
>     // printf("\nnach command2send\n");
>     if (argc == 3){
>
>         shared_ram[PARAM1]  = num_to_int(argv[2]);
>
>     } else if (argc == 4){
>
>         shared_ram[PARAM1]  = num_to_int(argv[2]);
>         shared_ram[PARAM2]  = num_to_int(argv[3]);
>
>     } else if (argc == 5){
>
>         shared_ram[PARAM1]  = num_to_int(argv[2]);
>         shared_ram[PARAM2]  = num_to_int(argv[3]);
>         shared_ram[PARAM3]  = num_to_int(argv[4]);
>
>     } else if (argc >= 6){
>         printf("argc too large: %d, giving up\n", argc);
>         exit(-1);
>     }
>     shared_ram[TEST1] = -1;
>     shared_ram[TEST2] = -2;
>     shared_ram[TEST3] = -3;
>     // printf("huhuh\n");
>     // nicht existierende argv anzufassen führt zu segfault.
>     // printf("%d    %d    %d \n", atoi(argv[1]), atoi(argv[2]), 
> atoi(argv[3]));
>     // for (int k= 0; k<8; k++) printf("\nshared ram[%d] = 0x%x  %d", 
> k, shared_ram[k], shared_ram[k]);
>     // printf("\n");
>     // now display & safe the pre-conditions.
>     disp_shared_ram_state();
> //    copy_pru_ram_to_file("pre_pru.txt");
> //    copy_shared_ram_to_file("pre_shared.txt");
>
>
> //-------------------------------------------------------------------------------
>
>     //printf("\nKicking it off\n");
>     shared_ram[COMMAND] = cmnd_to_send; // Now trigger the action.
>
>     command_postprocessing();
>
>     printf("\nStatus after running PRU command: ");
>     display_status();   // this will wait until PRU program is no 
> longer busy.
>     //printf("Hopefully cleared command word after execution: ");
>     //display_cmnd(shared_ram[COMMAND]);
>
>     disp_shared_ram_state();
>     // printf("copying shared ram to file\n");
>     copy_pru_ram_to_file("post_pru.txt");
>     copy_shared_ram_to_file("post_shared.txt");
>
>     exit(0);
> }  // run_pru_cmnd()
>
>
>
>
> int open_pru(){
>
>     int i;
>
>     //if (verbose) printf("enter open_pru()\n");
>     if (init_BBB_pins()) return 1;
>
>     // map the shared ram into our virtual memory
>     dev_mem_fd = open("/dev/mem",O_RDWR | O_SYNC);
>
>     // mmap params:
>     // address where the kernel creates the mapping. NULL= do as you like
>     // size of the mapped region  12288 = 12 KBytes
>     // protection
>     // flags
>     // file descriptor von /dev/mem
>     // pru-base  = 0x4A30_0000, shared ram starts at +0x10000
>     shared_ram = (int *) mmap(NULL, 12*1024, PROT_READ | PROT_WRITE, 
> MAP_SHARED,
>                 dev_mem_fd, 0x4A300000 + 0x10000);
>     if (-1 == (int)shared_ram) panic("could not mmap() shared PRU ram");
>
>     // both PRU local data rams together
>     pru_ram = (int *) mmap(NULL, 2*8*1024, PROT_READ | PROT_WRITE, 
> MAP_SHARED,
>                 dev_mem_fd, 0x4A300000 + 0x00000);
>     if (-1 == (int)pru_ram) panic("could not mmap() local PRU rams");
>     return 0;
> }
>
> int close_pru(void){
>     // FIXME: shared RAM must be un-mapped and file descriptors should 
> be closed
>     if (verbose) printf("enter close_pru()\n");
> //    if (!stop_pru()) return 1;
>     if (verbose) printf("leaving close_pru()\n");
>     return 0;
> }
>
>
>
>
>
>
>

-- 
For more options, visit http://beagleboard.org/discuss
--- 
You received this message because you are subscribed to the Google Groups 
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to beagleboard+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beagleboard/20f8b793-6549-4708-a355-8f56322a4b93n%40googlegroups.com.

Reply via email to