Looping through memory using Zero Page indirect addressing on the 6502 - loops

I have written a small 6502 program to loop through memory and use STA Zero Page Indirect Addressing to store a value in 128 consecutive memory locations, but the program doesn't appear to be working. It should store 128 copies of the value $01 to memory address $0400 on-wards but it does not. What am I doing wrong?
*=$8001
; set $00,$01 to $0400
LDA #$00
STA $00
LDA #$04
STA $01
CLC ; Clear carry and decimal mode
CLD
LDX #128 ; Loop 128 times
LDY #0
loop LDA #$01 ; the value to store
STA ($00),Y ; store A to the address held in $00,$01
; Add 1 to $00,$01 (16-bit addition)
LDA $00
ADC #1
STA $00
LDA $01
ADC #0
STA $01
; do it 127 more times
DEX
BNE loop
RTS

It looks like you're incrementing the value stored at $00, but shouldn't you be manipulating Y instead? Something like:
*=$8001
LDA #<$0400 ; store $0400 into $00 and $01
STA $00
LDA #>$0400
STA $01
LDY #128 ; load 128 into Y
LDA #$01 ; load 01 into A
loop DEY
STA ($00),Y ; store A into $0400 + Y
BNE loop ; loop until Y is zero
RTS
In this loop, we get rid of X, initialize Y to 128, and then decrement Y for each loop iteration. This means we're filling memory "backwards".
Note 1
Addresses $00 and $01 are often special (e.g.,
on the C64 these addresses control processor features), so depending
on your environment you may need to choose different zero memory
locations.
Note 2
If I were writing this, I would avoid hardcoding addresses directly into the code, and instead declare a named storage location. When testing your code locally, I assembled it using 64tass and the following code:
*=$00fb
addr .word ? ; declare two bytes of storage at * and *+1
; I'm using $00fb because this is an unused zero
; page location on the c64 (and I'm testing using
; the VICE emulator).
*=$8001
LDA #<$0400 ; store $0400 into addr and addr+1
STA addr
LDA #>$0400
STA addr+1
LDY #128
LDA #$01
loop DEY
STA (addr),Y
BNE loop
RTS
Update 1
Your original code seems to work just fine for me. Note that when testing in a C64 emulator, the range $0400-$0480 corresponds to the screen memory (see e.g. this memory map), so when returning to BASIC, that range is overwritten. For example, with your code loaded at $8001, I see the following code in the monitor (assuming we're storing the address in $FB and $FC):
(C:$e5cf) d 8001
.C:8001 A9 00 LDA #$00
.C:8003 85 FB STA $FB
.C:8005 A9 04 LDA #$04
.C:8007 85 FC STA $FC
.C:8009 18 CLC
.C:800a D8 CLD
.C:800b A2 80 LDX #$80
.C:800d A0 00 LDY #$00
.C:800f A9 01 LDA #$01
.C:8011 91 FB STA ($FB),Y
.C:8013 A5 FB LDA $FB
.C:8015 69 01 ADC #$01
.C:8017 85 FB STA $FB
.C:8019 A5 FC LDA $FC
.C:801b 69 00 ADC #$00
.C:801d 85 FC STA $FC
.C:801f CA DEX
.C:8020 D0 ED BNE $800F
.C:8022 60 RTS
If I place a breakpoint at $8022 and tune the code...
(C:$8029) break 8022
BREAK: 1 C:$8022 (Stop on exec)
(C:$8029) g 8001
#1 (Stop on exec 8022) 064 011
.C:8022 60 RTS - A:04 X:00 Y:00 SP:f2 ..-...Z. 4131803
And then inspect the target memory range, it's filled with $01:
(C:$8022) m 400,480
>C:0400 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0420 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0430 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0440 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0450 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0460 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0470 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
>C:0480 20
But as soon as I return to BASIC, it looks like this:
(C:$e5d4) m 400,480
>C:0400 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0410 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0420 20 20 20 20 20 20 20 20 12 05 01 04 19 2e 20 20 ......
>C:0430 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0440 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0450 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0460 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0470 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
>C:0480 20

Related

STM32 USB Host + HID Joystick

A USB HID Joystick is connected to my STM32F401-based board. I used last versions CubeMX, the USB_HOST library, and HAL. Everything works automatically with the mouse and keyboard, but not with the joystick. I made the following changes in the library based on USBlyzer data:
usbh_conf.h
/*---------- -----------*/
#define USBH_MAX_NUM_ENDPOINTS 1U
/*---------- -----------*/
#define USBH_MAX_NUM_INTERFACES 1U
usbh_core.c
I commented out all sections of the code with the creation of the IN pipe
phost->gState = HOST_ENUMERATION;
phost->Control.pipe_out = USBH_AllocPipe(phost, 0x00U);
// phost->Control.pipe_in = USBH_AllocPipe(phost, 0x80U);
/* Open Control pipes */
// USBH_OpenPipe(phost, phost->Control.pipe_in, 0x80U,
// phost->device.address, phost->device.speed,
// USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size);
/* Open Control pipes */
USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U,
phost->device.address, phost->device.speed,
USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size);
usbh_hid.h
Add nonboot code for my joystick
/* Interface Descriptor field values for HID Boot Protocol */
#define HID_BOOT_CODE 0x01U
#define HID_NONE_BOOT_CODE 0x00U
#define HID_KEYBRD_BOOT_CODE 0x01U
#define HID_MOUSE_BOOT_CODE 0x02U
usbh_hid.c
Add
else if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_NONE_BOOT_CODE)
{
USBH_UsrLog("Non boot device found!");
}
Changed the protocol to non-boot
case HID_REQ_SET_PROTOCOL:
/* set protocol */
classReqStatus = USBH_HID_SetProtocol(phost, 1U);
if (classReqStatus == USBH_OK)
{
HID_Handle->ctl_state = HID_REQ_IDLE;
My code goes as far as getting the USB_HID_GetHIDReportDescriptor in the USB_HID_ClassRequest function and gets it. But then it breaks down on the USB_HID_GetReport function in USB_HID_Process, where I always get the status USB_NOT_SUPPORTED. I need to get a report, my functions will process the data, but I can't get a report and really don't understand why.
Therefore, I need your help, maybe someone has already worked with similar HID devices and USB_HOST library.
Data from USBlyzer:
Connection Status Device connected
Current Configuration 1
Speed Full (12 Mbit/s)
Device Address 6
Number Of Open Pipes 1
Device Descriptor VKB-Sim Space Gunfighter L
Offset Field Size Value Description
0 bLength 1 12h
1 bDescriptorType 1 01h Device
2 bcdUSB 2 0200h USB Spec 2.0
4 bDeviceClass 1 00h Class info in Ifc Descriptors
5 bDeviceSubClass 1 00h
6 bDeviceProtocol 1 00h
7 bMaxPacketSize0 1 08h 8 bytes
8 idVendor 2 231Dh
10 idProduct 2 0127h
12 bcdDevice 2 1997h 19.97
14 iManufacturer 1 01h ". Alex Oz 2012-2020"
15 iProduct 1 02h " VKB-Sim Space Gunfighter L "
16 iSerialNumber 1 00h
17 bNumConfigurations 1 01h
Configuration Descriptor 1 Bus Powered, 500 mA
Offset Field Size Value Description
0 bLength 1 09h
1 bDescriptorType 1 02h Configuration
2 wTotalLength 2 0022h
4 bNumInterfaces 1 01h
5 bConfigurationValue 1 01h
6 iConfiguration 1 00h
7 bmAttributes 1 80h Bus Powered
4..0: Reserved ...00000
5: Remote Wakeup ..0..... No
6: Self Powered .0...... No, Bus Powered
7: Reserved (set to one)
(bus-powered for 1.0) 1.......
8 bMaxPower 1 FAh 500 mA
Interface Descriptor 0/0 HID, 1 Endpoint
Offset Field Size Value Description
0 bLength 1 09h
1 bDescriptorType 1 04h Interface
2 bInterfaceNumber 1 00h
3 bAlternateSetting 1 00h
4 bNumEndpoints 1 01h
5 bInterfaceClass 1 03h HID
6 bInterfaceSubClass 1 00h
7 bInterfaceProtocol 1 00h
8 iInterface 1 00h
HID Descriptor
Offset Field Size Value Description
0 bLength 1 09h
1 bDescriptorType 1 21h HID
2 bcdHID 2 0111h 1.11
4 bCountryCode 1 00h
5 bNumDescriptors 1 01h
6 bDescriptorType 1 22h Report
7 wDescriptorLength 2 012Dh 301 bytes
Endpoint Descriptor 81 1 In, Interrupt, 1 ms
Offset Field Size Value Description
0 bLength 1 07h
1 bDescriptorType 1 05h Endpoint
2 bEndpointAddress 1 81h 1 In
3 bmAttributes 1 03h Interrupt
1..0: Transfer Type ......11 Interrupt
7..2: Reserved 000000..
4 wMaxPacketSize 2 0040h 64 bytes
6 bInterval 1 01h 1 ms
Interface 0 HID Report Descriptor Joystick
Item Tag (Value) Raw Data
Usage Page (Generic Desktop) 05 01
Usage (Joystick) 09 04
Collection (Application) A1 01
Usage Page (Generic Desktop) 05 01
Report ID (1) 85 01
Usage Page (Generic Desktop) 05 01
Usage (X) 09 30
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (4095) 26 FF 0F
Physical Maximum (4095) 46 FF 0F
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Generic Desktop) 05 01
Usage (Y) 09 31
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (4095) 26 FF 0F
Physical Maximum (4095) 46 FF 0F
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Generic Desktop) 05 01
Usage (Rx) 09 33
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (2047) 26 FF 07
Physical Maximum (2047) 46 FF 07
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Generic Desktop) 05 01
Usage (Ry) 09 34
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (2047) 26 FF 07
Physical Maximum (2047) 46 FF 07
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Generic Desktop) 05 01
Usage (Rz) 09 35
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (2047) 26 FF 07
Physical Maximum (2047) 46 FF 07
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Undefined) 05 00
Usage 09 00
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (2047) 26 FF 07
Physical Maximum (2047) 46 FF 07
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Generic Desktop) 05 01
Usage (Z) 09 32
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (2047) 26 FF 07
Physical Maximum (2047) 46 FF 07
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Undefined) 05 00
Usage 09 00
Report Size (16) 75 10
Report Count (1) 95 01
Logical Minimum (0) 15 00
Logical Maximum (2047) 26 FF 07
Physical Maximum (2047) 46 FF 07
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Button) 05 09
Usage Minimum (Button 1) 19 01
Usage Maximum (Button 128) 2A 80 00
Logical Minimum (0) 15 00
Logical Maximum (1) 25 01
Report Size (1) 75 01
Report Count (128) 96 80 00
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Generic Desktop) 05 01
Usage (Hat Switch) 09 39
Logical Minimum (0) 15 00
Logical Maximum (7) 26 07 00
Physical Minimum (0) 35 00
Physical Maximum (360) 46 68 01
Unit (Eng Rot: Degree) 65 14
Unit Exponent (1) 55 01
Report Size (4) 75 04
Report Count (1) 95 01
Input (Data,Var,Abs,NWrp,Lin,Pref,Null,Bit) 81 42
Usage (Undefined) 09 00
Unit (None) 65 00
Unit Exponent (0) 55 00
Report Size (4) 75 04
Report Count (3) 95 03
Input (Cnst,Ary,Abs) 81 01
Usage Page (Generic Desktop) 05 01
Usage (Undefined) 09 00
Report Size (16) 75 10
Report Count (1) 95 01
Input (Cnst,Ary,Abs) 81 01
Usage Page (Generic Desktop) 05 01
Usage (Undefined) 09 00
Report Size (16) 75 10
Report Count (1) 95 01
Input (Cnst,Ary,Abs) 81 01
Usage Page (Generic Desktop) 05 01
Usage (Undefined) 09 00
Report Size (16) 75 10
Report Count (1) 95 01
Input (Cnst,Ary,Abs) 81 01
Usage Page (Generic Desktop) 05 01
Usage (Undefined) 09 00
Report Size (8) 75 08
Report Count (23) 95 17
Input (Cnst,Ary,Abs) 81 01
Report ID (11) 85 0B
Usage Page (Generic Desktop) 05 01
Usage (Undefined) 09 00
Report Size (8) 75 08
Report Count (63) 95 3F
Input (Cnst,Ary,Abs) 81 01
Report ID (8) 85 08
Usage Page (Generic Desktop) 05 01
Usage (Undefined) 09 00
Report Size (8) 75 08
Report Count (63) 95 3F
Input (Cnst,Ary,Abs) 81 01
Logical Minimum (0) 15 00
Logical Maximum (255) 26 FF 00
Physical Maximum (255) 46 FF 00
Report ID (88) 85 58
Report Size (8) 75 08
Report Count (63) 95 3F
Usage (Undefined) 09 00
Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02
Report ID (89) 85 59
Report Size (8) 75 08
Report Count (128) 95 80
Usage (Undefined) 09 00
Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) B1 02
End Collection C0

Cortex M7: Branch just after start

I'm using the ATSAMV71Q21B MCU which uses a cortex-M7 processor. In order to add redundancy, I would like to have multiple boot loader and enter to one of those boot loader just after starting the microcontroller. Atlough, the ARM processor begins executing at the reset vector location 0x00000000. I cannot choose where I want to start.
I was wondering if it was possible to branch to one of my boot loaders using in few instructions.
For the moment, all solutions that I tried to generate hundred instructions which is too much for me. I guess that I need to manually add branch instructions the vector location 0x00000000. Although, I'm not sure where I should branch and if it is OK to do this.
Indeed, I'm not sure if I really understand the beginning of the assembly code generated. Therefore, I'm not sure where to branch.
Here is an example of the beginning of the program:
0x00400000 70 0a 40 20 d9 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00 p.# Ù.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.....
0x00400020 00 00 00 00 00 00 00 00 00 00 00 00 d5 01 40 00 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 ............Õ.#.Õ.#.....Õ.#.Õ.#.
0x00400040 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400060 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.....Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400080 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x004000A0 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x004000C0 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x004000E0 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400100 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00 00 00 00 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.........
0x00400120 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400140 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400160 d5 01 40 00 d5 01 40 00 10 b5 05 4c 23 78 33 b9 04 4b 13 b1 04 48 af f3 00 80 01 23 23 70 10 bd Õ.#.Õ.#..µ.L#x3..K.±.H¯ó.€.##p..
0x00400180 2c 04 40 20 00 00 00 00 28 04 40 00 0c 4b 43 b1 0c 48 0d 49 10 b5 af f3 00 80 0c 48 03 68 23 b9 ,.# ....(.#..KC±.H.I.µ¯ó.€.H.h#.
0x004001A0 10 bd 0a 48 03 68 33 b9 70 47 09 4b 00 2b f7 d0 bd e8 10 40 18 47 06 4b 00 2b f5 d0 18 47 00 bf ...H.h3.pG.K.+÷Ð.è.#.G.K.+õÐ.G.¿
0x004001C0 00 00 00 00 28 04 40 00 30 04 40 20 28 04 40 00 00 00 00 00 fe e7 00 bf 16 49 17 4a 91 42 08 b5 ....(.#.0.# (.#.....þç.¿.I.J‘B.µ
If I understand correctly, this is a vector table and I should not branch here. Is that correct ?
0x00400000 70 0a 40 20 d9 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00 p.# Ù.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.....
0x00400020 00 00 00 00 00 00 00 00 00 00 00 00 d5 01 40 00 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 ............Õ.#.Õ.#.....Õ.#.Õ.#.
0x00400040 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400060 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.....Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
0x00400080 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.Õ.#.
So these look fine the first one is the stack pointer load value
0x20400a70
A strange number perhaps but this part has 0x80000 bytes of ram so it is valid. so probably a linker script generated value (stack setup in the linker script rather than just start with top of ram).
Reset vector is
0x004001d9
which is properly formatted (lsbit is set) as to what it points to you have not provided.
many of the others are
0x004001d5
Also properly formatted is probably an infinite loop based on its proximity to the reset vector but who knows have to look at the code. It does not matter much for booting.
The chip/family doc indicates that user flash is at address 0x00400000 and is quite large for these parts, so both the address on the left of this dump and the reset vectors this all looks fine.
There is an indication that there is a sam-ba bootloader at some address 0x00800000 or 0x08000000 or I do not remember, you can look it up. Now I have used other Atmel parts that did not have the bootloader burned in the flash from Atmel but instead source to a sam-ba you could build and use yourself (why bother make your own much simpler less bulky), but I had issues with that approach how the flash did or didn't lock, how easy to unlock and erase, so what is the point? use SWD. This comment in the doc may indicate a burned in one in that case then you need to look at how to choose to boot that application instead of the user application, in either case since they indicate a specific address. If it is user changeable then that would be where you want to put your bootloader possibly or if fixed and not changeable then just use it as your bootloader.
As to where in general you put your bootloader that is all you, you choose your design, what you mean by bootloader, what features etc. Often misused but the term implies both booting the part but also having a way to load other applications in some way (run one in ram, reprogram the user/boot/application flash, etc). Something you need to look at is how the flash works on this device assuming you want to be able to re-write a portion of it with new firmware. Sometimes you can execute out of and flash at the same time but more likely to do that they use multiple flash banks so you can run in one and modify the other, which then leads into what is their boot scheme does it always only boot on one and never the other so you either have to keep the bootloader as-is forever or have a scheme, also have to have a scheme for choosing which of the images on which banks to be the default firmware after the bootloader boots.
These cores can run code in ram generally and no reason to expect not here (it's not the core, it's the chip vendor's implementation that matters) so doing a copy and jump of a portion of the bootloader to ram in order to not be running on flash allowing you to reprogram any of the flash but put yourself at risk if it fails or if power goes the part may be bricked.
If the chip vendor has not already done this with a factory bootloader and that factory loader being desirable for field use, it may use an I/O pin to determine which one boots, have to look at the docs. If you choose to do this yourself it is not unwise to have a gpio pin pick two boot paths, you can then have a very small, ideally bug free dozen or so lines of assembly that read the gpio pin and branch to a fixed point in flash that you choose Say 0x00500000 and 0x00600000 for example depending on how big you think your applications really will be. Then you can do a copy and jump into ram if the user desires loading the flash and then you can choose to load one or the other. The handful of lines of code could be a few dozen and do a checksum of some sort of the selected bank and the not selected if the selected is bad and did not complete. or a third bootloader that you provide in case the two do not checksum.
Tons of solutions, generally if you do not have separately banked flashes you need to branch to ram and have more freedom as to how to design your memory space (assuming the flash can be erased in pages). Otherwise you might want to just go with the banking solution from the chip vendor.
So all of this is documented in documents from arm and Atmel (microchip) that you should have had before starting work on this device. The only thing remotely related to arm in any of this is how the vector table works. All of the rest, the addresses, sizes, etc are all chip vendor implementation. So most of your reading is in the chip vendors docs, in this case they have the huge datasheet approach (rather than separate data sheet and reference manual approach).
You need to re-read what I found about sam-ba if you want to use that if it works for you, the nature of the flash implementation, is it in application programmable, etc. And then you design not only the functionality of your bootloader but the address space, whether it executes in flash or ram.
Edit
In case I did not understand the question.
The arm reset vector is at 0x00000004 not 0x00000000 (for the cortex-ms) and it is the address of the handler ORRED with one. Address 0x00000000 is the stack pointer initialization value, if you choose to init the stack pointer in code and not using this mechanism you can put whatever you want there.
If you want to change the reset handler address then you have to modify 0x00000004 which on some parts you can change without an erase (often flashes either work by erasing to all ones then you can write zeros, can't write ones but can changes ones to zeros on a per byte/word/chunk basis). So to change this you likely need to save it erase the block/page, change the bits you want and write back. You might for example be able to change it from 0x004001d9 to sah 0x004101d9 or to 0x004000d9, but not worth trying to do that. The value is the address of the handler ORRED with one.
It is not a branch as code is not executing at this point (normally/assumed) it is the logic reading that location and using that as the starting point, the first fetch not branch.
And as pointed out look at where the vector table is in the project and then modify that to point at your alternate reset handler. It might be code that looks like this
.word STACK_END
.word reset_handler
.word
in this case some fill/dummy vector for many of the rest. Just replace the reset_handler or whatever you find with your handler, remember this is a bootloader and you need to bootstrap C if you plan to call any C functions, worse if C++ or other language.

h264 inside AVI, MP4 and "Raw" h264 streams. Different format of NAL units (or ffmpeg bug)

TL;DR: I want to read raw h264 streams from AVI/MP4 files, even broken/incomplete.
Almost every document about h264 tells me that it consists of NAL packets. Okay. Almost everywhere told to me that the packet should start with a signature like 00 00 01 or 00 00 00 01. For example, https://stackoverflow.com/a/18638298/8167678, https://stackoverflow.com/a/17625537/8167678
The format of H.264 is that it’s made up of NAL Units, each starting
with a start prefix of three bytes with the values 0x00, 0x00, 0x01
and each unit has a different type depending on the value of the 4th
byte right after these 3 starting bytes. One NAL Unit IS NOT one frame
in the video, each frame is made up of a number of NAL Units.
Okay.
I downloaded random_youtube_video.mp4 and strip out one frame from it:
ffmpeg -ss 10 -i random_youtube_video.mp4 -frames 1 -c copy pic.avi
And got:
Red part - this is part of AVI container, other - actual data.
As you can see, here I have 00 00 24 A9 instead of 00 00 00 01
This AVI file plays perfectly
I do same for mp4 container:
As you can see, here exact same bytes.
This MP4 file plays perfectly
I try to strip out raw data:
ffmpeg -i pic.avi -c copy pic.h264
This file can't play in VLC or even ffmpeg, which produced this file, can't parse it:
I downloaded mp4 stream analyzer and got:
MP4Box tells me:
Cannot find H264 start code
Error importing pic.h264: BitStream Not Compliant
It very hard to learn internals of h264, when nothing works.
So, I have questions:
What actual data inside mp4?
What I must read to decode that data (I mean different annex-es)
How to read stream and get decoded image (even with ffmpeg) from this "broken" raw stream?
UPDATE:
It seems bug in ffmpeg:
When I do double conversion:
ffmpeg -ss 10 -i random_youtube_video.mp4 -frames 1 -c copy pic.mp4
ffmpeg pic.mp4 -c copy pic.h264
But when I convert file directly:
ffmpeg -ss 10 -i random_youtube_video.mp4 -frames 1 -c copy pic.h264
I have NALs signatures and one extra NAL unit. Other bytes are same (selected).
This is bug?
UPDATE
Not, this is not bug, U must use option -bsf h264_mp4toannexb to save stream as "Annex B" format (with prefixes)
"I want to read raw h264 streams from AVI files, even broken/incomplete."
"Almost everywhere told to me that the packet should start with a signature like : 00 00 01 or 00 00 00 01"
"...As you can see, here I have 00 00 24 A9 instead of 00 00 00 01"
Your H264 is in AVCC format which means it uses data sizes (instead of data start codes). It is only Annex-B that will have your mentioned signature as start code.
You seek frames, not by looking for start codes, but instead you just do skipping by frame sizes to reach the final correct offset of a (requested) frame...
AVI processing :
Read size (four) bytes (32-bit integer, Little Endian).
Extract the next following bytes up to size amount.
This is your H.264 frame (in AVCC format), decode the bytes to view image.
To convert into Annex-B, try replacing first 4 bytes of H.264 frame bytes with 00 00 00 01.
Consider your shown AVI bytes (see first picture) :
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 4C 49 53 54 BA 24 00 00 6D 6F 76 69 ....LISTº$..movi
30 30 64 63 AD 24 00 00 00 00 24 A9 65 88 84 27 00dc.$....$©eˆ„'
C7 11 FE B3 C7 83 08 00 08 2A 7B 6E 59 B5 71 E1 Ç.þ³Çƒ...*{nYµqá
E3 9C 0E 73 E7 10 50 00 18 E9 25 F7 AA 7D 9C 30 ãœ.sç.P..é%÷ª}œ0
E6 2F 0F 20 00 3A 64 AA CA 5E 4F CA FF AE 20 04 æ/. .:dªÊ^OÊÿ® .
07 81 40 00 48 00 0A 28 71 21 84 48 06 18 90 0C ..#.H..(q!„H....
31 14 57 9E 7A CD 63 A0 E0 9B 96 69 C5 18 AE F2 1.WžzÍc à›–iÅ.®ò
E6 07 02 29 01 20 10 70 A1 0F 8C BC 73 F0 78 FA æ..). .p¡.Œ¼sðxú
9E 1D E1 C2 BF 8C 62 CE CE AC 14 5A A4 E1 45 44 ž.á¿ŒbÎά.Z¤áED
38 38 85 DB 12 57 3E F6 E0 FB AE 03 04 21 62 8D 88…Û.W>öàû®..!b.
F6 F1 1E 37 1C A2 FF 75 1C F1 02 66 0C 92 07 06 öñ.7.¢ÿu.ñ.f.’..
15 7C 90 15 6F 7D FC BD 13 1E 2B 0C 14 3C 0C 00 .|..o}ü½..+..<..
B0 EA 6F 53 B4 98 D7 80 7A 68 3E 34 69 20 D2 FA °êoS´˜×€zh>4i Òú
F0 91 FC 75 C6 00 01 18 C0 00 3B 9A C5 E2 7D BF ð‘üuÆ...À.;šÅâ}¿
Some explanation :
Ignore leading multiple 00 bytes.
4C 49 53 54 D6 3C 00 00 6D 6F 76 69 including 30 30 64 63 = AVI "List" header.
AD 24 00 00 == decimal 9389 is AVI's own size of H264 item (must read in Little Endian).
Notice that the AVI bytes include...
- a note of item's total size (AD 24 00 00... or reverse for Little Endian : 00 00 24 AD)
- followed by item data (00 00 24 A9 65 88 84 27 ... etc ... C5 E2 7D BF).
This size includes both the 4 bytes of the AVI's"size" entry + expected bytes length of the item's own bytes. Can be written simply as:
AVI_Item_Size = ( 4 + item_H264_Frame.length );
H.264 video frame bytes in AVI :
Next follows the item data, which is the H.264 video frame. By sheer coincidence of formats/bytes layout, it too holds a 4-byte entry for data's size (since your H264 is in AVCC format, if it was Annex-B then you would be seeing start code bytes here instead of size bytes).
Unlike AVI bytes, these H264 size bytes are written in Big Endian format.
00 00 24 A9 = size of bytes for this video frame (instead of start code : 00 00 00 01).
65 88 84 27 C7 11 FE B3 C7 = H.264 keyframe (always begins X5, where the X value is based on other settings).
Remember after four size bytes (or even start codes) if followed by...
byte X5 = keyframe (IDR), example byte 65.
byte X1 = P or B frame, example byte 41.
byte X6 = SEI (Supplemental Enhancement Information).
byte X7 = SPS (Sequence Parameter Set).
byte X8 = PPS (Picture Parameter Set).
bytes 00 00 00 X9 = Access unit delimiter.
You can find the H.264 if you search for exact same bytes within AVI file. See third picture, these are your H.264 bytes (they are cut & pasted into the AVI container).
Sometimes a frame is sliced into different NAL units. So if you extract a key frame and it only shows 1/2 or 1/3 instead of full image, just grab next one or two NAL and re-try the decode.

Open a wav file to read data in text editor vs in sndfile

I want to read the data of an 8bit wav file using textPad, I know that the data is located at the 44/46th byte, but I am having problems reading it.
I have that code:
52 49 46 46 F8 37 01 00 57 41 56 45 66 6D 74 20
12 00 00 00 06 00 01 00 40 1F 00 00 40 1F 00 00
01 00 08 00 00 00 66 61 63 74 04 00 00 00 C6 37
01 00 64 61 74 61 C6 37 01 00 D6 D4 56 54 D5 56
56 51 D4 D3 D0 D6 54 57 D4 54 57 51 57 D0 D3 D1
etc.
The part in bold is the data of it.
The problem is when i read it in sndfile using sf_read_int I get in the buffer the following values:
3670016 1572864 -3670016 -1572864 524288 -3670016 -3670016
etc
How am I supposed to read the data in the wav file? What is the equation or 'relationship' between the numbers i got in sndfile and the data in textPad?
Oh and one more thing, if i switch the reading to sf_read_float instead of int i get values between -0.0001 and +0.0001...
Any idea what's happening, the writing and data processing is very good but I don't understand what's up with these values.
Thank you.
You have some pattern to see in a .wav file:
"RIFF" : 0x52 0x49 0x46 0x46
"WAVE" : 0x57 0x41 0x56 0x45
"fmt " : 0x66 0x6d 0x74 0x20
"data" : 0x64 0x61 0x74 0x61
We see 64 61 74 61 at offset 50. So data begins only at offset 54 and not 46.
You can find a wave specification to understand how is encoded your file.
Thanks to this spec, I can tell you that your file is encoded in "8-bit ITU-T G.711 A-law".
Okay so i found out that the wav file is encoded and libsndfile takes care of it without any intervention. That caused the "unequal" values.

searching Tags (TLV) with C function

I' m working on Mastercard Paypass transactions, I Have sent a READ RECORD command and got the result:
70 81 AB 57 11 54 13 33 00 89 60 10 83 D2 51 22
20 01 23 40 91 72 5A 08 54 13 33 00 89 60 10 83
5F 24 03 25 12 31 5F 25 03 04 01 01 5F 28 02 00
56 5F 34 01 01 8C 21 9F 02 06 9F 03 06 9F 1A 02
95 05 5F 2A 02 9A 03 9C 01 9F 37 04 9F 35 01 9F
45 02 9F 4C 08 9F 34 03 8D 0C 91 0A 8A 02 95 05
9F 37 04 9F 4C 08 8E 0E 00 00 00 00 00 00 00 00
42 03 5E 03 1F 03 9F 07 02 FF 00 9F 08 02 00 02
9F 0D 05 00 00 00 00 00 9F 0E 05 00 08 00 60 00
9F 0F 05 00 00 00 00 00 9F 42 02 09 78 9F 4A 01
82 9F 14 01 00 9F 23 01 00 9F 13 02 00 00
This response contains TLV data objects (without spaces). I have converted the response as described in the following:
// Read Record 1 with SFI2
//---------------------------------SEND READ RECORD-------------------
inCtlsSendVAPDU(0x2C,0x03,(unsigned char *)"\x00\xB2\x01\x14\x00",5);
clrscr();
inRet = inCTLSRecv2(Response, 269);
LOG_HEX_PRINTF("Essai EMV4 Read record 1 EMV Paypass:",Response,inRet);
if(Response[14]==0x70)
{
sprintf(Response_PPSE,"%02X%02X",Response[12],Response[13]);//To retrieve length of received data
t1=hexToInt(Response_PPSE);// Convert length to integer
t11=t1-2;
i=14;
k=0;
//--------------------------- Converting data to be used later---------
while(i<t11+14)// 14 to escape the header+ command+ status+ length
{
sprintf(READ1+(2*k),"%02X",Response[i]);
i++;
k++;
}
Now I should check if this Response contains the Mandatory Tags:
5A - Application Primary Account Number (PAN)
5F24 - Application Expiration Date
8C - Card Risk Management Data Object List 1 (CDOL1)
8D - Card Risk Management Data Object List 2 (CDOL2)
So I tried the following to check for the 5A tag (Application Primary Account Number (PAN)):
i=0;
t11=2*t11;
while(i<=t11)
{
strncpy(Response_PPSE,READ1+i,2);
if(strncmp(Response_PPSE,"\x05\x0A")==0)
{
write_at("true",4,1,1);// Just to test on the terminal display
goto end;
}
else
i=i+2;
}
goto end;
I don't know why nothing is displayed on the terminal, The if block is not executed!
I tried to print the 5A tag manually by:
strncpy(Response_PPSE,READ1+44,2);
write_at(Response_PPSE,strlen(Response_PPSE),1,1);
And it display the right value!!
Can someone helps to resolve this issue?
You don't find that tag because you are not searching for the string "5A" but for the string "\x05\x0A" (ENQ character + line feed character). Moreover, I wonder if the above code actually compiles as you did not specify the mandatory length argument to strncmp(). You could try something like
if(strncmp(Response_PPSE,"5A", 2)==0)
instead.
However, you should understand that you are scanning the whole response data for the value 5A. Therefore, finding this value could also mean that it was part of some other TLV tag's data field, length field or even part of a multi-byte tag field. It would therefore make sense to implement (or use an existing) TLV parser for the BER (Basic Encoding Rules) format.
It's not a good approach to search a specific byte in a raw byte-stream data using strings functions at first place.
The generic TLV parser is a very easy algorithm and you will do it in 30 minutes or so.
In general a pseudo-code for TLV parser that look for a specific Tag would be something like this:
index = 0
while (byte[i] != 0x5A or EOF)
{
length = DecodeLength(byte[i+1])
i += length + 2 // + 1 for L (length) byte itself, it might be encoded with
// 2 bytes so the function DecodeLength can return the number
// of bytes lenght has been encoded
// +1 for T (tag) byte
}
if(EOF) return tag_not_found
return byte[i + 2], length // pointer to data for Tag '5A'and length of data

Resources