Issue in Internal EEPROM Writing of PIC 16F887 - pic

Are there any PIC microcontroller programmers here?
I'm learning some PIC microcontroller programming using a pickit2 and the 16F887 chip I'm working through trying out the various facilities at the moment. I can't able to read right byte from location.
I am sharing my read and write code. Did lot of combination / read lot of data on net and sheet but not able to close this issue.
My code for read:
EDREAD
BANKSEL EEADR
movlw 0X08 ;Read data from location 08
movwf EEADR
BANKSEL EECON1
bcf EECON1,EEPGD
bsf EECON1,RD
BANKSEL EEDATA
movf EEDATA,W
BANKSEL BIN1
movwf BIN1
RETURN
Write Instruction:
EDWRITE
banksel EECON1
back btfsc EECON1,WR ;Wait for
goto back
banksel EEADR
movlw 0X08
BANKSEL EEADR
movwf EEADR
BANKSEL VALUE
movf VALUE,W
BANKSEL EEDATA
movwf EEDATA
NOP
NOP
BANKSEL EECON1
bcf EECON1,EEPGD
bsf EECON1,WREN
banksel EECON2
MOVLW 0x55 ; Unlock-write voodoo
MOVWF EECON2
MOVLW 0xAA
MOVWF EECON2
BANKSEL EECON1
BSF EECON1,WR
JUMP BTFSC EECON1,WR ;
GOTO J UMP
BCF EECON1,WREN
RETURN
i write data in value resistor to EEPROM. This data comes from ADC Input value. data shown post running code is 255 despite input of ADC varies from 100 to 200.

The sequence of instructions you have implemented does not enable writes to the EEPROM correctly. There are extra BANKSEL directives that interfere with how the EEPROM write unlock sequence works.
I would suggest that you read and understand the example 10-2 on page 113 of the PIC16F887 data sheet.

Related

Self-modifying code on macOS v10.15 (Catalina) / x64

As part as porting a Forth compiler, I'm trying to create a binary that allows for self-modifying code. The gory details are at https://github.com/klapauciusisgreat/jonesforth-MacOS-x64
Ideally, I create a bunch of pages for user definitions and call mprotect like so:
#define __NR_exit 0x2000001
#define __NR_open 0x2000005
#define __NR_close 0x2000006
#define __NR_read 0x2000003
#define __NR_write 0x2000004
#define __NR_mprotect 0x200004a
#define PROT_READ 0x01
#define PROT_WRITE 0x02
#define PROT_EXEC 0x04
#define PROT_ALL (PROT_READ | PROT_WRITE | PROT_EXEC)
#define PAGE_SIZE 4096
// https://opensource.apple.com/source/xnu/xnu-201/bsd/sys/errno.h
#define EACCES 13 /* Permission denied */
#define EINVAL 22 /* Invalid argument */
#define ENOTSUP 45 /* Operation not supported */
/* Assembler entry point. */
.text
.globl start
start:
// Use mprotect to allow read/write/execute of the .bss section
mov $__NR_mprotect, %rax // mprotect
lea user_defs_start(%rip), %rdi // Start address
and $-PAGE_SIZE,%rdi // Align at page boundary
mov $USER_DEFS_SIZE, %rsi // Length
mov $PROT_ALL,%rdx
syscall
cmp $EINVAL, %rax
je 1f
cmp $EACCES,%rax
je 2f
test %rax,%rax
je 4f // All good, proceed:
// must be ENOTSUP
mov $2,%rdi // First parameter: stderr
lea errENOTSUP(%rip),%rsi // Second parameter: error message
mov $8,%rdx // Third parameter: length of string
mov $__NR_write,%rax // Write syscall
syscall
jmp 3f
1:
mov $2,%rdi // First parameter: stderr
lea errEINVAL(%rip),%rsi // Second parameter: error message
mov $7,%rdx // Third parameter: length of string
mov $__NR_write,%rax // Write syscall
syscall
jmp 3f
2:
mov $2,%rdi // First parameter: stderr
lea errEACCES(%rip),%rsi // Second parameter: error message
mov $7,%rdx // Third parameter: length of string
mov $__NR_write,%rax // Write syscall
syscall
3:
// did't work -- then exit
xor %rdi,%rdi
mov $__NR_exit,%rax // syscall: exit
syscall
4:
// All good, let's get started for real:
.
.
.
.set RETURN_STACK_SIZE,8192
.set BUFFER_SIZE,4096
.set USER_DEFS_SIZE,65536*2 // 128 kiB ought to be enough for everybody
.bss
.balign 8
user_defs_start:
.space USER_DEFS_SIZE
However, I get an EACCES return value. I suspect that this is because of some security policy apple has set up, but I do not find good documentation.
Where is the source code for mprotect, and/or what are the methods to mark the data area executable and writable at the same time?
I found that compiling with
gcc -segprot __DATA rwx rwx
does mark the entire data segment rwx, so it must somehow be possible to do the right thing. But I would prefer to only make the area hosting Forth words executable, not the entire data segment.
I found a similar discussion here, but without any solution.
The segment that I want to 'unprotect' exec permission in has really two values describing its permissions:
the initial protection settings, which for __DATA I want rw-
the maximum protection (loosest) settings, which I want to be rwx.
So first I need to set the maxprot field to rwx. According to the ld manpage, this should be achieved by invoking gcc or ld with the flags -segprot __DATA rwx rw. However, a recent change made by Apple to the linker essentially ignores the maxprot value, and sets maxprot=initprot.
Thanks to Darfink, you can use this script to tweak the maxprot bits after the fact. I thought additional code signing with special entitlements was required, but it's not, at least for the __DATA segment. The __TEXT segment may need code signing with the com.apple.security.cs.disable-executable-page-protection entitlement.
Also see here for a few more details.
Looking at the larger picture, I should also point out that rather to unprotect pieces of an otherwise protected __DATA segment, it may be better to create a complete new data/code segment just for the self-modifying code with rwx permissions from the start. This allows still protecting the rest of data by the operating system, and requires no non-standard tools.

Child-EBP vs Child-SP

While following up on some windbg tutorials I have noticed that some callstacks using k command are in this format, specially mine
Child-SP RetAddr Call Site
While other online resources like CodeProject have the k command spit out info in this format
Child-EBP RetAddr Call Site
I am confused to why there is a difference between my output and theirs and to what that truly means.
It depends on what calling convention is being used. Some functions allocate locals and parameters that it will pass to the functions it calls using the base pointer, such as cdecl, but Windows x64 calling convention uses rsp.
Child-SP is the value the stack pointer of that frame, which will be the byte before the return address for all frames except for frame 0, which might have a breakpoint before or during the prologue. If the breakpoint is on the first instruction, then the rsp would have only decreased by 8 on the Child-SP of the previous frame; this rsp value is read from the trap frame. The Child-SP is the address of the frame at the frame number if you do not consider the return address of the callee to be part of the frame (which makes sense in this scenario because the return address column of the frame is showing the return address to the previous frame to be part of this frame).
ChildEBP is the value of ebp when in that frame (not the ebp that is pushed to the frame, but the new value of ebp)
RetAddr is the return address that belongs to the frame, so it is the address it will return to
The call site is the address of the instruction after the call instruction that was called that ended the frame (so basically the callee return address -- call instruction + call instruction length), or the address of the breakpoint or other exception that caused it to break into the debugger (note: the address of the exception, not the instruction after it, so this will be rip in the trap frame) in the case of frame 0 (the frame at the top of the stack). This will indicate the name of the function that owns the frame on this row as long as the function doesn't contain a label, and args to child are the arguments passed to it. Indeed the callsite is the return address of the frame that it calls (the frame above it).
Args to child are the arguments passed to the function that owns the stack frame on the current row, not the arguments passed to the callee function it calls in the allocated space by the prologue. This is almost never accurate on x64, where it shows the first 3 quadwords of the homespace, because the first 4 arguments can be passed in registers, and the callee function may not home these arguments (save them in the homespace) if it is -O0 or not a varargs function, or may put something else in the homespace entirely. 'Child' in 'Args to child' and 'Child-SP' is a false and misleading name which implies the function the frame calls, but it actually refers to the current function.
There is an example stacktrace on this site which shows a breakpoint on notepad!ShowOpenSaveDialog, which will be the first instruction.
0:011> bp notepad!ShowOpenSaveDialog
0:011> g
Breakpoint 0 hit
notepad!ShowOpenSaveDialog:
00007ff7`0307182c 48895c2408 mov qword ptr [rsp+8],
rbx ss:00000073`74d2f310=0000000000000000
0:000> k
# Child-SP RetAddr Call Site
00 00000073`74d2f308 00007ff7`03071aeb notepad!ShowOpenSaveDialog
01 00000073`74d2f310 00007ff7`030721fa notepad!InvokeOpenDialog+0x14f
02 00000073`74d2f370 00007ff7`030738d6 notepad!NPCommand+0x4a2
03 00000073`74d2f6f0 00007fff`664b6d41 notepad!NPWndProc+0x726
04 00000073`74d2f9f0 00007fff`664b6713 USER32!UserCallWinProcCheckWow+0x2c1
05 00000073`74d2fb80 00007ff7`03073bdb USER32!DispatchMessageWorker+0x1c3
06 00000073`74d2fc10 00007ff7`03089333 notepad!WinMain+0x27f
07 00000073`74d2fd10 00007fff`68ea3034 notepad!__mainCRTStartup+0x19f
08 00000073`74d2fdd0 00007fff`69073691 KERNEL32!BaseThreadInitThunk+0x14
09 00000073`74d2fe00 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:000> r #rcx=0
0:000> r
rax=0000000000000000 rbx=0000000000000000 rcx=0000000000000000
rdx=00000213f5020968 rsi=000000499cb1f338 rdi=00000213f5021c20
rip=00007ff70307182c rsp=000000499cb1f288 rbp=000000499cb1f2d0
r8=00000213f4ffe9d6 r9=000000499cb1f338 r10=00000ffee060e246
r11=0000000000014140 r12=0000000000000000 r13=0000000000000001
r14=000000000004094e r15=00000000ffffffff
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
notepad!ShowOpenSaveDialog:
00007ff7`0307182c 48895c2408 mov qword ptr [rsp+8],
rbx ss:00000049`9cb1f290=0000000000000000
0:000> ub notepad!InvokeOpenDialog+0x14f
notepad!InvokeOpenDialog+0x133:
00007ff7`03071acf 8bd8 mov ebx,eax
00007ff7`03071ad1 85c0 test eax,eax
00007ff7`03071ad3 782c js notepad!InvokeOpenDialog+0x165 (00007ff7`03071b01)
00007ff7`03071ad5 4c8b05fc080200 mov r8,qword ptr [notepad!szOpenCaption (00007ff7`030923d8)]
00007ff7`03071adc 4c8bce mov r9,rsi
00007ff7`03071adf 488b5538 mov rdx,qword ptr [rbp+38h]
00007ff7`03071ae3 498bce mov rcx,r14
00007ff7`03071ae6 e841fdffff call notepad!ShowOpenSaveDialog (00007ff7`0307182c)
The trap frame created by nt!KiBreakpointTrap is not part of the stack trace, because trap frames are pushed to the threads's kernel stack not the user stack.
If you are kernel debugging then you will see a fusion of the user and kernel stacks if there is a trap frame and the process address space is accessible:
lkd> .process /P fffffa80723296f0
lkd> .reload
lkd> ld *
lkd> !process 3490
Searching for Process with Cid == 3490
Cid handle table at fffff8a00195f000 with 4126 entries in use
PROCESS fffffa80723296f0
SessionId: 1 Cid: 3490 Peb: 7fffffdf000 ParentCid: 1470
DirBase: 403874000 ObjectTable: fffff8a02b3a2ce0 HandleCount: 293.
Image: chrome.exe
VadRoot fffffa805fc816e0 Vads 295 Clone 0 Private 16586. Modified 1536. Locked 0.
DeviceMap fffff8a00208d0b0
Token fffff8a03466d9e0
ElapsedTime 00:23:43.376
UserTime 00:00:00.717
KernelTime 00:00:00.000
QuotaPoolUsage[PagedPool] 0
QuotaPoolUsage[NonPagedPool] 0
Working Set Sizes (now,min,max) (27282, 50, 345) (109128KB, 200KB, 1380KB)
PeakWorkingSetSize 33917
VirtualSize 870 Mb
PeakVirtualSize 891 Mb
PageFaultCount 81452
MemoryPriority BACKGROUND
BasePriority 4
CommitCharge 19316
Job fffffa805f9f46d0
THREAD fffffa802e890b50 Cid 3490.469c Teb: 000007fffffdd000 Win32Thread: fffff900c53a48c0 WAIT: (UserRequest) UserMode Non-Alertable
fffffa8062daf060 SynchronizationEvent
Not impersonating
DeviceMap fffff8a00208d0b0
Owning Process fffffa80723296f0 Image: chrome.exe
Attached Process N/A Image: N/A
Wait Start TickCount 45844297 Ticks: 42 (0:00:00:00.655)
Context Switch Count 21234 LargeStack
UserTime 00:00:07.300
KernelTime 00:00:00.234
Win32 Start Address chrome!IsSandboxedProcess (0x000000013fbcbe90)
Stack Init fffff8802d5bec70 Current fffff8802d5be7c0
Base fffff8802d5bf000 Limit fffff8802d5b7000 Call 0
Priority 4 BasePriority 4 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP RetAddr Call Site
fffff880`2d5be800 fffff800`0367ec32 nt!KiSwapContext+0x7a
fffff880`2d5be940 fffff800`0368145f nt!KiCommitThreadWait+0x1d2
fffff880`2d5be9d0 fffff800`0397602e nt!KeWaitForSingleObject+0x19f
fffff880`2d5bea70 fffff800`03678c13 nt!NtWaitForSingleObject+0xde
fffff880`2d5beae0 00000000`7782bd7a nt!KiSystemServiceCopyEnd+0x13 (TrapFrame # fffff880`2d5beae0)
00000000`002eec08 000007fe`fd6110ac ntdll!NtWaitForSingleObject+0xa
00000000`002eec10 000007fe`d97c2107 KERNELBASE!WaitForSingleObjectEx+0x79
00000000`002eecb0 000007fe`d858aeab chrome_child!GetHandleVerifier+0x15d8417
00000000`002eed40 000007fe`d823004d chrome_child!GetHandleVerifier+0x3a11bb
00000000`002eedb0 000007fe`d822fc91 chrome_child!GetHandleVerifier+0x4635d
00000000`002eee10 000007fe`d8217c59 chrome_child!GetHandleVerifier+0x45fa1
00000000`002eee40 000007fe`d82176de chrome_child!GetHandleVerifier+0x2df69
00000000`002ef040 000007fe`d82105d1 chrome_child!GetHandleVerifier+0x2d9ee
00000000`002ef1b0 000007fe`d81e518b chrome_child!GetHandleVerifier+0x268e1
00000000`002ef250 000007fe`d81e4c58 chrome_child!ChromeMain+0x377d
00000000`002ef570 000007fe`d81e1b2e chrome_child!ChromeMain+0x324a
00000000`002ef600 00000001`3faf354c chrome_child!ChromeMain+0x120
00000000`002ef6d0 00000001`3faf1699 chrome+0x354c
00000000`002ef7c0 00000001`3fbcbe33 chrome+0x1699
00000000`002efba0 00000000`775d59cd chrome!IsSandboxedProcess+0x61483
00000000`002efbe0 00000000`7780a561 kernel32!BaseThreadInitThunk+0xd
00000000`002efc10 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
The trap frame is made by nt!KiSystemCall64, which has a label in it called nt!KiSystemServiceCopyEnd, which makes the call to the system service, in this case nt!NtWaitForSingleObject. The trap frame is the first stack frame hence function on the kernel stack and begins at the rsp (Child-SP) of the function nt!KiSystemCall64 and starts with the homespace that it allocates for the next function. The first instruction of nt!KiSystemCall64 is swapgs to swap gs with the gs in IA32_KERNEL_GS_BASE, and then it stores rsp into gs:10h, which is the UserRsp field in the KPCR and then stores gs:1A8h into rsp, which is the RspBase field in the KPRCB, this is clearly swapping the user rsp with the kernel rsp for the thread, which is cached in the hyperthread that currently has that thread running's KPRCB. It then starts building the trap frame, where the rsp is currently pointing to offset 0x190 in the trap frame by definition (the byte after the end of the frame), starting with pushing SS, because the CPU doesn't do this when you use syscall instead of int 0x2e.
When a base pointer is used, the trap frame would be at 8 less than the ebp of the frame above it (subtract ebp and return address, 4 bytes each), so the frame of nt!NtWaitForSingleObject
Exceptions have an exception frame that stores the non-volatile registers using nt!KiExceptionDispatch, after nt!KiBreakpointTrap for instance creates the trap frame (and the trap frame building different to a system call because the processor pushes SS:RSP RFLAGS, CS:RIP and ErrorCode to the stack for a user-mode exception and RFLAGS, CS:RIP and ErrorCode to the stack for a kernel-mode exception, and does not save/load any rsp from the KPCR / KPRCB). nt!KiExceptionDispatch creates an exception frame KEXCEPTION_FRAME beginning at the next rsp in the stack trace and the EXCEPTION_RECORD is immediately after above that on the stack, with a total combined size of 1D8, so you'll see a difference of 1E0 between the stack pointers of nt!KiExceptionDispatch and nt!KiBreakpointTrap when you include the return address to nt!KiBreakpointTrap.
The trap frame stores all registers that can be clobbered by the kernel
during the array of functions that are called in the kernel, called volatile registers, because the volatile registers are guaranteed not to be changed during a syscall or an exception. It does not save non-volatile registers because the functions that are called in the kernel save any non-volatile registers they use, so by the time it returns to this function to perform a sysret, all the nonvolatile registers will be the value they were before. You need an exception frame for exceptions because it needs to know in the function that performs the stack unwinding what the nonvolatile registers contained at the time of the exception so that the stack can be unwound. A CONTEXT structure is created on the stack in nt!KiDispatchException to represent the full context at the time of the exception, which is a combination of the nonvolatile and volatile register state.
You also need another exception frame when swapping thread contexts in order to save the state of the nonvolatile registers at the time the thread is switched out, so this will be the state in nt!KiSwapContext, so this can be restored when the thread is switched back in. The volatile state does not need to be saved, because it's assumed that the call to SwapContext discards all volatile registers. The trap frame created when entering kernel mode in the first place will be used to restore the volatile register context to the thread when it returns to user mode.
Fun fact: for a breakpoint exception INT 3, the CPU pushes the rip starting after the end of the breakpoint instruction and not the breakpoint instruction which means that windows needs to decrement the address so the top of the stack callsite is the rip in the trap frame and not the return address pushed by the CPU.

Cannot modify data segment register. When tried General Protection Error is thrown

I have been trying to create an ISR handler following this
tutorial by James Molloy but I got stuck. Whenever I throw a software interrupt, general purpose registers and the data segment register is pushed onto the stack with the variables automatically pushed by the CPU. Then the data segment is changed to the value of 0x10 (Kernel Data Segment Descriptor) so the privilege levels are changed. Then after the handler returns those values are poped. But whenever the value in ds is changed a GPE is thrown with the error code 0x2544 and after a few seconds the VM restarts. (linker and compiler i386-elf-gcc , assembler nasm)
I tried placing hlt instructions in between instructions to locate which instruction was throwing the GPE. After that I was able to find out that the the `mov ds,ax' instruction. I tried various things like removing the stack which was initialized by the bootstrap code to deleting the privilege changing parts of the code. The only way I can return from the common stub is to remove the parts of my code which change the privilege levels but as I want to move towards user mode I still want them to stay.
Here is my common stub:
isr_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
xor eax,eax
mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor
mov ax, 0x10 ; load the kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call isr_handler
xor eax,eax
pop eax
mov ds, ax ; This is the instruction everything fails;
mov es, ax
mov fs, ax
mov gs, ax
popa
iret
My ISR handler macros:
extern isr_handler
%macro ISR_NOERRCODE 1
global isr%1 ; %1 accesses the first parameter.
isr%1:
cli
push byte 0
push %1
jmp isr_common_stub
%endmacro
%macro ISR_ERRCODE 1
global isr%1
isr%1:
cli
push byte %1
jmp isr_common_stub
%endmacro
ISR_NOERRCODE 0
ISR_NOERRCODE 1
ISR_NOERRCODE 2
ISR_NOERRCODE 3
...
My C handler which results in "Received interrupt: 0xD err. code 0x2544"
#include <stdio.h>
#include <isr.h>
#include <tty.h>
void isr_handler(registers_t regs) {
printf("ds: %x \n" ,regs.ds);
printf("Received interrupt: %x with err. code: %x \n", regs.int_no, regs.err_code);
}
And my main function:
void kmain(struct multiboot *mboot_ptr) {
descinit(); // Sets up IDT and GDT
ttyinit(TTY0); // Sets up the VGA Framebuffer
asm volatile ("int $0x1"); // Triggers a software interrupt
printf("Wow"); // After that its supposed to print this
}
As you can see the code was supposed to output,
ds: 0x10
Received interrupt: 0x1 with err. code: 0
but results in,
...
ds: 0x10
Received interrupt: 0xD with err. code: 0x2544
ds: 0x10
Received interrupt: 0xD with err. code: 0x2544
...
Which goes on until the VM restarts itself.
What am I doing wrong?
The code isn't complete but I'm going to guess what you are seeing is a result of a well known bug in James Molloy's OSDev tutorial. The OSDev community has compiled a list of known bugs in an errata list. I recommend reviewing and fixing all the bugs mentioned there. Specifically in this case I believe the bug that is causing problems is this one:
Problem: Interrupt handlers corrupt interrupted state
This article previously told you to know the ABI. If you do you will
see a huge problem in the interrupt.s suggested by the tutorial: It
breaks the ABI for structure passing! It creates an instance of the
struct registers on the stack and then passes it by value to the
isr_handler function and then assumes the structure is intact
afterwards. However, the function parameters on the stack belongs to
the function and it is allowed to trash these values as it sees fit
(if you need to know whether the compiler actually does this, you are
thinking the wrong way, but it actually does). There are two ways
around this. The most practical method is to pass the structure as a
pointer instead, which allows you to explicitly edit the register
state when needed - very useful for system calls, without having the
compiler randomly doing it for you. The compiler can still edit the
pointer on the stack when it's not specifically needed. The second
option is to make another copy the structure and pass that
The problem is that the 32-bit System V ABI doesn't guarantee that data passed by value will be unmodified on the stack! The compiler is free to reuse that memory for whatever purposes it chooses. The compiler probably generated code that trashed the area on the stack where DS is stored. When DS was set with the bogus value it crashed. What you should be doing is passing by reference rather than value. I'd recommend these code changes in the assembly code:
irq_common_stub:
pusha
mov ax, ds
push eax
mov ax, 0x10 ;0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push esp ; At this point ESP is a pointer to where GS (and the rest
; of the interrupt handler state resides)
; Push ESP as 1st parameter as it's a
; pointer to a registers_t
call irq_handler
pop ebx ; Remove the saved ESP on the stack. Efficient to just pop it
; into any register. You could have done: add esp, 4 as well
pop ebx
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
popa
add esp, 8
sti
iret
And then modify irq_handler to use registers_t *regs instead of registers_t regs :
void irq_handler(registers_t *regs) {
if (regs->int_no >= 40) port_byte_out(0xA0, 0x20);
port_byte_out(0x20, 0x20);
if (interrupt_handlers[regs->int_no] != 0) {
interrupt_handlers[regs->int_no](*regs);
}
else
{
klog("ISR: Unhandled IRQ%u!\n", regs->int_no);
}
}
I'd actually recommend each interrupt handler take a pointer to registers_t to avoid unnecessary copying. If your interrupt handlers and the interrupt_handlers array used function that took registers_t * as the parameter (instead of registers_t) then you'd modify the code:
interrupt_handlers[r->int_no](*regs);
to be:
interrupt_handlers[r->int_no](regs);
Important: You have to make these same type of changes for your ISR handlers as well. Both the IRQ and ISR handlers and associated code have this same problem.

PN532 Tag Emulation - Understanding initial response and APDU data field

I have a pn532 which I'd like to present to a reader as a passive NFC tag with an NDEF record URL on it.
Following the PN532's User Manual I can put the device into target mode, and read the first ADPU command from the phone. I can use the iso-14443-4 pdf from 2005 to see that the command is A4, Read File, and that the two parameter bytes indicate "Select by DF name, first occurrence". Past that though, I don't know how to interpret the Data Field, which should the the name of a file being requested for reading.
Furthermore, I don't know how to interpret the initial command [E080] from the phone.
The program's output: (comments with #'s)
usart init.
i2c init.
pn532 init.
Firmware: 1.6
SAM config done.
Gen Status:
Err code: 0x00
Field: 0x00
Number of tags: 0x00
Initiating as target. # Here the pn532 waits for a reader.
tgInitAsTarget. Length: 5 # Callback function once the pn532 detects a reader and retrieves the first command from it.
Mode:
Baud: 106kbps, 14443-4: yes, DEP: no, Framing type: Mifare.
Initiator command:
0xE0
0x80
Entering tg loop.
callback: tgGetData. # The tgGetData command is sent without doing anything with the initial instructions.
status: 0x00
0x00 0xA4 0x04 0x00 0x07 0xD2 0x76 0x00 0x00 0x85 0x01 0x01 0x00
CLA: 0x00 # Single command, No SM, channel 0.
INS: 0xA4 # Select.
P1: 0x04 # Select by DF name.
P2: 0x00 # First/Only occurrence, return FCI template.
Lc: 0x07 # 7 data bytes.
Data: 0xD2 0x76 0x00 0x00 0x85 0x01 0x01 #???
Le: 0x00 # Any length response.
Furthermore, I don't know how to interpret the initial command [E080] from the phone.
I can point you at some starting points. E080 is part of RATS (Request for Answer To Select). Secion 5.9.2 (Rats command and ATS response) of this pdf (https://www.st.com/resource/en/datasheet/st25ta64k.pdf) breaks down the 0xE0 as the INS and 0x80 as the Param, which is a bit vector.

Atmel Studio executes instructions outside my source files

I'm trying to write and debug a C program for an ATMega8 device using the Atmel Studio Simulator.
For example, let's say I'm trying to debug this piece of code:
int main(void)
{
while(1)
{
SPI_transaction(0xFF);
}
}
uint8_t SPI_transaction(unsigned char byte_to_send){
value = byte_to_send;
SPDR = byte_to_send; //Sends command
while (checkBitStatus(SPSR,SPIF) == 0){}; //Do nothing until transfer is completed
value = SPDR; //Receives command
CLEARBIT(SPSR, SPIF);
return value;
}
unsigned char checkBitStatus(unsigned char byte, unsigned char bit){
unsigned char bit_status;
if ((byte & (1 << bit)) == 0){
bit_status = 0;
}
else{
bit_status = 1;
}
return bit_status;
}
This code buids without any problem but when I try to debug this happens:
At some points the program counter goes outside my source files. I've been trying to find out why this happens but I have ot been able yet to find an answer. I leave here the disassembly code for you to have a look. I find it really strange.
Init of main function:
00000024 PUSH R28 Push register on stack
00000025 PUSH R29 Push register on stack
00000026 IN R28,0x3D In from I/O location
00000027 IN R29,0x3E In from I/O location
SPI_transaction(0xFF);
00000028 SER R24 Set Register
00000029 RCALL PC+0x0002 Relative call subroutine
uint8_t SPI_transaction(unsigned char byte_to_send){
0000002B PUSH R28 Push register on stack
0000002C PUSH R29 Push register on stack
0000002D PUSH R1 Push register on stack
0000002E IN R28,0x3D In from I/O location
0000002F IN R29,0x3E In from I/O location
00000030 STD Y+1,R24 Store indirect with displacement
while (checkBitStatus(SPSR,SPIF) == 0){}; //Do nothing until transfer is completed
00000039 NOP No operation
--- No source file -------------------------------------------------------------
0000003A LDI R24,0x2E Load immediate
0000003B LDI R25,0x00 Load immediate
0000003C MOVW R30,R24 Copy register pair
--- No source file -------------------------------------------------------------
0000003D LDD R24,Z+0 Load indirect with displacement
0000003E LDI R22,0x07 Load immediate
0000003F RCALL PC+0x0018 Relative call subroutine
From that it jumps here:
unsigned char checkBitStatus(unsigned char byte, unsigned char bit){
00000057 PUSH R28 Push register on stack
00000058 PUSH R29 Push register on stack
00000059 RCALL PC+0x0001 Relative call subroutine
0000005A PUSH R1 Push register on stack
0000005B IN R28,0x3D In from I/O location
0000005C IN R29,0x3E In from I/O location
0000005D STD Y+2,R24 Store indirect with displacement
0000005E STD Y+3,R22 Store indirect with displacement
if ((byte & (1 << bit)) == 0){
0000005F LDD R24,Y+2 Load indirect with displacement
00000060 MOV R24,R24 Copy register
00000061 LDI R25,0x00 Load immediate
00000062 LDD R18,Y+3 Load indirect with displacement
00000063 MOV R18,R18 Copy register
00000064 LDI R19,0x00 Load immediate
00000065 MOV R0,R18 Copy register
00000066 RJMP PC+0x0003 Relative jump
00000067 ASR R25 Arithmetic shift right
00000068 ROR R24 Rotate right through carry
00000069 DEC R0 Decrement
0000006A BRPL PC-0x03 Branch if plus
0000006B ANDI R24,0x01 Logical AND with immediate
0000006C CLR R25 Clear Register
0000006D SBIW R24,0x00 Subtract immediate from word
0000006E BRNE PC+0x03 Branch if not equal
bit_status = 0;
0000006F STD Y+1,R1 Store indirect with displacement
00000070 RJMP PC+0x0003 Relative jump
bit_status = 1;
00000071 LDI R24,0x01 Load immediate
00000072 STD Y+1,R24 Store indirect with displacement
return bit_status;
00000073 LDD R24,Y+1 Load indirect with displacement
}
00000074 POP R0 Pop register from stack
00000075 POP R0 Pop register from stack
00000076 POP R0 Pop register from stack
00000077 POP R29 Pop register from stack
00000078 POP R28 Pop register from stack
00000079 RET Subroutine return
The function returns to somewhere out my source files:
--- No source file -------------------------------------------------------------
00000040 TST R24 Test for Zero or Minus
00000041 BREQ PC-0x07 Branch if equal
0000003A LDI R24,0x2E Load immediate
0000003B LDI R25,0x00 Load immediate
0000003C MOVW R30,R24 Copy register pair
0000003D LDD R24,Z+0 Load indirect with displacement
0000003E LDI R22,0x07 Load immediate
0000003F RCALL PC+0x0018 Relative call subroutine
And the goes again to CheckBitStatus() function.
Any help will be really appreciated.
Alex
The code executed outside your source is most likely an interrupt service routine for a hardware interrupt handled by an atmel or c standard library. These routinely occur for stuff like USB events that must be handled asynchronously.
Another simple reason for the debugger to display the assembly view and the message "no source file found" , if you attempt to use the debugger while the configuration manager (Under Build tap) has the configuration option set for release, the program compilation will go to the release directory and not to the debug directory.

Resources