Запись в сокет завершается неудачно с добавлением любой отдельной строки кода в программу c - PullRequest
0 голосов
/ 05 ноября 2018

Я пишу программу на c, предназначенную для передачи данных через сокет клиенту Python. Я столкнулся с действительно странной проблемой, когда запись в созданный сокет перестает работать с добавлением практически любой строки кода после определенного момента в программе.

Подробнее об этой проблеме: я пытаюсь записать произвольное число в сокет, например, 256. Это работает нормально, то есть клиент python получает число 256 от сервера c, при условии, что нет никаких команд, кроме get_status(s2mm_status,"S2MM"); Если есть какие-либо такие команды после этой точки, «0» записывается в сокет вместо любого числа (например, 256), который я указал. Все такое простое как объявление "int i" приводит к такому поведению.

Излишне говорить, что я в замешательстве. Мне интересно, если я использую слишком много памяти или что-то? Я просто не знаю, как диагностировать проблему. Во всяком случае, я предоставил код ниже. Извините за длину, я просто действительно не знаю, что является или не имеет значения.

Для базового объяснения кода: создано несколько карт памяти, чтобы я мог записывать определенные значения в регистры, что инициирует запись данных с АЦП на устройство, запись этих данных в память и затем передать эти данные через сокет клиенту Python.

#include<stdio.h>
#include<string.h> //strlen
#include<stdlib.h>
#include<sys/socket.h> 
#include<arpa/inet.h> // inet_addr 
#include<unistd.h> //write 
#include<pthread.h> //for threading, link with lpthread 
#include<sys/mman.h>
#include <fcntl.h>
#include <arpa/inet.h> //https://linux.die.net/man/3/htonl
#include <time.h> 
#include<math.h> 

#include "server_library.h" 

/*********************************/
//Address Editor                         
/*********************************/
//ps_0 
//  Data 
//      axi_dma_0 S_AXI_LITE reg 0x4040_0000 64K 0x4040_FFFF
//axi_dma_0
//  Data_SG 
//      ps_0 S_AXI_HP0 HP0_DDR_LOWOCM 0x0800_0000 128M 0x07FF_FFFF
//  DATA_MM2S
//      ps_0 S_AXI_HP0 HP0_DDR_LOWOCM 0x0800_0000 128M 0x07FF_FFFF
//  DATA_S2MM
//      ps_0 S_AXI_HP0 HP0_DDR_LOWOCM 0x0800_0000 128M 0x07FF_FFFF
/*********************************/

/*********************************/
//Addresses                        
/*********************************/
#define AXI_DMA_ADDRESS         0x40400000
#define HP0_ADDRESS             0x08000000 //Formerly HP0_DMA_BUFFER_MEM_ADDRESS
#define MM2S_BASE_DESC_ADDR     HP0_ADDRESS //Formerly HP0_MM2S_DMA_DESCRIPTORS_ADDRESS
#define S2MM_BASE_DESC_ADDR     HP0_ADDRESS+MEMBLOCK_WIDTH+1 //Formerly HP0_S2MM_DMA_DESCRIPTORS_ADDRESS
#define MM2S_SOURCE_ADDRESS     HP0_ADDRESS+SG_DMA_DESCRIPTORS_WIDTH+1 //Formerly HP0_MM2S_SOURCE_MEM_ADDRESS
#define S2MM_TARGET_ADDRESS     HP0_ADDRESS+(MEMBLOCK_WIDTH+1)+SG_DMA_DESCRIPTORS_WIDTH+1 //Formerly HP0_S2MM_TARGET_MEM_ADDRESS

// AXI_DMA_ADDRESS: 0x40400000
// HP0_ADDRESS: 0x08000000
// MM2S_BASE_DESC_ADDR: 0x08000000
// S2MM_BASE_DESC_ADDR: 0x0c000000
// MM2S_SOURCE_ADDRESS: 0x08010000
// S2MM_TARGET_ADDRESS: 0x0c010000

/*********************************/
//Miscellaneous                         
/*********************************/
#define DESCRIPTOR_REGISTERS_SIZE 0xFFFF
#define SG_DMA_DESCRIPTORS_WIDTH 0xFFFF 
#define MEMBLOCK_WIDTH 0x3FFFFFF //Size of memory used by S2MM and MM2S 
#define BUFFER_BLOCK_WIDTH 0x7D0000 //Size of memory block per descriptor in bytes 
#define NUM_OF_DESCRIPTORS 0x02 //Number of descriptors for each direction 

#define START_FRAME     0x08000000 //TXSOF = 1 TXEOF = 0 
#define MID_FRAME       0x00000000 //TXSOF = TXEOF = 0 
#define COMPLETE_FRAME  0x0C000000 //TXSOF = TXEOF = 1
#define END_FRAME       0x04000000 //TXSOF = 0 TXEOF = 1

#define CYCLIC_ENABLE   0x10

#define TRANSFER_BYTES 1024
#define TRANSFER_INTS 256 
#define TRANSFER_BITS 8*TRANSFER_BYTES  
#define N_DESC 2


/*********************************/
//Offsets                          
/*********************************/
// MM2S CONTROL
#define MM2S_CONTROL_REGISTER       0x00    // MM2S_DMACR
#define MM2S_STATUS_REGISTER        0x04    // MM2S_DMASR
#define MM2S_CURDESC                0x08    // must align 0x40 addresses
#define MM2S_CURDESC_MSB            0x0C    // unused with 32bit addresses
#define MM2S_TAILDESC               0x10    // must align 0x40 addresses
#define MM2S_TAILDESC_MSB           0x14    // unused with 32bit addresses

#define SG_CTL                      0x2C    // CACHE CONTROL

// S2MM CONTROL
#define S2MM_CONTROL_REGISTER       0x30    // S2MM_DMACR
#define S2MM_STATUS_REGISTER        0x34    // S2MM_DMASR
#define S2MM_CURDESC                0x38    // must align 0x40 addresses
#define S2MM_CURDESC_MSB            0x3C    // unused with 32bit addresses
#define S2MM_TAILDESC               0x40    // must align 0x40 addresses
#define S2MM_TAILDESC_MSB           0x44    // unused with 32bit addresses

//Scatter/Gather Control 
#define NEXT_DESC   0x00 //Set to address of next descriptor in chain 
#define BUFF_ADDR   0x08 //Set to address to read from (MM2S) or write to (S2MM) 
#define CONTROL     0x18 //Set transfer length, T/RXSOF and T/RXEOF 
#define STATUS      0x1C //Descriptor status

/*********************************/
//Functions                         
/*********************************/
unsigned int set_offset(unsigned int* virtual_address, int offset, unsigned int value){
    virtual_address[offset>>2] = value; 
}

unsigned int get_offset(unsigned int* virtual_address, int offset) {    
    return virtual_address[offset>>2];
}

void print_offset(unsigned int* virtual_address, int offset){    
    unsigned int value = get_offset(virtual_address,offset); 
    printf("0x%08x\n",value); 
}

void memsend(void* virtual_address, int byte_count, int socket_desc)
{
    unsigned int *p = virtual_address;
    int offset; 
    for(offset = 0; offset<byte_count;offset++){
        printf("0x%08x\n",p[offset]); 
        write(socket_desc,&p[offset],sizeof(p[offset])); 
    }
}

void memdump(void* virtual_address, int byte_count)
{    
    unsigned int *p = virtual_address;
    int offset; 
    for(offset = 0; offset<byte_count;offset++){
        printf("%d: 0x%08x\n",offset,p[offset]);         
    }
}

void get_status(uint32_t status, char *type){   
    if(type == "S2MM"){
        printf("S2MM status 0x%08x @0x%08x\n",status,AXI_DMA_ADDRESS+S2MM_STATUS_REGISTER);         
    }
    if(type == "MM2S"){
        printf("MM2S status 0x%08x @0x%08x\n",status,AXI_DMA_ADDRESS+MM2S_STATUS_REGISTER);         
    }
    if(status & 0x00000001) printf(" Halted"); 
    if(status & 0x00000002) printf(" Idle"); 
    if(status & 0x00000008) printf(" SGIncld"); 
    if(status & 0x00000010) printf(" DMAIntErr"); 
    if(status & 0x00000020) printf(" DMASlvErr"); 
    if(status & 0x00000040) printf(" DMADecErr"); 
    if(status & 0x00000100) printf(" SGIntErr"); 
    if(status & 0x00000200) printf(" SGSlvErr"); 
    if(status & 0x00000400) printf(" SGDecErr"); 
    if(status & 0x00001000) printf(" IOC_Irq"); 
    if(status & 0x00002000) printf(" Dly_Irq"); 
    if(status & 0x00004000) printf(" Err_Irq"); 
    else printf(" running"); 
    printf("\n"); 
}


int main(){

    int mm2s_status, s2mm_status;       
    uint32_t mm2s_base_descriptor_address; //Formerly mm2s_current_descriptor_address
    uint32_t s2mm_base_descriptor_address; //Formerly s2mm_current_descriptor_address
    uint32_t mm2s_tail_descriptor_address;
    uint32_t s2mm_tail_descriptor_address;
    int fd = open("/dev/mem",O_RDWR|O_SYNC);    
    //Create 64K AXI DMA Memory Map at AXI_DMA_ADDRESS (0x40400000)
    unsigned int* axi_dma = mmap(NULL,DESCRIPTOR_REGISTERS_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,AXI_DMA_ADDRESS); 
    //Create 64k mm2s descriptors memory map at HP0_MM2S_DMA_DESCRIPTORS_ADDRESS (0x08000000)
    unsigned int* mm2s_descriptors = mmap(NULL,DESCRIPTOR_REGISTERS_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,MM2S_BASE_DESC_ADDR); //Formerly mm2s_descriptor_register_mmap
    //Create 64k s2mm descriptors memory map at HP0_S2MM_DMA_DESCRIPTORS_ADDRESS (0x0c000000)
    unsigned int* s2mm_descriptors = mmap(NULL,DESCRIPTOR_REGISTERS_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,S2MM_BASE_DESC_ADDR); //Formerly s2mm_descriptor_register_mmap
    //Create ~1Mb x Num_Descriptors source memory map at HP0_MM2S_SOURCE_MEM_ADDRESS  (0x08010000)
    unsigned int* source_memory = mmap(NULL,BUFFER_BLOCK_WIDTH*NUM_OF_DESCRIPTORS,PROT_READ|PROT_WRITE,MAP_SHARED,fd,(off_t)(MM2S_SOURCE_ADDRESS)); //Formerly source_mmap
    //Create ~1Mb x Num_Descriptors target memory map at HP0_S2MM_TARGET_MEM_ADDRESS (0x0c010000)
    unsigned int* dest_memory = mmap(NULL,BUFFER_BLOCK_WIDTH*NUM_OF_DESCRIPTORS,PROT_READ|PROT_WRITE,MAP_SHARED,fd,(off_t)(S2MM_TARGET_ADDRESS)); //Formerly dest_mmap 

    //Clear mm2s descriptors 
    memset(mm2s_descriptors,0x00000000,DESCRIPTOR_REGISTERS_SIZE); 
    //Clear s2mm descriptors 
    memset(s2mm_descriptors,0x00000000,DESCRIPTOR_REGISTERS_SIZE); 
    //Clear Target Memory 
    memset(dest_memory,0x00000000,NUM_OF_DESCRIPTORS*BUFFER_BLOCK_WIDTH/4); 

        //Reset and halt all DMA operations 
    set_offset(axi_dma,MM2S_CONTROL_REGISTER,0x4); 
    set_offset(axi_dma,S2MM_CONTROL_REGISTER,0x4); 
    set_offset(axi_dma,MM2S_CONTROL_REGISTER,0x0); 
    set_offset(axi_dma,S2MM_CONTROL_REGISTER,0x0); 
    mm2s_status = get_offset(axi_dma,MM2S_STATUS_REGISTER); 
    s2mm_status = get_offset(axi_dma,S2MM_STATUS_REGISTER); 
    get_status(mm2s_status,"MM2S"); 
    get_status(s2mm_status,"S2MM"); 

    /*********************************************************************/
    // Any code after this point, save for a print function, 
    // breaks the write function (line 223) below. 
    //Specifically, it goes from correctly writing TRANSFER_INTS = 256 
    //to writing 0 to "new_socket"
    //????
    /*********************************************************************/


    /*********************************************************************/
    // Open a server 
    /*********************************************************************/
    //Define variables 
    int new_socket,c; 
    int socket_desc; 
    struct sockaddr_in created_server_addr, client_addr; 
    //Create Socket 
    socket_desc = open_socket(socket_desc); 
    //Create Server 
    created_server_addr = server_structure(created_server_addr); 
    //Bind Socket 
    bind_socket(socket_desc,created_server_addr); 
    //Listen
    listen(socket_desc,3); 
    puts("Waiting for incoming connections..."); 
    //Transfer Data over socket 
    while(new_socket=accept(socket_desc,(struct sockaddr *)&client_addr, (socklen_t*)&c))
    {
        puts("Connection Accepted.\n"); 
        printf("Transfer Size: %d\n",TRANSFER_INTS);
        uint32_t htonl_TRANSFER_INTS = htonl(TRANSFER_INTS);  
        write(new_socket, &htonl_TRANSFER_INTS,sizeof(htonl_TRANSFER_INTS));    
        printf("Write Data (Destination memory block): \n"); 
        close(new_socket); 
        break; 
    }
    close(socket_desc); 
    /*********************************************************************/
}

Я также включил файл "server_library.h" для справки, который я написал, чтобы немного упростить процесс запуска сокета. Я могу предоставить клиентский код Python по запросу, но я уже беспокоюсь, что это слишком много кода, чтобы его уже просеять.

#ifndef MY_HEADER_H
#define MY_HEADER_H 

//Start/open Socket 
int open_socket(int socket_desc)
{
    int option = 1; 
    socket_desc = socket(AF_INET,SOCK_STREAM,0); 
    if(socket_desc == -1)
    {
        printf("Could not create socket\n"); 
    }
    //This stupid line fixes binds failing 
    setsockopt(socket_desc,SOL_SOCKET,SO_REUSEADDR,(void *)&option,sizeof(option)); 
    return socket_desc; 
}
//Prepare server structure 
struct sockaddr_in server_structure(struct sockaddr_in server_addr)
{
    server_addr.sin_family = AF_INET; 
    server_addr.sin_addr.s_addr = INADDR_ANY; 
    server_addr.sin_port = htons(8888); 
    return server_addr; 
}
//Bind Socket
void bind_socket(int socket_desc, struct sockaddr_in server_addr)
{

    if(bind(socket_desc,(struct sockaddr *)&server_addr, sizeof(server_addr))<0)
    {
        puts("Bind Failed\n"); 
    }else{
        puts("Bind Done\n"); 
    }

}

//Send Message (uint32_t)
//Doesn't Work I dunno why 
void send_int(uint32_t message, int socket) 
{
    message = htonl(message);
    write(socket, &message, sizeof(message)); 
}


#endif 

Мне очень жаль, что я так расплывчен и выбрасываю столько кода, у меня просто нет даже идей о том, как диагностировать эту проблему, не говоря уже о том, чтобы сузить причину.

В любом случае, спасибо за помощь. Я рад предоставить как можно больше дополнительной информации.

1 Ответ

0 голосов
/ 06 ноября 2018

Когда изменение кода несвязанным образом нарушает работу программы, вот несколько вещей, которые нужно проверить: 1. Переполнение стека (это чаще встречается в микропрограммном / встроенном коде микропроцессоров, но может произойти, особенно с рекурсией, или если вы помещаете большие массивы и тому подобное в стек) 2. Дикие указатели, недопустимые записи в массивы или строки и т. Д., Которые приводят к перезаписи памяти (изменение кода несвязанным способом может изменить структуру памяти так, что перезапись памяти будет либо безвредной, либо вредной). location) [Проверяете ли вы, что все массивы, которые вы пытаетесь выделить, успешно распределены?] [использование set_offset является кандидатами для доступа за пределы]

Вот с чего бы я начал.

И, конечно же, включение предупреждений компилятора и проверка возвращаемых значений из всех вызовов функций, которые их имеют.

Если вы выполните все вышеперечисленное, вы либо обнаружите ошибку, либо сможете предоставить нам информацию, которая поможет нам лучше помочь вам.

...