How to get physical page in Solaris 11 - debugging

I am using mdb on Solaris 11. I have opened a file by using " tail -f file_name" command in another ssh session. I got the pid of tail command and Vnode of the file opened by tail command. After getting the Vnode, I fired "walk page" on this file. Unfortunately, I am not getting any pages in walk. How to get Virtual Pages and Physical pages?

I have done following.
1) Opened the file with 'tail -f'.
2) Get the pid in mdb. Get the Vnode of the opened file.
3) Get the page_t from Vnode_t of the opened file.
4) Left shift to the page number with 0xD, it will give pp2pa effect.
Here are the dcmds in mdb.
> ::pgrep tail
S PID PPID PGID SID UID FLAGS ADDR NAME
R 2889 2882 2889 2850 0 0x4a004000 0000060013f29890 tail
> 0000060013f29890::pfiles
FD TYPE VNODE INFO
0 REG 00000600162f6740 /export/home/chaitanya/OpenSolaris/README.opensolaris
1 CHR 000006001a290400 /devices/pseudo/pts#0:2
2 CHR 000006001a290400 /devices/pseudo/pts#0:2
> 00000600162f6740::walk page
70004781480
700040b0400
> 70004781480::print -at page_t
{
70004781480 u_offset_t p_offset = 0x2000
70004781488 struct vnode *p_vnode = 0x600162f6740
70004781490 selock_t p_selock = 0
70004781494 uint_t p_vpmref = 0x11d9d
70004781498 struct page *p_hash = 0x70002f79b00
700047814a0 struct page *p_vpnext = 0x700040b0400
700047814a8 struct page *p_vpprev = 0x700040b0400
700047814b0 struct page *p_next = 0x70004781480
700047814b8 struct page *p_prev = 0x70004781480
700047814c0 ushort_t p_lckcnt = 0
700047814c2 ushort_t p_cowcnt = 0
700047814c4 kcondvar_t p_cv = {
700047814c4 ushort_t _opaque = 0
}
700047814c6 kcondvar_t p_io_cv = {
700047814c6 ushort_t _opaque = 0
}
700047814c8 uchar_t p_iolock_state = 0
700047814c9 volatile uchar_t p_szc = 0
700047814ca uchar_t p_fsdata = 0
700047814cb uchar_t p_state = 0x40
700047814cc uchar_t p_nrm = 0x2
700047814cd uchar_t p_vcolor = 0x2
700047814ce uchar_t p_index = 0
700047814cf uchar_t p_toxic = 0
700047814d0 void *p_mapping = 0
700047814d8 pfn_t p_pagenum = 0x80f029
700047814e0 uint_t p_share = 0
700047814e4 uint_t p_sharepad = 0
700047814e8 uint_t p_slckcnt = 0
700047814ec uint_t p_kpmref = 0
700047814f0 struct kpme *p_kpmelist = 0
700047814f8 kmutex_t p_ilock = {
700047814f8 void *[1] _opaque = [ 0 ]
}
}
Left shift to the page number 0x80f029 with 0xD, it will give pp2pa
> 101E052000,100::dump -p
\/ 1 2 3 4 5 6 7 8 9 a b c d e f v123456789abcdef
101e052000: 75742069 742e2020 4e6f7220 646f2079 ut it. Nor do y
101e052010: 6f752068 61766520 746f206b 65657020 ou have to keep
101e052020: 7468650a 20202020 206e616d 65206f70 the. name op
101e052030: 656e736f 6c617269 732e7368 2c206275 ensolaris.sh, bu
101e052040: 74207468 61742773 20746865 206e616d t that's the nam
101e052050: 65207765 276c6c20 75736520 696e2074 e we'll use in t
101e052060: 68657365 206e6f74 65732e0a 0a202020 hese notes...
101e052070: 20205468 656e206d 616b6520 74686520 Then make the
101e052080: 666f6c6c 6f77696e 67206368 616e6765 following change
101e052090: 7320696e 20796f75 72206f70 656e736f s in your openso
101e0520a0: 6c617269 732e7368 3a0a0a20 20202d20 laris.sh:.. -
101e0520b0: 6368616e 67652047 41544520 746f2074 change GATE to t
101e0520c0: 6865206e 616d6520 6f662074 68652074 he name of the t
101e0520d0: 6f702d6c 6576656c 20646972 6563746f op-level directo
101e0520e0: 72792028 652e672e 2c0a2020 20202022 ry (e.g.,. "
101e0520f0: 74657374 77732229 2e0a0a20 20202d20 testws")... -

Related

How can I fix the Error of MSC Bootloader with ATxmega32a4?

I'm trying to upload a .hex file via Uart into an ATxmega32a4. I'm using BASCOM IDE and Programmed my MCU with the sample code which is available in sample folder of Bascom (I have attached my code). So I'm using MSC Bootloader Wizard in Bascom to upload my code but unfortunately it has error 6006. I increased timeout but the problem is not fixed.
I monitored serial port as you can find it in attachments.
Could anyone help?
'----------------------------------------------------------------
' (c) 1995-2020, MCS
' BootloaderXmega32A4.bas
' This sample demonstrates how you can write your own bootloader
' in BASCOM BASIC for the XMEGA
'-----------------------------------------------------------------
'The loader is supported from the IDE
$crystal = 29491200 ' xmega128 is running on 32 MHz
$regfile = "xm32a4def.dat"
$hwstack = 40
$swstack = 40
$framesize = 40
'first enabled the osc of your choice
''Config Osc = Disabled , 32mhzosc = Enabled 'internal 2 MHz and 32 MHz enabled
Config Osc = Enabled , 32mhzosc = Enabled , Extosc = Enabled
'configure the systemclock
''Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1 ' we will use 32 MHz and divide by 1 to end up with 32 MHz
Config Sysclock = External , Prescalea = 1 , Prescalebc = 1_1
$loader = &H4000 ' bootloader starts after the application
'this sample uses 38400 baud. To be able to use the Xplain which has a bootloader working at 9600 baud you need to use 9600 baud
''Config Com1 = 38400 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 ' use USART C0
'COM0-USARTC0, COM1-USARTC2, COM2-USARTD0. etc.
''Config Portc.3 = Output 'define TX as output
''Config Pinc.2 = Input
Config Com3 = 115200 , Mode = Asynchroneous , Parity = EVEN , Stopbits = 1 , Databits = 8
Open "COM3:" For Binary As #1
Config PortD.3 = Output 'define TX as output
Config PinD.2 = Input
Const Maxwordbit = 7 ' Z7 is maximum bit '
Const Maxword =(2 ^ Maxwordbit) * 2 '128
Const Maxwordshift = Maxwordbit + 1
Const Cdebug = 0 ' leave this to 0
'Dim the used variables
Dim Bstatus As Byte , Bretries As Byte , Bmincount As Byte , Bblock As Byte , Bblocklocal As Byte
Dim Bcsum1 As Byte , Bcsum2 As Byte , Buf(128) As Byte , Csum As Byte
Dim J As Byte , Spmcrval As Byte ' self program command byte value
Dim Z As Long 'this is the Z pointer word
Dim Vl As Byte , Vh As Byte ' these bytes are used for the data values
Dim Wrd As Word , Page As Word 'these vars contain the page and word address
Disable Interrupts 'we do not use ints
'We start with receiving a file. The PC must send this binary file
'some constants used in serial com
Const Nak = &H15
Const Ack = &H06
Const Can = &H18
$timeout = 300000 'we use a timeout
'When you get LOADER errors during the upload, increase the timeout value
'for example at 16 Mhz, use 200000
Bretries = 5 : Bmincount = 3 'we try 10 times and want to get 123 at least 3 times
Do
Bstatus = Waitkey(#1) 'wait for the loader to send a byte
If Bstatus = 123 Then 'did we received value 123 ?
If Bmincount > 0 Then
Decr Bmincount
Else
Print #1, Chr(bstatus);
Goto Loader ' yes so run bootloader
End If
Else 'we received some other data
If Bretries > 0 Then 'retries left?
Bmincount = 3
Decr Bretries
Else
Rampz = 0
Goto Proces_reset 'goto the normal reset vector at address 0
End If
End If
Loop
'this is the loader routine. It is a Xmodem-checksum reception routine
Loader:
Do
Bstatus = Waitkey(#1)
Loop Until Bstatus = 0
Spmcrval = &H20 : Gosub Do_spm ' erase all app pages
Bretries = 10 'number of retries
Do
Csum = 0 'checksum is 0 when we start
Bblocklocal = 1
Print #1, Chr(bstatus); ' firt time send a nack
Do
Bstatus = Waitkey(#1) 'wait for statuse byte
Select Case Bstatus
Case 1: ' start of heading, PC is ready to send
Csum = 1 'checksum is 1
Bblock = Waitkey(#1) : Csum = Csum + Bblock 'get block
Bcsum1 = Waitkey(#1) : Csum = Csum + Bcsum1 'get checksum first byte
For J = 1 To 128 'get 128 bytes
Buf(j) = Waitkey(#1) : Csum = Csum + Buf(j)
Next
Bcsum2 = Waitkey(#1) 'get second checksum byte
If Bblocklocal = Bblock Then 'are the blocks the same?
If Bcsum2 = Csum Then 'is the checksum the same?
Gosub Writepage 'yes go write the page
Print #1, Chr(bstatus); 'acknowledge
Incr Bblocklocal 'increase local block count
Else 'no match so send nak
Print #1, Chr(bstatus);
End If
Else
Print #1, Chr(bstatus); 'blocks do not match
End If
Case 4: ' end of transmission , file is transmitted
If Wrd > 0 Then 'if there was something left in the page
Wrd = 0 'Z pointer needs wrd to be 0
Spmcrval = &H24 : Gosub Do_spm 'write page
End If
Print #1, Chr(bstatus); ' send ack and ready
Waitms 20
Goto Proces_reset
Case &H18: ' PC aborts transmission
Goto Proces_reset ' ready
Case 123 : Exit Do 'was probably still in the buffer
Case 124 : Exit Do
Case Else
Exit Do ' no valid data
End Select
Loop
If Bretries > 0 Then 'attempte left?
Waitms 1000
Decr Bretries 'decrease attempts
Else
Goto Proces_reset 'reset chip
End If
Loop
'write one or more pages
Writepage:
For J = 1 To 128 Step 2 'we write 2 bytes into a page
Vl = Buf(j) : Vh = Buf(j + 1) 'get Low and High bytes
!lds r0, {vl} 'store them into r0 and r1 registers
!lds r1, {vh}
Spmcrval = &H23 : Gosub Do_spm 'write value into page at word address
Wrd = Wrd + 2 ' word address increases with 2 because LS bit of Z is not used
If Wrd = Maxword Then ' page is full
Wrd = 0 'Z pointer needs wrd to be 0
Spmcrval = &H24 : Gosub Do_spm 'write page
Page = Page + 1 'next page
End If
Next
Return
Do_spm:
Z = Page 'make equal to page
Shift Z , Left , Maxwordshift 'shift to proper place
Z = Z + Wrd 'add word
!lds r30,{Z}
!lds r31,{Z+1}
#if _romsize > 65536
!lds r24,{Z+2}
!sts rampz,r24 ' we need to set rampz also for the M128
#endif
Nvm_cmd = Spmcrval
Cpu_ccp = &H9D
!spm 'this is an asm instruction
Do_spm_busy:
!lds r23, NVM_STATUS
!sbrc r23,7 ;if busy bit is cleared skip next instruc tion
!rjmp do_spm_busy
Return
Proces_reset:
Rampz = 0
Goto _reset 'start at address 0

CAN 1 RX works in loopback mode, but not in Normal mode

I am using a STM32F413RG based custom board and trying to run some CAN bus based applications on it.
I am trying to start with CAN 1 and wrote a bare metal code using CMSIS library to transmit and receive.
Here is the code for three functions - Init,Send and Receive.
void initCAN()
{
// enable clock
// note: because CAN2 is a "slave CAN" you have to enable CAN1 clock
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
// and reset CAN1, so request reset
CAN1->MCR |= CAN_MCR_RESET;
// wait for it to say it has gone to sleep
while ((CAN1->MSR & CAN_MSR_SLAK_Msk) == 1) {}
//CAN1
// enable port A clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
__DSB();
// CAN_RX = CAN1R on PA11, so set alt function
GPIOA->MODER &= ~GPIO_MODER_MODER11_Msk;
GPIOA->MODER |= GPIO_MODER_MODER11_1;
// CAN 1 is AF9 (AFSEL 9 = 0b1001 -> bit 3 & bit 0
GPIOA->AFR[1] |= (GPIO_AFRH_AFSEL11_3 | GPIO_AFRH_AFSEL11_0);
// CAN_TX = CAN1T on PA12
GPIOA->MODER &= ~GPIO_MODER_MODER12_Msk;
GPIOA->MODER |= GPIO_MODER_MODER12_1;
// open-drain
GPIOA->OTYPER |= GPIO_OTYPER_OT_11;
GPIOA->OTYPER |= GPIO_OTYPER_OT_12;
// CAN 1 is AF9 (AFSEL 9 = 0b1001 -> bit 3 & bit 0
GPIOA->AFR[1] |= (GPIO_AFRH_AFSEL12_3 | GPIO_AFRH_AFSEL12_0);
//bring it our from sleep by setting the sleep bit in MCR to 0
CAN1->MCR &= ~CAN_MCR_SLEEP_Msk;
//if sleep ACK(SLAK) not zero, wait i.e. exited from sleep
while ((CAN1->MSR & CAN_MSR_SLAK_Msk) != 0) {}
//put CAN 1 to Init mode
CAN1->MCR |= CAN_MCR_INRQ;
// wait for it to say it has gone there
while ((CAN1->MSR & CAN_MSR_INAK_Msk) != CAN_MSR_INAK_Msk) {}
uint32_t APB1Clock = SystemCoreClock/2000000; // in MHz
CAN1->BTR = 0x00050007U;
CAN1->FMR |= CAN_FMR_FINIT;
// and make sure the CANSB value is zero
CAN1->FMR &= ~(CAN_FMR_CAN2SB_Msk);
//Give 14 filter banks to CAN 1 and 2 each
CAN1->FMR |= (((uint32_t) 14) << CAN_FMR_CAN2SB_Pos) & CAN_FMR_CAN2SB_Msk;
// set all as 32 bit filter in identifier mask mode (zeros)
CAN1->FM1R = 0;
// use all as 32 bit filter with mask
CAN1->FS1R |= CAN_FS1R_FSC_Msk;
// assign FIFO0 to CAN1, and FIFO1 to CAN2 (well, all to FIFO0, except filter 14)
CAN1->FFA1R = CAN_FFA1R_FFA14;
// make sure it is deactivated (clear FACT in CAN_FAR)
CAN1->FA1R &= ~CAN_FA1R_FACT0;
CAN1 ->FA1R &= ~CAN_FA1R_FACT14;
// setup a filter that accepts everything (w/ extended id)
// Each filter bank i (i= 0 to 27 in dual CAN configuration and i= 0 to 13 in single CAN configuration)
//is composed of two 32-bit registers, CAN_FiR\[2:1\].
CAN1->sFilterRegister[0].FR1 = CAN_F0R1_FB2;
CAN1->sFilterRegister[0].FR2 = CAN_F0R1_FB2;
CAN1->sFilterRegister[14].FR1 = CAN_F0R1_FB2;
CAN1->sFilterRegister[14].FR2 = CAN_F0R1_FB2;
// now activate filter
CAN1->FA1R |= CAN_FA1R_FACT0;
CAN1->FA1R |= CAN_FA1R_FACT14;
// take out of init mode for filters
CAN1->FMR &= ~CAN_FMR_FINIT;
//loopback mode. need to do it while on init mode
// CAN1->BTR |= CAN_BTR_LBKM;
//bring CAN1 out from init mode.
CAN1->MCR &= ~CAN_MCR_INRQ;
while ((CAN1->MSR & CAN_MSR_INAK_Msk) != 0) {}
}
void sendCAN1( uint32_t pgn, uint8_t bytes[], uint8_t len)
{
// wait for the mailbox to be empty
while ((CAN1->TSR & CAN_TSR_TME0_Msk) == 0) {};
// put this in next empty mailbox
int boxnum = (CAN1->TSR & CAN_TSR_CODE_Msk) >> CAN_TSR_CODE_Pos;
CAN1->sTxMailBox[boxnum].TDTR &= ~CAN_TDT0R_DLC_Msk;
CAN1->sTxMailBox[0].TIR = ((pgn << CAN_TI0R_EXID_Pos) & CAN_TI0R_EXID_Msk) | CAN_TI0R_IDE;
// for standard (11-bit) ids, replace the above with:
// CAN1->sTxMailBox[boxnum].TIR = ((pgn << CAN_TI0R_STID_Pos) & CAN_TI0R_STID_Msk);
CAN1->sTxMailBox[boxnum].TDHR = ((bytes[7]<<CAN_TDH0R_DATA7_Pos) |
(bytes[6]<<CAN_TDH0R_DATA6_Pos) |
(bytes[5]<<CAN_TDH0R_DATA5_Pos) | bytes[4]);
CAN1->sTxMailBox[boxnum].TDLR = ((bytes[3]<<CAN_TDL0R_DATA3_Pos) |
(bytes[2]<<CAN_TDL0R_DATA2_Pos) |
(bytes[1]<<CAN_TDL0R_DATA1_Pos) | bytes[0]);
CAN1->sTxMailBox[boxnum].TDTR = (len << CAN_TDT0R_DLC_Pos) & CAN_TDT0R_DLC_Msk;
CAN1->sTxMailBox[boxnum].TIR |= CAN_TI0R_TXRQ;
}
uint8_t recCAN1()
{
uint8_t data[8];
uint32_t pgn;
uint8_t len;
uint8_t msgcount;
static uint8_t ret = 0;
// check for any msg in FIFO
// we only use FIFO 0 here
msgcount = CAN1->RF0R & CAN_RF0R_FMP0_Msk;
ret += msgcount;
// read them out one at a time
while (msgcount > 0)
{
pgn = CAN1->sFIFOMailBox[0].RIR >> 3;
len = CAN1->sFIFOMailBox[0].RDTR & 0xF;
// NOTE: case fall through is intentional and critical
switch (len)
{
case 8:
data[7] = (CAN1->sFIFOMailBox[0].RDHR >> 24) & 0xFF;
case 7:
data[6] = (CAN1->sFIFOMailBox[0].RDHR >> 16) & 0xFF;
case 6:
data[5] = (CAN1->sFIFOMailBox[0].RDHR >> 8) & 0xFF;
case 5:
data[4] = CAN1->sFIFOMailBox[0].RDHR & 0xFF;
case 4:
data[3] = (CAN1->sFIFOMailBox[0].RDLR >> 24) & 0xFF;
case 3:
data[2] = (CAN1->sFIFOMailBox[0].RDLR >> 16) & 0xFF;
case 2:
data[1] = (CAN1->sFIFOMailBox[0].RDLR >> 8) & 0xFF;
case 1:
data[0] = CAN1->sFIFOMailBox[0].RDLR & 0xFF;
// do nothing as data is empty
}
// process as they are read
// processCAN(pgn, data, len);
// release that mailbox
CAN1->RF0R |= CAN_RF0R_RFOM0;
// update the message count
msgcount = CAN1->RF0R & CAN_RF0R_FMP0_Msk;
}
return ret;
}
Sending a packet from CAN 1 is fine. When receiving, I cannot see any status changing on the Rx Registers. But, I can see an ACK being transmitted from the TX pin upon receiving a packet when scoping the signals.
The CAN 1 Error Status is completely empty (0x0).
However, when I try the same code with Loopback mode activated, I can see a message received on the registers and my code picks it up too.
Attaching screenshots of CAN 1 RF0R register when in loopback mode which indicates reception.
This scope (Channel 0 for RX and Channel 2 for TX) shows that its receiving a message on RX and it sends back an ACK on its TX under normal mode.
I have checked the termination too and its fine. (120 ohms added. Anyway, getting an ACK, so I am thinking that's not the problem).
I am out of ideas of where I might be going wrong.
No explicit error messages. However, the Rx message is not reflecting on any one of the registers under normal mode.
From the reference manual in CAN_FMR register : to use CAN1 only: stop the clock on CAN2 and/or set the CAN_MCR.INRQ on CAN2, I haven't seen instruction that does this explicitly in your code.
Also in the comments from your code it says that you are not filtering anything but you set CAN_F0R1_FB2 in sFilterRegister thus not everything will be accepted. The ID you are sending is one of those.

SDL 2 how to check for "no modifiers" (keyboard input)

This is my attempt:
const bool MOD_NONE{SDL_GetModState() == KMOD_NONE};
if(MOD_NONE) std::cout << "none" << std::endl;
However this does not work. Why?
If I print the integer value returned by SDL_GetModState(), without pressing any modifiers the value is 4096. Also why?
Looking at the SDL (2.0.5) source code, here is the SDL_Keymod structure:
typedef enum
{
KMOD_NONE = 0x0000,
KMOD_LSHIFT = 0x0001,
KMOD_RSHIFT = 0x0002,
KMOD_LCTRL = 0x0040,
KMOD_RCTRL = 0x0080,
KMOD_LALT = 0x0100,
KMOD_RALT = 0x0200,
KMOD_LGUI = 0x0400,
KMOD_RGUI = 0x0800,
KMOD_NUM = 0x1000,
KMOD_CAPS = 0x2000,
KMOD_MODE = 0x4000,
KMOD_RESERVED = 0x8000
} SDL_Keymod;
The value 4096 you get when calling SDL_GetModState corresponds to the "Num Lock" key (which doesn't have to be physically pressed to be active, just like the Caps Lock key).
What you likely want is to check for the Alt, Shift, Ctrl and Gui keys (the Gui key is the special OS-specific key, if I'm not mistaken).
const SDL_Keymod modkeys = KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI;
const bool MOD_NONE{(SDL_GetModState() & modkeys) == KMOD_NONE};
// or simply
const auto modkeys = KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI;
const bool MOD_NONE = !(SDL_GetModState() & modkeys);

ENC28J60 returning wrong (unexpected) values

I'm trying to create my own library for the ENC28J60. Yes, I know that there are several ready to use libraries out there, but I like to do thing from scratch, so I understand what is going on, how it works.
So, I'm only at the beging and already found someting that I don't understand.
My first test was to send the RCR command to read BANK0. I've recived mixed results.
Over UART(HyperTerminal) I'm getting the following results back:
USART Ready
SPI Ready
1 RCR-ERDPTL Send: 0 "(sending RCR|ERDPTL = 0 over SPI)"
0 11111010 11111010 OK
1 101 101 OK
2 0 0 OK
3 0 0 OK
4 0 0 OK
5 0 0 OK
6 0 0 OK
7 0 0 OK
8 1000 11111010 ERROR
9 101 101 OK
10 11111111 11111111 OK
11 11111 11111 OK
12 110001 11111010 ERROR
13 110011 101 ERROR
14 0 0 OK
15 0 0 OK
The first column is the byte number or the number of the register of BANK0,
The second column is the value that I'm getting from the ENC chip(according to the datasheet),
The third is tha value I should get,
And the fouth is just a simple check to find a mismatch.
As you can see there are 3 values that do not correspond with the datasheet.
Why?
My code is the following:
#include <define.h>
#include <ENC28J60.h>
#define ENC28J60 PB3
#define ENC28J61 PB4
#define DUMMY 0x00
unsigned char i, data, data0[] = {}, data1[] = {}, data2[] = {},
data3[16] = {0b11111010, 0b00000101, 0,0,0,0,0,0,0b11111010,0b00000101,255,0b00011111,0b11111010,0b00000101,0,0};
void ENC28J60_CS(void) // ENC28J60 Select
{
SPI_PORT &= ~(1<<ENC28J60);
}
void ENC28J60_DS(void) // ENC28J60 DeSelect
{
SPI_PORT |= (1<<ENC28J60);
}
void ENC28J61_CS(void) // ENC28J60 Select
{
SPI_PORT &= ~(1<<ENC28J61);
}
void ENC28J61_DS(void) // ENC28J60 DeSelect
{
SPI_PORT |= (1<<ENC28J61);
}
void ENC28J60_SRC(void) // System Reset Command (Soft Reset)
{
ENC28J60_CS(); // Enable
SPIWR(0xFF);
ENC28J60_DS(); // Disable
_delay_ms(50);
}
int main(void)
{
_delay_ms(3000);
USART0_Init(12);
USART0_TX_String("USART Ready");
USART0_TXD(10);
USART0_TXD(13);
SPI_Init();
PORTB ^= 1<<PINB0;
USART0_TX_String("SPI Ready");
USART0_TXD(10);
USART0_TXD(13);
ENC28J60_DS();
ENC28J61_DS();
_delay_ms(250);
ENC28J60_SRC();
ENC28J61_CS(); // Enable
SPIWR(0xFF);
ENC28J61_DS(); // Disable
_delay_ms(250);
ENC28J60_CS();
SPIWR(RCR|ERDPTL);
PORTB ^= 1<<PINB0;
USART0_TX_String("1 RCR-ERDPTL Send: ");
itoa(RCR|ERDPTL, StringA, 10);
USART0_TX_String(StringA);
USART0_TXD(10);
USART0_TXD(13);
data = SPIWRD(0xFF);
for(i = 0;i<15;i++)
{
data0[i] = SPIWRD(0xFF);
}
ENC28J60_DS();
for(i = 0;i<16;i++)
{
PORTB ^= 1<<PINB0;
itoa(i, StringA, 10);
USART0_TX_String(StringA);
USART0_TXD(9);
itoa(data0[i], StringA, 2);
USART0_TX_String(StringA);
USART0_TXD(9);
USART0_TXD(9);
itoa(data3[i], StringA, 2);
USART0_TX_String(StringA);
USART0_TXD(9);
if(data0[i] == data3[i])
{
USART0_TX_String("OK");
}
else
{
USART0_TX_String("ERROR");
}
USART0_TXD(10);
USART0_TXD(13);
}
PORTB |= 1<<PINB0;
while(1)
{
}
}
There is another matter that gives me headaches.
I ha to add an extra SPI junk transmission on line 71, because if I had not done this, I would get the first result twice and so the rest would get out of line.
According to the datasheet(section 4.2.1) only by reading from the MAC or MII registers should I get a dummy byte.
What's up whit that?
I'm using AVR ATMega1284P with WinAVR.
It seems the problem is yet again in the code.
In the declaration of my variables(data0 to 2) I have not set the size of them:
unsigned char i, data, data0[] = {}, data1[] = {}, data2[] = {},
data3[16] = {0b11111010, 0b00000101,0,0,0,0,0,0,0b11111010,0b00000101,
255,0b00011111,0b11111010,0b00000101,0,0};
I should have done this:
unsigned char i, data, data0[16] = {}, data1[16] = {}, data2[16] = {},
data3[16] = {0b11111010, 0b00000101, 0,0,0,0,0,0,0b11111010,0b00000101,
255,0b00011111,0b11111010,0b00000101,0,0};

DBD::Oracle Column returns number in unusual format

I am querying an Oracle database using DBD::Oracle, however, oddly enough the decimals are return as follows:
0.1 will be returned as .1
0.97 will be returned as .97
Any ideas why this is happening.
I am using the latest version of DBI and DBD::Oracle.
That would be the default number format in your session. DBD::Oracle retrieves columns as strings so there will be an implicit TO_CHAR done by Oracle. If you want a different format do a TO_CHAR(column_name, 'FORMAT'). e.g.,
use strict;
use warnings;
use DBI;
use Devel::Peek;
my $h = DBI->connect('dbi:Oracle:host=xxx;sid=xxx','xxx','xxx',
{RaiseError => 1});
eval {
$h->do(q/drop table mje/);
};
$h->do(q/create table mje (a number)/);
my #n = (0.1, 0.97);
my $s = $h->prepare(q/insert into mje values(?)/);
foreach (#n) {
$s->execute($_);
}
$s = $h->prepare(q/select * from mje/);
$s->execute;
while (my #row = $s->fetchrow) {
Dump($row[0]);
}
$s = $h->prepare(q/select TO_CHAR(a, '09D99') from mje/);
$s->execute;
while (my #row = $s->fetchrow) {
Dump($row[0]);
}
outputs
SV = PV(0x9b72810) at 0x9c57ed8
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x9d11ec0 ".1"\0
CUR = 2
LEN = 12
SV = PV(0x9b72810) at 0x9c57ed8
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x9d18230 ".97"\0
CUR = 3
LEN = 12
SV = PV(0x9b72840) at 0x9c57ff8
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x9d0d600 " 00.10"\0
CUR = 6
LEN = 12
SV = PV(0x9b72840) at 0x9c57ff8
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x9d0d600 " 00.97"\0
CUR = 6
LEN = 12
I added the Devel::Peek just to show you they are strings (see the PV) by default so adding the TO_CHAR makes no difference.

Resources