C on embedded system w/ linux kernel - mysterious adc read issue -
i'm developing on ad blackfin bf537 dsp running uclinux. have total of 32mb sd-ram available. have adc attached, can access using simple, blocking call read()
.
the interesting part of code below. running program seems work fine, nice data package can fetch sd-card , plot. however, if comment out float calculation part (as noted in code), zeroes in ft_all.raw file. same occurs if change optimization level -o3 -o0.
i've tried countless combinations of sorts of things, , works, not - earlier (with minor modifications below), code work when optimization disabled. may break if add else further down in file.
my suspicion data transferred read()
-function may not have been transferred (is possible, though returns correct number of bytes?). first time initialize pointers using direct memory adresses, , have no idea how compiler reacts - perhaps missed something, here?
i've spent days on issue now, , i'm getting desperate - appreciate on one! in advance.
// clear top 16m memory data processing memset((int *)0x01000000,0x0000,(size_t)size_16m); /* prep pointers data processing */ int16_t *buffer; int16_t *buf16i, *buf16q; buffer = (int16_t *)(0x1000000); buf16i = (int16_t *)(0x1600000); buf16q = (int16_t *)(0x1680000); /* read data adc */ int rbytes = read(sportfd, (int16_t*)buffer, 0x200000); if (rbytes != 0x200000) { printf("could not sample data! %x\n",rbytes); goto end; } else { printf("read %x bytes\n",rbytes); } file *outfd; int wbytes; /* commenting region results in zeroes in ft_all.raw */ float a,b; int c; b = 0; (c = 0; c < 1000; c++) { = c; b = b+pow(a,3); } printf("b %.2f\n",b); /* 12 lsbs of each 32-bit word actual data. * first 20 bits of nothing, 12 bits i, 20 bits * nothing, 12 bits q, etc... * below, , q parts scaled factor of 16 * , extracted buf16i , buf16q. * */ int32_t *buf32; buf32 = (int32_t *)buffer; uint32_t = 0; uint32_t n = 0; while (n < 0x80000) { buf16i[i] = buf32[n] << 4; n++; buf16q[i] = buf32[n] << 4; i++; n++; } printf("saving /mnt/sd/d/ft_all.raw..."); outfd = fopen("/mnt/sd/d/ft_all.raw", "w+"); if (outfd == null) { printf("could not open file.\n"); } wbytes = fwrite((int*)0x1600000, 1, 0x100000, outfd); fclose(outfd); if (wbytes < 0x100000) { printf("wbytes not correct (= %d) \n", (int)wbytes); } printf(" done.\n");
edit: code seems work if use read() read data simple file rather adc. leads me believe rather hacky-looking code when extracting , q parts of input working intended. inspecting assembly generated compiler confirms this.
i'm trying in touch developer of adc driver see if has explanation of behaviour.
the adc connected through sport, , opened such:
sportfd = open("/dev/sport1", o_rdwr); ioctl(sportfd, sport_ioc_config, spconf);
and here options used when configuring sport:
spconf->int_clk = 1; spconf->word_len = 32; spconf->serial_clk = sport_clk; spconf->fsync_clk = sport_clk/34; spconf->fsync = 1; spconf->late_fsync = 1; spconf->act_low = 1; spconf->dma_enabled = 1; spconf->tckfe = 0; spconf->rckfe = 1; spconf->txse = 0; spconf->rxse = 1;
a bfin_sport.h file analog devices included: https://gist.github.com/tausen/5516954
update after long night of debugging previous developer on project, turned out issue not related code shown above @ all. chris suggested, indeed issue sport driver , adc configuration.
while debugging, error messaged appeared whenever data "broken": bfin_sport: sport ffc00900 status error: tuvf
. while doesn't make sense in application, clear printing data, out of sync: data in buffer on form 0x12000000,0x34000000,...
rather 0x00000012,0x00000034,...
whenever status error shown. seems clear then, why buf16i , buf16q contained zeroes (since extracting 12 lsbs).
putting in few calls usleep()
between stages of adc initialization , configuration seems have fixed issue - i'm hoping stays way!
Comments
Post a Comment