Я пишу программу на 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
Мне очень жаль, что я так расплывчен и выбрасываю столько кода, у меня просто нет даже идей о том, как диагностировать эту проблему, не говоря уже о том, чтобы сузить причину.
В любом случае, спасибо за помощь. Я рад предоставить как можно больше дополнительной информации.