firmware merging

updating of install script - consolidation udev into driver and adding to main install
bug_fixes_integration_tx
David Michaeli 2023-06-05 06:18:30 +00:00
rodzic 603d4664ca
commit 25851685ea
20 zmienionych plików z 42537 dodań i 49050 usunięć

Wyświetl plik

@ -8,7 +8,8 @@ NC='\033[0m' # No Color
ERROR="0"
BUILD_DIR="build"
BLOB_CREATOR_DIR="../software/utils/"
USERSPACE_SMI_DIR="../software/libcariboulite/src/caribou_smi/kernel"
[ $(id -u) = 0 ] && printf "${RED}Please do not run this script as root${NC}\n" && exit 100
@ -29,9 +30,15 @@ install() {
fi
# enter build dir and build the ko file
cd "$BUILD_DIR"
cd "${ROOT_DIR}/$BUILD_DIR"
cmake ../
make
cd ${ROOT_DIR}
# copy the outputs to internal software
${BLOB_CREATOR_DIR}generate_bin_blob ${ROOT_DIR}/$BUILD_DIR/smi_stream_dev.ko smi_stream_dev ${USERSPACE_SMI_DIR}/smi_stream_dev_gen.h
cp ${ROOT_DIR}/bcm2835_smi.h ${USERSPACE_SMI_DIR}
cp ${ROOT_DIR}/smi_stream_dev.h ${USERSPACE_SMI_DIR}
# find the location to install
output_dir=$(find "/lib/modules" -type f -name "bcm2835_smi_dev*" -exec dirname {} \;)
@ -45,8 +52,8 @@ install() {
fi
printf "\n[ 3 ] ${GREEN}Installing into '${output_dir}'${NC}\n"
xz -z smi_stream_dev.ko -c > smi_stream_dev.ko.xz
sudo cp smi_stream_dev.ko.xz ${output_dir}/
xz -z ${ROOT_DIR}/$BUILD_DIR/smi_stream_dev.ko -c > ${ROOT_DIR}/$BUILD_DIR/smi_stream_dev.ko.xz
sudo cp ${ROOT_DIR}/$BUILD_DIR/smi_stream_dev.ko.xz ${output_dir}/
printf "\n[ 4 ] ${GREEN}Updating 'depmod'${NC}\n"
sudo depmod -a
@ -59,6 +66,11 @@ install() {
echo "# load SMI stream driver on startup" | sudo tee "/etc/modules-load.d/smi_stream_mod.conf" > /dev/null
echo "smi_stream_dev" | sudo tee -a "/etc/modules-load.d/smi_stream_mod.conf" > /dev/null
printf "\n[ 7 ] ${GREEN}Adding UDEV rules${NC}\n"
cd ${ROOT_DIR}/udev
sudo ./install.sh install
cd ${ROOT_DIR}
printf "${GREEN}Installation completed.${NC}\n"
}
@ -90,6 +102,9 @@ uninstall() {
sudo rm "/etc/modules-load.d/smi_stream_mod.conf"
fi
printf "\n[ 5 ] ${GREEN}Removing UDEV rules${NC}\n"
sudo udev/install.sh uninstall
printf "${GREEN}Uninstallation completed.${NC}\n"
}

Wyświetl plik

@ -20,8 +20,8 @@ uninstall() {
## FLOW
printf "${GREEN}CaribouLite UDEV Rules (un)installation${NC}\n"
printf "${GREEN}=======================================${NC}\n\n"
printf "CaribouLite UDEV Rules (un)installation\n"
printf "=======================================\n\n"
if [ "$1" == "install" ]; then
install
@ -32,6 +32,6 @@ elif [ "$1" == "uninstall" ]; then
exit 0
else
printf "${CYAN}Usage: $0 [install|uninstall]${NC}\n"
printf "Usage: $0 [install|uninstall]\n"
exit 1
fi

Wyświetl plik

@ -5,7 +5,7 @@ pcf_file = ./io.pcf
top.bin:
yosys -p 'synth_ice40 -top top -json $(filename).json -blif $(filename).blif' -p 'ice40_opt' -p 'fsm_opt' $(filename).v
#nextpnr-ice40 --lp1k --package qn84 --json $(filename).json --pcf $(pcf_file) --asc $(filename).asc
nextpnr-ice40 --lp1k --package qn84 --json $(filename).json --pcf $(pcf_file) --asc $(filename).asc --freq 80 --parallel-refine --opt-timing --placer-heap-timingweight 10
nextpnr-ice40 --lp1k --package qn84 --json $(filename).json --pcf $(pcf_file) --asc $(filename).asc --freq 64 --parallel-refine --opt-timing --timing-allow-fail
#nextpnr-ice40 --json blinky.json --pcf blinky.pcf --asc blinky.asc --gui
icepack $(filename).asc $(filename).bin

Wyświetl plik

@ -5,7 +5,7 @@ module lvds_rx (
input i_fifo_full,
output o_fifo_write_clk,
output o_fifo_push,
output reg o_fifo_push,
output reg [31:0] o_fifo_data,
input i_sync_input,
output [ 1:0] o_debug_state
@ -22,7 +22,6 @@ module lvds_rx (
reg [2:0] r_phase_count;
reg r_sync_input;
// Initial conditions
initial begin
r_state_if = state_idle;
@ -45,25 +44,23 @@ module lvds_rx (
state_idle: begin
if (i_ddr_data == modem_i_sync) begin
r_state_if <= state_i_phase;
o_fifo_data <= {30'b000000000000000000000000000000, i_ddr_data};
o_fifo_data[1:0] <= 2'b10;
r_sync_input <= i_sync_input; // mark the sync input for this sample
end
r_phase_count <= 3'b111;
r_phase_count <= 3'b110;
o_fifo_push <= 1'b0;
end
state_i_phase: begin
if (r_phase_count == 3'b000) begin
if (r_phase_count == 3'b111) begin
if (i_ddr_data == modem_q_sync) begin
r_phase_count <= 3'b110;
r_state_if <= state_q_phase;
end else begin
r_state_if <= state_idle;
end
end else begin
r_phase_count <= r_phase_count - 1;
end
end
r_phase_count <= r_phase_count - 1;
o_fifo_push <= 1'b0;
o_fifo_data <= {o_fifo_data[29:0], i_ddr_data};
end
@ -72,13 +69,12 @@ module lvds_rx (
if (r_phase_count == 3'b000) begin
o_fifo_push <= ~i_fifo_full;
r_state_if <= state_idle;
o_fifo_data <= {o_fifo_data[29:0], i_ddr_data[1], 1'b0};
end else begin
o_fifo_push <= 1'b0;
r_phase_count <= r_phase_count - 1;
o_fifo_data <= {o_fifo_data[29:0], i_ddr_data};
end
o_fifo_data <= {o_fifo_data[29:0], i_ddr_data};
r_phase_count <= r_phase_count - 1;
end
endcase
end

Wyświetl plik

@ -10,8 +10,6 @@ module sys_ctrl
input i_fetch_cmd,
input i_load_cmd,
input [7:0] i_error_list,
// controls output
output o_debug_fifo_push,
output o_debug_fifo_pull,
@ -62,7 +60,6 @@ module sys_ctrl
ioc_module_version: o_data_out <= module_version;
ioc_system_version: o_data_out <= system_version;
ioc_manu_id: o_data_out <= manu_id;
ioc_error_state: o_data_out <= i_error_list;
endcase
end
//=============================================

Plik diff jest za duży Load Diff

Plik binarny nie jest wyświetlany.

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -138,11 +138,9 @@ module top (
.i_cs(w_cs[0]),
.i_fetch_cmd(w_fetch),
.i_load_cmd(w_load),
.i_error_list(8'b00000000),
.o_debug_fifo_push(w_debug_fifo_push),
.o_debug_fifo_pull(w_debug_fifo_pull),
.o_debug_smi_test(w_debug_smi_test),
.o_debug_fifo_push(),
.o_debug_fifo_pull(),
.o_debug_smi_test(),
);
wire w_debug_fifo_push;
@ -163,12 +161,12 @@ module top (
// Digital interfaces
.i_button(i_button),
.i_config(i_config),
.o_led0 (o_led0),
.o_led1 (o_led1),
.o_led0 (/*o_led0*/),
.o_led1 (/*o_led1*/),
.o_pmod (),
// Analog interfaces
.o_mixer_fm(o_mixer_fm),
.o_mixer_fm(/*o_mixer_fm*/),
.o_rx_h_tx_l(o_rx_h_tx_l),
.o_rx_h_tx_l_b(o_rx_h_tx_l_b),
.o_tr_vc1(o_tr_vc1),
@ -176,9 +174,12 @@ module top (
.o_tr_vc2(o_tr_vc2),
.o_shdn_tx_lna(o_shdn_tx_lna),
.o_shdn_rx_lna(o_shdn_rx_lna),
.o_mixer_en(o_mixer_en)
.o_mixer_en(/*o_mixer_en*/)
);
assign o_led0 = i_smi_a2;
assign o_led1 = i_smi_a3;
//=========================================================================
// CONBINATORIAL ASSIGNMENTS
//=========================================================================
@ -244,9 +245,6 @@ module top (
.D_IN_1(w_lvds_rx_24_d1)
); // the 180 deg data output
// TODO!!!: w_lvds_rx_24_d1's route reports long routing. We need to put a register between it and the
// Consumer: lvds_rx_24_inst
// Differential 0.9GHz I/Q DDR signal
SB_IO #(
.PIN_TYPE (6'b000000), // Input only, DDR mode (sample on both pos edge and
@ -287,6 +285,22 @@ module top (
.D_OUT_1(w_lvds_tx_d0)
);
/*SB_IO #(
.PIN_TYPE(6'b0111_01),
) tx_clk_neg (
.PACKAGE_PIN(o_iq_tx_clk_n),
.OUTPUT_CLK(lvds_clock_buf),
.D_OUT_0(lvds_clock_buf),
);
SB_IO #(
.PIN_TYPE(6'b0101_01),
) tx_clk_pos (
.PACKAGE_PIN(o_iq_tx_clk_p),
.OUTPUT_CLK(lvds_clock_buf),
.D_OUT_0(lvds_clock_buf),
);*/
// Logic on a clock signal is very bad - try to use a dedicated
// SB_IO
assign o_iq_tx_clk_p = lvds_clock_buf;
@ -310,7 +324,7 @@ module top (
wire [31:0] w_rx_24_fifo_data;
lvds_rx lvds_rx_09_inst (
.i_rst_b (i_rst_b),
.i_rst_b (1'b1/*i_rst_b*/),
.i_ddr_clk(lvds_clock_buf),
.i_ddr_data({w_lvds_rx_09_d0, w_lvds_rx_09_d1}),
@ -325,10 +339,10 @@ module top (
);
lvds_rx lvds_rx_24_inst (
.i_rst_b (i_rst_b),
.i_rst_b (1'b1/*i_rst_b*/),
.i_ddr_clk(lvds_clock_buf),
.i_ddr_data({w_lvds_rx_24_d0, w_lvds_rx_24_d1}),
.i_ddr_data({!w_lvds_rx_24_d0, !w_lvds_rx_24_d1}),
.i_fifo_full(w_rx_fifo_full),
.o_fifo_write_clk(w_rx_24_fifo_write_clk),
@ -339,7 +353,7 @@ module top (
.o_debug_state()
);
wire w_rx_fifo_write_clk = (channel == 1'b0) ? w_rx_09_fifo_write_clk : w_rx_24_fifo_write_clk;
wire w_rx_fifo_write_clk = lvds_clock_buf; //(channel == 1'b0) ? w_rx_09_fifo_write_clk : w_rx_24_fifo_write_clk;
wire w_rx_fifo_push = (channel == 1'b0) ? w_rx_09_fifo_push : w_rx_24_fifo_push;
wire [31:0] w_rx_fifo_data = (channel == 1'b0) ? w_rx_09_fifo_data : w_rx_24_fifo_data;
wire w_rx_fifo_pull;
@ -348,16 +362,17 @@ module top (
wire w_rx_fifo_empty;
wire channel;
assign channel = i_smi_a3;
complex_fifo #(
.ADDR_WIDTH(10), // 1024 samples
.DATA_WIDTH(16), // 2x16 for I and Q
) rx_fifo (
.wr_rst_b_i(i_rst_b),
.wr_rst_b_i(1'b1/*i_rst_b*/),
.wr_clk_i(w_rx_fifo_write_clk),
.wr_en_i(w_rx_fifo_push),
.wr_data_i(w_rx_fifo_data),
.rd_rst_b_i(i_rst_b),
.rd_rst_b_i(1'b1/*i_rst_b*/),
.rd_clk_i(w_clock_sys),
.rd_en_i(w_rx_fifo_pull),
.rd_data_o(w_rx_fifo_pulled_data),
@ -373,9 +388,8 @@ module top (
wire w_lvds_tx_d0; // 0 degree
wire w_lvds_tx_d1; // 180 degree
lvds_tx lvds_tx_inst (
.i_rst_b(i_rst_b),
.i_rst_b(1'b1/*i_rst_b*/),
.i_ddr_clk(lvds_clock_buf),
.o_ddr_data({w_lvds_tx_d0, w_lvds_tx_d1}),
.i_fifo_empty(w_tx_fifo_empty),
@ -401,13 +415,13 @@ module top (
.DATA_WIDTH(16), // 2x16 for I and Q
) tx_fifo (
// smi clock is writing
.wr_rst_b_i(i_rst_b),
.wr_rst_b_i(1'b1/*i_rst_b*/),
.wr_clk_i(w_tx_fifo_clock),
.wr_en_i(w_tx_fifo_push),
.wr_data_i(w_tx_fifo_data),
// lvds clock is pulling (reading)
.rd_rst_b_i(i_rst_b),
.rd_rst_b_i(1'b1/*i_rst_b*/),
.rd_clk_i(w_tx_fifo_read_clk),
.rd_en_i(w_tx_fifo_pull),
.rd_data_o(w_tx_fifo_pulled_data),
@ -445,7 +459,7 @@ module top (
.i_smi_data_in(w_smi_data_input),
.o_smi_read_req(w_smi_read_req),
.o_smi_write_req(w_smi_write_req),
.o_channel(channel),
.o_channel(/*channel*/),
.i_smi_test(1'b0/*w_debug_smi_test*/),
.o_cond_tx(),
.o_address_error()

Wyświetl plik

@ -1,5 +1,8 @@
#! /bin/bash
## --------------------------------------------------------------------
## Variables
## --------------------------------------------------------------------
ROOT_DIR=`pwd`
SOAPY_UTILS_EXE=SoapySDRUtil
RED='\033[0;31m'
@ -10,21 +13,26 @@ ERROR="0"
[ $(id -u) = 0 ] && echo "Please do not run this script as root" && exit 100
# update the git repo on develop_R1 branch to include sub-modules
## --------------------------------------------------------------------
## update the git repo on develop_R1 branch to include sub-modules
## --------------------------------------------------------------------
printf "\n[ 1 ] ${GREEN}CaribouLite Git Repo${NC}\n"
#git checkout develop_R1
git pull
git submodule init
git submodule update
## --------------------------------------------------------------------
## kernel module dev dependencies
## --------------------------------------------------------------------
printf "\n[ 2 ] ${GREEN}Updating system and installing dependencies...${NC}\n"
sudo apt-get update
sudo apt-get -y install raspberrypi-kernel-headers module-assistant pkg-config libncurses5-dev cmake git libzmq3-dev
sudo apt-get -y install swig avahi-daemon libavahi-client-dev python3-distutils libpython3-dev
sudo depmod -a
# clone SoapySDR dependencies
## --------------------------------------------------------------------
## clone SoapySDR dependencies
## --------------------------------------------------------------------
printf "\n[ 3 ] ${GREEN}Checking Soapy SDR installation ($SOAPY_UTILS_EXE)...${NC}\n"
SOAPY_UTIL_PATH=`which $SOAPY_UTILS_EXE`
@ -80,7 +88,9 @@ else
fi
fi
## --------------------------------------------------------------------
## Main Software
## --------------------------------------------------------------------
printf "\n[ 5 ] ${GREEN}Compiling main source...${NC}\n"
printf "${CYAN}1. External Tools...${NC}\n"
cd $ROOT_DIR/software/utils
@ -101,9 +111,6 @@ printf "${CYAN}3. SMI kernel module & udev...${NC}\n"
cd $ROOT_DIR/driver
./install.sh
cd ..
cd udev
./install.sh
cd ..
printf "${CYAN}4. Main software...${NC}\n"
cd $ROOT_DIR
@ -112,7 +119,9 @@ cmake $ROOT_DIR/software/libcariboulite/
make
sudo make install
# Configuration File
## --------------------------------------------------------------------
## Configuration File - RPI /boot/config.txt
## --------------------------------------------------------------------
printf "\n[ 6 ] ${GREEN}Environmental Settings...${NC}\n"
printf "${GREEN}1. SPI configuration... "
DtparamSPI=`cat /boot/config.txt | grep "dtparam=spi" | xargs | cut -d\= -f1`

Wyświetl plik

@ -1,57 +0,0 @@
cmake_minimum_required(VERSION 3.15)
project(smi_modules VERSION 0.1.0 LANGUAGES C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
# Module info
add_definitions(-D__KERNEL__ -DMODULE)
# Find the kernel release
execute_process(
COMMAND uname -r
OUTPUT_VARIABLE KERNEL_RELEASE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Find the headers
find_path(
KERNELHEADERS_DIR
include/linux/user.h
PATHS /usr/src/linux-headers-${KERNEL_RELEASE}
)
message(STATUS "Kernel release: ${KERNEL_RELEASE}")
message(STATUS "Kernel headers: ${KERNELHEADERS_DIR}")
function(compile_module obj)
set(TARGET_NAME ${obj})
add_custom_target(${TARGET_NAME} ALL cp -f ${CMAKE_CURRENT_SOURCE_DIR}/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.h ${CMAKE_CURRENT_BINARY_DIR}/
COMMAND echo "compiling module ${obj}.ko...")
list(LENGTH ARGN argn_len)
set(i 0)
set(depend_objlist "")
while(i LESS ${argn_len})
list(GET ARGN ${i} argn_value)
set(depend_objlist "${depend_objlist} ${argn_value}.o")
math(EXPR i "${i} + 1")
endwhile()
add_custom_command(TARGET ${TARGET_NAME}
POST_BUILD
COMMAND cp Makefile Makefile.bak
COMMAND echo "obj-m += ${obj}.o" > ${CMAKE_CURRENT_BINARY_DIR}/Makefile
COMMAND echo "MY_CFLAGS += -g -DDEBUG" >> ${CMAKE_CURRENT_BINARY_DIR}/Makefile
COMMAND echo "ccflags-y += -g -DDEBUG" >> ${CMAKE_CURRENT_BINARY_DIR}/Makefile
COMMAND echo "CC += -g -DDEBUG" >> ${CMAKE_CURRENT_BINARY_DIR}/Makefile
COMMAND echo "${obj}-objs:=${depend_objlist}" >> ${CMAKE_CURRENT_BINARY_DIR}/Makefile
COMMAND make -C ${KERNELHEADERS_DIR} M=${CMAKE_CURRENT_BINARY_DIR} modules EXTRA_CFLAGS="-g"
#>>NO DEBUG OPTION<< COMMAND make -C ${KERNELHEADERS_DIR} M=${CMAKE_CURRENT_BINARY_DIR} modules
COMMAND ../../../../../utils/generate_bin_blob ${obj}.ko ${obj} ../${obj}_gen.h
COMMAND cp Makefile Makefile.op
COMMAND cp Makefile.bak Makefile
)
endfunction()
#compile_module(bcm2835_smi)
compile_module(smi_stream_dev)
#compile_module(bcm2835_smi_dev)

Wyświetl plik

@ -1,2 +1,3 @@
# README
TODO...
This directory contains generated files.
Do not edit directly.
Editing can be done through the "[root]/driver/" directory.

Wyświetl plik

@ -1,166 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <pthread.h>
#include "../caribou_smi.h"
#include "bcm2835_smi.h"
#define SMI_STREAM_IOC_GET_NATIVE_BUF_SIZE _IO(BCM2835_SMI_IOC_MAGIC, 3)
#define SMI_STREAM_IOC_SET_NON_BLOCK_READ _IO(BCM2835_SMI_IOC_MAGIC, 4)
#define SMI_STREAM_IOC_SET_NON_BLOCK_WRITE _IO(BCM2835_SMI_IOC_MAGIC, 5)
#define SMI_STREAM_IOC_SET_STREAM_STATUS _IO(BCM2835_SMI_IOC_MAGIC, 6)
static void setup_settings (struct smi_settings *settings)
{
settings->read_setup_time = 0;
settings->read_strobe_time = 5;
settings->read_hold_time = 0;
settings->read_pace_time = 0;
settings->write_setup_time = 0;
settings->write_hold_time = 0;
settings->write_pace_time = 0;
settings->write_strobe_time = 4;
settings->data_width = SMI_WIDTH_8BIT;
settings->dma_enable = 1;
settings->pack_data = 1;
settings->dma_passthrough_enable = 1;
}
pthread_t tid;
int fd = -1;
size_t native_batch_length_bytes = 0;
int thread_running = 0;
void* read_thread(void *arg)
{
fd_set set;
int rv;
int timeout_num_millisec = 500;
uint8_t *buffer = malloc(native_batch_length_bytes);
int size_of_buf = native_batch_length_bytes;
while (thread_running)
{
while (1)
{
struct timeval timeout = {0};
FD_ZERO(&set); // clear the set mask
FD_SET(fd, &set); // add our file descriptor to the set - and only it
int num_sec = timeout_num_millisec / 1000;
timeout.tv_sec = num_sec;
timeout.tv_usec = (timeout_num_millisec - num_sec*1000) * 1000;
rv = select(fd + 1, &set, NULL, NULL, &timeout);
if(rv == -1)
{
int error = errno;
switch(error)
{
case EINTR: // A signal was caught.
continue;
case EBADF: // An invalid file descriptor was given in one of the sets.
// (Perhaps a file descriptor that was already closed, or one on which an error has occurred.)
case EINVAL: // nfds is negative or the value contained within timeout is invalid.
case ENOMEM: // unable to allocate memory for internal tables.
default: goto exit;
};
}
else if (rv == 0)
{
printf("Read poll timeout\n");
break;
}
else if (FD_ISSET(fd, &set))
{
int num_read = read(fd, buffer, size_of_buf);
printf("Read %d bytes\n", num_read);
break;
}
}
}
exit:
free(buffer);
return NULL;
}
int main()
{
char smi_file[] = "/dev/smi";
struct smi_settings settings = {0};
fd = open(smi_file, O_RDWR);
if (fd < 0)
{
printf("can't open smi driver file '%s'\n", smi_file);
return -1;
}
// Get the current settings
int ret = ioctl(fd, BCM2835_SMI_IOC_GET_SETTINGS, &settings);
if (ret != 0)
{
printf("failed reading ioctl from smi fd (settings)\n");
close (fd);
return -1;
}
// apply the new settings
setup_settings(&settings);
ret = ioctl(fd, BCM2835_SMI_IOC_WRITE_SETTINGS, &settings);
if (ret != 0)
{
printf("failed writing ioctl to the smi fd (settings)\n");
close (fd);
return -1;
}
// set the address to idle
ret = ioctl(fd, BCM2835_SMI_IOC_ADDRESS, caribou_smi_address_idle);
if (ret != 0)
{
printf("failed setting smi address (idle / %d) to device\n", caribou_smi_address_idle);
close (fd);
return -1;
}
// get the native batch length in bytes
ret = ioctl(fd, SMI_STREAM_IOC_GET_NATIVE_BUF_SIZE, &native_batch_length_bytes);
if (ret != 0)
{
printf("failed reading native batch length, setting default\n");
native_batch_length_bytes = (1024)*(1024)/2;
}
printf("Native batch size: %u\n", native_batch_length_bytes);
// start streaming data
ret = ioctl(fd, SMI_STREAM_IOC_SET_STREAM_STATUS, 1);
// start the reader thread
thread_running = 1;
int err = pthread_create(&tid, NULL, &read_thread, NULL);
if (err != 0)
{
printf("\ncan't create thread :[%s]", strerror(err));
}
getchar();
thread_running = 0;
pthread_join(tid, NULL);
ret = ioctl(fd, SMI_STREAM_IOC_SET_STREAM_STATUS, 0);
close (fd);
return 0;
}