/* * logic_analyser_backend.c * Implements the logic analyser backend to intereact with the GUI. * * Copyright (C) 2019, STMicroelectronics - All Rights Reserved * Author: Michel Catrouillet michel.catrouillet@st.com for STMicroelectronics. * * License type: GPLv2 * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see * http://www.gnu.org/licenses/. * https://github.com/STMicroelectronics/meta-st-stm32mpu-app-logicanalyser/blob/kirkstone/recipes-graphics/st-software/logic-analyser-backend/backend.c */ #define _GNU_SOURCE /* To get DN_* constants from */ #include #include #include #include #include #include #include #include #include #include #include // for usleep #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SAMP_SRAM_PACKET_SIZE (256*2) #define SAMP_DDR_BUFFER_SIZE (1024*1024) #define TTY_CTRL_OPTS (CS8 | CLOCAL | CREAD) #define TTY_INPUT_OPTS IGNPAR #define TTY_OUTPUT_OPTS 0 #define TTY_LOCAL_OPTS 0 #define DATA_BUF_POOL_SIZE 1024*1024 /* 1MB */ #define MAX_BUF 80 #define PORT 8888 #define GET 0 #define POST 1 #define POSTBUFFERSIZE 512 #define DMA_DDR_BUFF 1 #define PHYS_RESERVED_REGION_ADDR 0xdb000000 #define PHYS_RESERVED_REGION_SIZE 0x1000000 #define RPMSG_SDB_IOCTL_SET_EFD _IOW('R', 0x00, struct rpmsg_sdb_ioctl_set_efd *) #define RPMSG_SDB_IOCTL_GET_DATA_SIZE _IOWR('R', 0x01, struct rpmsg_sdb_ioctl_get_data_size *) #define TIMEOUT 60 #define NB_BUF 10 typedef struct { int bufferId, eventfd; } rpmsg_sdb_ioctl_set_efd; typedef struct { int bufferId; uint32_t size; } rpmsg_sdb_ioctl_get_data_size; struct connection_info_struct { int connectiontype; char *answerstring; struct MHD_PostProcessor *postprocessor; }; struct MHD_Daemon *mHttpDaemon; char FIRM_NAME[50]; struct timeval tval_before, tval_after, tval_result; typedef enum { STATE_READY = 0, STATE_SAMPLING_LOW, STATE_SAMPLING_HIGH, } machine_state_t; static char machine_state_str[5][13] = {"READY", "SAMPLING_LOW", "SAMPLING_HIGH"}; static char SELECTED[10] = {" selected"}; static char NOT_SELECTED[10] = {""}; static char freq_unit_str[3][4] = {"MHz", "kHz", "Hz"}; static char FREQU[3] = {'M', 'k', 'H'}; /* The file descriptor used to manage our TTY over RPMSG */ static int mFdRpmsg[2] = {-1, -1}; /* The file descriptor used to manage our SDB over RPMSG */ static int mFdSdbRpmsg = -1; static int virtual_tty_send_command(int len, char* commandStr); static char mByteBuffer[512]; static char mByteBuffCpy[512]; static int mNbReadTty = 0; static char mRxTraceBuffer[512]; static char mSamplingStr[15]; static int32_t mSampFreq_Hz = 4; static machine_state_t mMachineState; static int32_t mSampParmCount; static uint8_t mExitRequested = 0, mErrorDetected = 0; static uint32_t mNbUncompData=0, mNbWrittenInFileData; static uint32_t mNbUncompMB=0, mNbPrevUncompMB=0, mNbTty0Frame=0; static uint8_t mDdrBuffAwaited; static uint8_t mThreadCancel = 0; void* mmappedData[NB_BUF]; static int fMappedData = 0; FILE *pOutFile = NULL; static char mFileNameStr[150]; static pthread_t threadTTY, threadSDB, threadUI; static int efd[NB_BUF]; static struct pollfd fds[NB_BUF]; static GtkWidget *window; static GtkWidget *f_scale; static GtkAdjustment *fadjustment; static GtkWidget *controlTitle_label; static GtkWidget *fTitle_label; static GtkWidget *fValue_label; static GtkWidget *measurTitle_label; static GtkWidget *state_label; static GtkWidget *state_value; static GtkWidget *nbCompData_label; static GtkWidget *nbCompData_value; static GtkWidget *nbRealData_label; static GtkWidget *nbRealData_value; static GtkWidget *nbRpmsgFrame_label ; static GtkWidget *nbRpmsgFrame_value; static GtkWidget *data_label; static GtkWidget *data_value; static GtkWidget *butSingle; static GtkWidget *notchSetdata; /******************************************************************************** Copro functions allowing to manage a virtual TTY over RPMSG *********************************************************************************/ int copro_isFwRunning(void) { int fd; size_t byte_read; int result = 0; unsigned char bufRead[MAX_BUF]; char *user = getenv("USER"); if (user && strncmp(user, "root", 4)) { system("XTERM=xterm su root -c 'cat /sys/class/remoteproc/remoteproc0/state' > /tmp/remoteproc0_state"); fd = open("/tmp/remoteproc0_state", O_RDONLY); } else { fd = open("/sys/class/remoteproc/remoteproc0/state", O_RDONLY); } if (fd < 0) { printf("CA7 : Error opening remoteproc0/state, err=-%d\n", errno); return (errno * -1); } byte_read = (size_t) read (fd, bufRead, MAX_BUF); if (byte_read >= strlen("running")) { char* pos = strstr((char*)bufRead, "running"); if(pos) { result = 1; } } close(fd); return result; } int copro_stopFw(void) { int fd; char *user = getenv("USER"); if (user && strncmp(user, "root",4)) { system("su root -c 'echo stop > /sys/class/remoteproc/remoteproc0/state'"); return 0; } fd = open("/sys/class/remoteproc/remoteproc0/state", O_RDWR); if (fd < 0) { printf("CA7 : Error opening remoteproc0/state, err=-%d\n", errno); return (errno * -1); } write(fd, "stop", strlen("stop")); close(fd); return 0; } int copro_startFw(void) { int fd; char *user = getenv("USER"); if (user && strncmp(user, "root",4)) { system("su root -c 'echo start > /sys/class/remoteproc/remoteproc0/state'"); return 0; } fd = open("/sys/class/remoteproc/remoteproc0/state", O_RDWR); if (fd < 0) { printf("CA7 : Error opening remoteproc0/state, err=-%d\n", errno); return (errno * -1); } write(fd, "start", strlen("start")); close(fd); return 0; } int copro_getFwPath(char* pathStr) { int fd; int byte_read; char *user = getenv("USER"); if (user && strncmp(user, "root",4)) { system("XTERM=xterm su root -c 'cat /sys/module/firmware_class/parameters/path' > /tmp/parameters_path"); fd = open("/tmp/parameters_path", O_RDONLY); } else { fd = open("/sys/module/firmware_class/parameters/path", O_RDONLY); } if (fd < 0) { printf("CA7 : Error opening firmware_class/parameters/path, err=-%d\n", errno); return (errno * -1); } byte_read = read (fd, pathStr, MAX_BUF); close(fd); return byte_read; } int copro_setFwPath(char* pathStr) { int fd; int result = 0; char *user = getenv("USER"); if (user && strncmp(user, "root",4)) { char cmd[1024]; snprintf(cmd, 1024, "su root -c 'echo %s > /sys/module/firmware_class/parameters/path'", pathStr); system(cmd); return strlen(pathStr); } fd = open("/sys/module/firmware_class/parameters/path", O_RDWR); if (fd < 0) { printf("CA7 : Error opening firmware_class/parameters/path, err=-%d\n", errno); return (errno * -1); } result = write(fd, pathStr, strlen(pathStr)); close(fd); return result; } int copro_getFwName(char* pathStr) { int fd; int byte_read; char *user = getenv("USER"); if (user && strncmp(user, "root",4)) { system("XTERM=xterm su root -c 'cat /sys/class/remoteproc/remoteproc0/firmware' > /tmp/remoteproc0_firmware"); fd = open("/tmp/remoteproc0_firmware", O_RDONLY); } else { fd = open("/sys/class/remoteproc/remoteproc0/firmware", O_RDWR); } if (fd < 0) { printf("CA7 : Error opening remoteproc0/firmware, err=-%d\n", errno); return (errno * -1); } byte_read = read (fd, pathStr, MAX_BUF); close(fd); return byte_read; } int copro_setFwName(char* nameStr) { int fd; int result = 0; char *user = getenv("USER"); if (user && strncmp(user, "root",4)) { char cmd[1024]; snprintf(cmd, 1024, "su root -c 'echo %s > /sys/class/remoteproc/remoteproc0/firmware'", nameStr); system(cmd); return strlen(nameStr); } fd = open("/sys/class/remoteproc/remoteproc0/firmware", O_RDWR); if (fd < 0) { printf("CA7 : Error opening remoteproc0/firmware, err=-%d\n", errno); return (errno * -1); } result = write(fd, nameStr, strlen(nameStr)); close(fd); return result; } int copro_openTtyRpmsg(int ttyNb, int modeRaw) { struct termios tiorpmsg; char devName[50]; sprintf(devName, "/dev/ttyRPMSG%d", ttyNb%2); mFdRpmsg[ttyNb%2] = open(devName, O_RDWR | O_NOCTTY | O_NONBLOCK); if (mFdRpmsg[ttyNb%2] < 0) { printf("CA7 : Error opening ttyRPMSG%d, err=-%d\n", ttyNb%2, errno); return (errno * -1); } #if 1 /* get current port settings */ tcgetattr(mFdRpmsg[ttyNb%2],&tiorpmsg); if (modeRaw) { #if 0 tiorpmsg.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); tiorpmsg.c_oflag &= ~OPOST; tiorpmsg.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tiorpmsg.c_cflag &= ~(CSIZE | PARENB); tiorpmsg.c_cflag |= CS8; #else memset(&tiorpmsg, 0, sizeof(tiorpmsg)); tiorpmsg.c_cflag = TTY_CTRL_OPTS; tiorpmsg.c_iflag = TTY_INPUT_OPTS; tiorpmsg.c_oflag = TTY_OUTPUT_OPTS; tiorpmsg.c_lflag = TTY_LOCAL_OPTS; tiorpmsg.c_cc[VTIME] = 0; tiorpmsg.c_cc[VMIN] = 1; cfmakeraw(&tiorpmsg); #endif } else { /* ECHO off, other bits unchanged */ tiorpmsg.c_lflag &= ~ECHO; /*do not convert LF to CR LF */ tiorpmsg.c_oflag &= ~ONLCR; } if (tcsetattr(mFdRpmsg[ttyNb%2], TCSANOW, &tiorpmsg) < 0) { printf("Error %d in copro_openTtyRpmsg(%d) tcsetattr", errno, ttyNb); return (errno * -1); } #endif return 0; } int copro_closeTtyRpmsg(int ttyNb) { close(mFdRpmsg[ttyNb%2]); mFdRpmsg[ttyNb%2] = -1; return 0; } int copro_writeTtyRpmsg(int ttyNb, int len, char* pData) { int result = 0; if (mFdRpmsg[ttyNb%2] < 0) { printf("CA7 : Error writing ttyRPMSG%d, fileDescriptor is not set\n", ttyNb%2); return mFdRpmsg[ttyNb%2]; } result = write(mFdRpmsg[ttyNb%2], pData, len); return result; } int copro_readTtyRpmsg(int ttyNb, int len, char* pData) { int byte_rd, byte_avail; int result = 0; if (mFdRpmsg[ttyNb%2] < 0) { printf("CA7 : Error reading ttyRPMSG%d, fileDescriptor is not set\n", ttyNb%2); return mFdRpmsg[ttyNb%2]; } ioctl(mFdRpmsg[ttyNb%2], FIONREAD, &byte_avail); if (byte_avail > 0) { if (byte_avail >= len) { byte_rd = read (mFdRpmsg[ttyNb%2], pData, len); } else { byte_rd = read (mFdRpmsg[ttyNb%2], pData, byte_avail); } //printf("CA7 : read successfully %d bytes to %p, [0]=0x%x\n", byte_rd, pData, pData[0]); result = byte_rd; } else { result = 0; } return result; } /******************************************************************************** End of Copro functions *********************************************************************************/ void print_time() { struct timespec ts; clock_gettime(1, &ts); printf("Time: %lld\n", (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000LL)); } /******************************************************************************** GTK UI functions *********************************************************************************/ static void open_raw_file(void) { time_t t = time(NULL); struct tm tm = *localtime(&t); sprintf(mFileNameStr, "/usr/local/demo/la/%04d%02d%02d-%02d%02d%02d.dat", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); pOutFile = fopen(mFileNameStr,"wb"); } static int32_t write_raw_file(unsigned char* pData, unsigned int size) { // perform the write by packets of 4kB int rest2write = size; int index = 0; int size2write = 4096; int writtenSize = 0; do { if (rest2write < 4096) { size2write = rest2write; } writtenSize += fwrite(pData+index, 1, size2write, pOutFile); rest2write -= size2write; index += size2write; } while (rest2write > 0); return writtenSize; } static void close_raw_file(void) { if (pOutFile != NULL) { fclose(pOutFile); pOutFile = NULL; } } static gboolean refreshUI_CB (gpointer data) { char tmpStr[200]; if (mMachineState >= STATE_SAMPLING_LOW) { gtk_button_set_label (GTK_BUTTON (butSingle), "Stop"); } else { gtk_button_set_label (GTK_BUTTON (butSingle), "Start"); } gtk_label_set_text (GTK_LABEL (state_value), machine_state_str[mMachineState]); sprintf(tmpStr, "%uMB : %u", mNbUncompMB, mNbUncompData); gtk_label_set_text (GTK_LABEL (nbRealData_value), tmpStr); sprintf(tmpStr, "%u", mNbTty0Frame); gtk_label_set_text (GTK_LABEL (nbRpmsgFrame_value), tmpStr); //gtk_label_set_text (GTK_LABEL (fileName_value), mFileNameStr); sprintf(tmpStr, "%x", mByteBuffCpy[0]); gtk_label_set_text (GTK_LABEL (data_value), tmpStr); gtk_widget_show_all(window); return FALSE; } static void single_clicked (GtkWidget *widget, gpointer data) { char setData = 'n'; if (mMachineState == STATE_READY) { if (mSampFreq_Hz > 5) { mMachineState = STATE_SAMPLING_HIGH; } else { mMachineState = STATE_SAMPLING_LOW; } mNbUncompData=0; mNbPrevUncompMB = 0; mNbUncompMB = 0; mNbWrittenInFileData=0; mDdrBuffAwaited=0; mNbTty0Frame=0; if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (notchSetdata))) { setData = 'y'; } // build sampling string sprintf(mSamplingStr, "S%03dMs%c", mSampFreq_Hz, setData); printf("CA7 : Start sampling at %dMHz\n", mSampFreq_Hz); virtual_tty_send_command(strlen(mSamplingStr), mSamplingStr); gdk_threads_add_idle (refreshUI_CB, window); } else if (mMachineState >= STATE_SAMPLING_LOW) { mMachineState = STATE_READY; printf("CA7 : Stop sampling\n"); virtual_tty_send_command(strlen("Exit"), "Exit"); gdk_threads_add_idle (refreshUI_CB, window); } else { printf("CA7 : Start sampling param error: mMachineState=%d mSampFreq_Hz=%d \n", mMachineState, mSampFreq_Hz); } } static void f_scale_moved (GtkRange *range, gpointer user_data) { GtkWidget *label = user_data; gdouble pos = gtk_range_get_value (range); gdouble val = 1 + 11 * pos / 100; gchar *str = g_strdup_printf ("%.0f", val); mSampFreq_Hz = atoi(str); gtk_label_set_text (GTK_LABEL (label), str); printf("CA7 : fscale = %d\n", mSampFreq_Hz); g_free(str); } void *ui_thread(void *arg) { GtkWidget *mainGrid; char tmpStr[100]; time_t t = time(NULL); struct tm tm = *localtime(&t); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "STHowToM4ToA7LargeDataExchange"); g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); gtk_container_set_border_width (GTK_CONTAINER (window), 10); gtk_window_fullscreen(GTK_WINDOW (window)); GtkCssProvider *provider = gtk_css_provider_new (); gtk_css_provider_load_from_path (provider, "/usr/local/demo/la/bin/la.css", NULL); GdkDisplay* Display = gdk_display_get_default(); GdkScreen* Screen = gdk_display_get_default_screen(Display); gtk_style_context_add_provider_for_screen(Screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER); controlTitle_label = gtk_label_new ("Control"); gtk_widget_set_name(controlTitle_label, "title1"); fTitle_label = gtk_label_new ("Sampling freq. (MHz) :"); gtk_label_set_xalign (GTK_LABEL (fTitle_label), 0); gtk_widget_set_name(fTitle_label, "header"); fValue_label = gtk_label_new ("4"); gtk_label_set_xalign (GTK_LABEL (fValue_label), 0); gtk_widget_set_name(fValue_label, "value"); fadjustment = gtk_adjustment_new (16, 0, 100, 5, 10, 0); f_scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, fadjustment); gtk_scale_set_draw_value (GTK_SCALE (f_scale), FALSE); g_object_set (GTK_SCALE (f_scale), "expand", TRUE, NULL); g_signal_connect (f_scale, "value-changed", G_CALLBACK (f_scale_moved), fValue_label); measurTitle_label = gtk_label_new ("Measurements"); gtk_widget_set_name(measurTitle_label, "title1"); state_label = gtk_label_new ("Machine state :"); gtk_label_set_xalign (GTK_LABEL (state_label), 0); gtk_widget_set_name(state_label, "header"); state_value = gtk_label_new (""); gtk_label_set_xalign (GTK_LABEL (state_value), 0); gtk_widget_set_name(state_value, "value"); nbRealData_label = gtk_label_new ("Nb of received data :"); gtk_label_set_xalign (GTK_LABEL (nbRealData_label), 0); gtk_widget_set_name(nbRealData_label, "header"); nbRealData_value = gtk_label_new (""); gtk_label_set_xalign (GTK_LABEL (nbRealData_value), 0); gtk_widget_set_name(nbRealData_value, "value"); nbRpmsgFrame_label = gtk_label_new ("Nb of RPMSG data frame :"); gtk_label_set_xalign (GTK_LABEL (nbRpmsgFrame_label ), 0); gtk_widget_set_name(nbRpmsgFrame_label, "header"); nbRpmsgFrame_value = gtk_label_new (""); gtk_label_set_xalign (GTK_LABEL (nbRpmsgFrame_value), 0); gtk_widget_set_name(nbRpmsgFrame_value, "value"); data_label = gtk_label_new ("Data :"); gtk_label_set_xalign (GTK_LABEL (data_label), 0); gtk_widget_set_name(data_label, "header"); data_value = gtk_label_new (""); gtk_label_set_xalign (GTK_LABEL (data_value), 0); gtk_widget_set_name(data_value, "value"); gtk_label_set_text (GTK_LABEL (state_value), machine_state_str[mMachineState]); sprintf(tmpStr, "%u", mNbUncompData); gtk_label_set_text (GTK_LABEL (nbCompData_value), tmpStr); sprintf(tmpStr, "%u", mNbUncompData); gtk_label_set_text (GTK_LABEL (nbRealData_value), tmpStr); sprintf(tmpStr, "%u", mNbWrittenInFileData); gtk_label_set_text (GTK_LABEL (nbRpmsgFrame_value), tmpStr); butSingle = gtk_button_new_with_label("Start"); g_signal_connect(butSingle, "clicked", G_CALLBACK (single_clicked), NULL); gtk_style_context_add_class( gtk_widget_get_style_context(GTK_WIDGET(butSingle)), "circular"); gtk_widget_set_name(butSingle, "mybutt"); notchSetdata = gtk_check_button_new_with_label("Set DATA"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(notchSetdata), FALSE); mainGrid = gtk_grid_new (); gtk_grid_set_row_spacing (GTK_GRID (mainGrid), 5); gtk_grid_set_column_spacing (GTK_GRID (mainGrid), 20); // Control title in (0,0) is 3 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), controlTitle_label, 0, 0, 3, 1); // Freq. title in (0,1) is 1 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), fTitle_label, 0, 1, 1, 1); // Freq. value in (1,1) is 1 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), fValue_label, 1, 1, 1, 1); // Freq. scale in (2,1) is 1 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), f_scale, 2, 1, 1, 1); // Start button in (0,2) is 2 column large & 2 row high gtk_grid_attach (GTK_GRID (mainGrid), butSingle, 0, 2, 2, 2); // SetDATA notch in (3,2) is 2 column large & 2 row high gtk_grid_attach (GTK_GRID (mainGrid), notchSetdata, 2, 2, 2, 1); // Measurement title in (0,4) is 3 columns large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), measurTitle_label, 0, 4, 3, 1); // State label in (0,5) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), state_label, 0, 5, 2, 1); // State value in (2,5) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), state_value, 2, 5, 2, 1); // Real data label in (0,7) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), nbRealData_label, 0, 6, 2, 1); // Real data value in (2,7) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), nbRealData_value, 2, 6, 2, 1); // Nb of RPMSG frame label in (0,8) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), nbRpmsgFrame_label, 0, 7, 2, 1); // Nb of RPMSG frame value in (2,8) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), nbRpmsgFrame_value, 2, 7, 2, 1); // Data label in (0,9) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), data_label, 0, 8, 2, 1); // File name value in (2,9) is 2 column large & 1 row high gtk_grid_attach (GTK_GRID (mainGrid), data_value, 2, 8, 2, 1); gtk_grid_set_row_homogeneous (GTK_GRID (mainGrid), TRUE); gtk_container_add (GTK_CONTAINER (window), mainGrid); gtk_widget_show_all(window); gtk_main (); return 0; } /************************************************************************************* End of GTK UI functions *************************************************************************************/ static void sleep_ms(int milliseconds) { usleep(milliseconds * 1000); } static int virtual_tty_send_command(int len, char* commandStr) { struct timespec ts; clock_gettime(1, &ts); printf("CA7 [%lld] : virtual_tty_send_command len=%d => %s\n", (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000LL), len, commandStr); return copro_writeTtyRpmsg(0, len, commandStr); } size_t getFilesize(const char* filename) { struct stat st; stat(filename, &st); return st.st_size; } void incatchr(int signum){ printf("%s!\n",__func__); } void exit_fct(int signum) { gtk_main_quit(); mThreadCancel = 1; sleep_ms(100); if (fMappedData) { for (int i=0;i 0) { mNbTty0Frame++; mNbUncompData += read0; mNbUncompMB = mNbUncompData / 1024 / 1024; if (mNbUncompMB != mNbPrevUncompMB) { // a new MB has been received, update display mNbPrevUncompMB = mNbUncompMB; mByteBuffCpy[0] = mByteBuffer[0]; gdk_threads_add_idle (refreshUI_CB, window); } } // tty1 is dedicated to trace of M4 read1 = copro_readTtyRpmsg(1, 512, mRxTraceBuffer); mRxTraceBuffer[read1] = 0; // to be sure to get a end of string if (read1 > 0) { if (strcmp(mRxTraceBuffer, "CM4 : DMA TransferError") == 0) { // sampling is aborted, refresh the UI mErrorDetected = 1; //mMachineState = STATE_READY; //gdk_threads_add_idle (refreshUI_CB, window); } gettimeofday(&tval_after, NULL); timersub(&tval_after, &tval_before, &tval_result); if (mRxTraceBuffer[0] == 'C') { printf("[%ld.%06ld] : %s\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec, mRxTraceBuffer); } else { printf("[%ld.%06ld] : CA7 : tty1 got %d [%x] bytes\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec, read1, mRxTraceBuffer[0]); } } //usleep(500); //sleep_ms(1); // give time to UI } return 0; } void *sdb_thread(void *arg) { int ret, rc, i, n; int buffIdx = 0; char buf[16]; char dbgmsg[80]; rpmsg_sdb_ioctl_get_data_size q_get_data_size; char *filename = "/dev/rpmsg-sdb"; rpmsg_sdb_ioctl_set_efd q_set_efd; mFdSdbRpmsg = open(filename, O_RDWR); assert(mFdSdbRpmsg != -1); for (i=0;i buf[%d] is empty\n", mDdrBuffAwaited); } mDdrBuffAwaited++; if (mDdrBuffAwaited >= NB_BUF) { mDdrBuffAwaited = 0; } } else { // we face message lost due to SDB driver not managing RPMSG DATA containing several messages // in this case, just treat several message mDdrBuffAwaited++; if (mDdrBuffAwaited >= NB_BUF) { mDdrBuffAwaited = 0; } if (fds[mDdrBuffAwaited].revents & POLLIN) { rc = read(efd[mDdrBuffAwaited], buf, 16); if (!rc) { printf("CA7 : stdin closed\n"); return 0; } /* Get buffer data size*/ q_get_data_size.bufferId = mDdrBuffAwaited; if(ioctl(mFdSdbRpmsg, RPMSG_SDB_IOCTL_GET_DATA_SIZE, &q_get_data_size) < 0) { error(EXIT_FAILURE, errno, "Failed to get data size"); } if (q_get_data_size.size) { mNbUncompMB += 2; mNbUncompData += q_get_data_size.size; mNbUncompData += q_get_data_size.size; // need twice as we missed one unsigned char* pData = (unsigned char*)mmappedData[mDdrBuffAwaited]; // save a copy of 1st data mByteBuffCpy[0] = *pData; gettimeofday(&tval_after, NULL); timersub(&tval_after, &tval_before, &tval_result); printf("[%ld.%06ld] sdb_thread data EVENT mDdrBuffAwaited=%d mNbUncompData=%u \n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec, mDdrBuffAwaited, mNbUncompData); gdk_threads_add_idle (refreshUI_CB, window); } else { printf("CA7 : sdb_thread => buf[%d] is empty\n", mDdrBuffAwaited); } mDdrBuffAwaited++; if (mDdrBuffAwaited >= NB_BUF) { mDdrBuffAwaited = 0; } } else { // we may have started the timeout, but have stopped and started sampling in RPMSG if (mMachineState == STATE_SAMPLING_HIGH) { n = 0; for (i=0; i use rpmsg-sdb driver to perform CMA buff allocation ******/ mMachineState = STATE_READY; mSampFreq_Hz = 4; mSampParmCount = 0; gtk_init (&argc, &argv); if (pthread_create( &threadUI, NULL, ui_thread, NULL) != 0) { printf("CA7 : ui_thread creation fails\n"); goto end; } printf("CA7 : Entering in Main loop\n"); while (1) { if (mExitRequested) break; if (mErrorDetected) { if (mMachineState >= STATE_SAMPLING_LOW) { virtual_tty_send_command(strlen("Exit"), "Exit"); if (mErrorDetected == 2) printf("CA7 : ERROR in DDR Buffer order => Stop sampling!!!\n"); //else if (mErrorDetected == 2) printf("CA7 : File System full => Stop sampling!!!\n"); else if (mErrorDetected == 1) printf("CA7 : M4 reported DMA error !!!\n"); mErrorDetected = 0; mMachineState = STATE_READY; gdk_threads_add_idle (refreshUI_CB, window); #if 0 close_raw_file(); #endif } } sleep_ms(1); // give time to UI } for (i=0;i