首页 > 解决方案 > 向 c 程序添加任何单行代码,写入套接字失败

问题描述

我正在编写 ac 程序,旨在通过套接字将数据传输到 python 客户端。我遇到了一个非常奇怪的问题,即在程序中的某个点之后添加几乎任何代码行时,写入创建的套接字会停止工作。

扩展这个问题:我正在尝试将任意数字写入套接字,例如 256。这工作正常,即 python 客户端从 c 服务器接收数字 256,只要没有超出get_status(s2mm_status,"S2MM");If的任何命令除了这一点之外还有任何这样的命令,“0”被写入套接字,而不是我指定的任何数字(例如 256)。任何像声明“ int i”这样简单的东西都会导致这种行为。

不用说,我很困惑。我想知道是我使用了太多内存还是什么?我只是不知道如何诊断问题。无论如何,我已经提供了下面的代码。对不起,长度,我真的不知道什么是相关的或不相关的。

提供代码的基本解释:创建了许多内存映射,以便我可以将特定值写入寄存器,这会启动设备上 ADC 的数据记录,将此数据写入内存,然后将其传递给通过套接字到 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 

很抱歉在这里含糊不清并抛出了这么多代码,我什至对如何诊断这个问题都没有任何想法,更不用说开始缩小原因了。

无论如何,谢谢你的帮助。我很乐意提供尽可能多的额外信息。

标签: csocketsmemoryembedded

解决方案


当以不相关的方式更改代码会破坏程序时,需要检查以下内容: 1. 堆栈溢出(这在微处理器上的固件/嵌入式代码中更为常见,但尤其是在递归或放置大型数组等时可能发生2. 导致内存覆盖的野指针、越界写入数组或字符串等(以不相关的方式更改代码可能会更改内存布局,使得内存覆盖处于无害或有害位置)[您是否检查您尝试分配的所有数组都已成功分配?] [set_offset 的使用是越界访问的候选者]

那就是我要开始的地方。

当然,打开编译器警告并检查所有具有它们的函数调用的返回值。

如果您完成上述所有操作,您将找到错误,或者您可以向我们提供有助于我们更好地帮助您的信息。


推荐阅读