Radio listen initialization on bare metal

I am trying to listen for bluetooth advertising packets in nRF52832 (pinetime watch to be exact).

What is the minimum required code to program radio in pure bare environment (i.e. in reset interrupt handler without SoftDevice)?

I have following code and it does not work: it always exits with timeout waiting for address. In timeout handler I see that radio is in state 3 "RADIO is in the RX state".

                .thumb_func
_radio:
                LDR         R3, =(80*256*256*256 + 26*256*256 + 2*256 + 0)

_listen:
                LDR         R5, =RADIO_BASE
                MOV         R0, 0
                STR         R0, [R5, RADIO_POWER]
                Sleep       R0, 32
                MOV         R0, 1
                STR         R0, [R5, RADIO_POWER]

                LDR         R0, =(3)                                   // Nrf_1Mbit=0, Ble_1Mbit=3, Ble_2Mbit=4
                STR         R0, [R5, RADIO_MODE]

                LDR         R0, =((0<<24) | (1<<20) | (0<<16) | (1<<8) | 8)  // LFLEN=8 bit, S0LEN=1 bytes, S1LEN=0bit, S1INCL=1, preamble 8bit
                STR         R0, [R5, RADIO_PCNF0]

                LDR         R0, =((1<<25) | (0<<24) | (3<<16) | (0<<8) | 64) // MAXLEN=64 bytes, STATLEN=0, BALEN=3+1 bytes to transfer, LSBit first, WHITEN=0
                STR         R0, [R5, RADIO_PCNF1]

                LDR         R0, =((2<<8) | 1)                                // Fast rampup, 2=Transmit center frequency
                STR         R0, [R5, RADIO_MODECNF0]

                LDR         R0, =(150)
                STR         R0, [R5, RADIO_TIFS]

                LDR         R0, =(0x89BED600)                          // 0x8E89BED6
                STR         R0, [R5, RADIO_BASE0]

                LDR         R0, =(0x8E)
                STR         R0, [R5, RADIO_PREFIX0]

                LDR         R0, =((0x10000) | (1<<0))                      // Use address 0 to recieve packets // workaround errata nrf52832 3.41 [143]
                STR         R0, [R5, RADIO_RXADDRESSES]

                LDR         R0, =(RAM_BASE + FLASH_PAGE_SIZE)
                STR         R0, [R5, RADIO_PACKETPTR]

                ROR         R3, 8
                AND         R0, R3, 0xFF
                STR         R0, [R5, RADIO_FREQUENCY]                    // Map 2400 .. 2500 MHz, use channel 66

                MOV         R0, 1
                STR         R0, [R5, RADIO_TASKS_RXEN]
                LDR         R4, =(8*1024*1024)

_ready:
                SUBS        R4, 1
                BEQ         _timeout

                LDR         R0, [R5, RADIO_EVENTS_READY]
                CMP         R0, 0
                BEQ         _ready

                MOV         R0, 1
                STR         R0, [R5, RADIO_TASKS_START]

                LDR         R4, =(16*1024*1024)

_addr:
                SUBS        R4, 1
                BEQ         _timeout

                LDR         R0, [R5, RADIO_EVENTS_ADDRESS]
                CMP         R0, 0
                BEQ         _addr

Do I miss something?

I.e. configure some frequency sources or set some GPIOs?

PS Hardware is ok: when I upload original firmware I can see watch advertises itself on both phones.

PPS. The addresses RADIO_* has been taken from nRF52832_PS_v1.4.pdf

Thank you.

Parents
  • Hi 

    First off we don't provide any code examples or support for assembly programming, rather we use C for the majority of our libraries and examples. 

    There is an old, unofficial sample showing how to do BLE advertising in a relatively simple manner, without using a full Bluetooth stack: 
    https://github.com/NordicPlayground/solar_sensor_beacon

    In particular you might want to take a look at the hal_radio_reset() function, where the radio registers are configured in order to put the radio in a Bluetooth compliant mode. 

    While this example is only designed to send advertise packets, the procedure to receive packets is very similar, and most of the radio registers should be identical whether you are in transmit or receive mode. 

    So I would recommend you start by having a look at this example. You could always test it out in C, and then try to rewrite it in assembly later (or just use it as a reference for your own assembly implementation), but as I said before it is very limited what help we can provide if you are writing applications in assembly. 
    Is there any particular reason you are using assembly over C?

    Best regards
    Torbjørn

Reply
  • Hi 

    First off we don't provide any code examples or support for assembly programming, rather we use C for the majority of our libraries and examples. 

    There is an old, unofficial sample showing how to do BLE advertising in a relatively simple manner, without using a full Bluetooth stack: 
    https://github.com/NordicPlayground/solar_sensor_beacon

    In particular you might want to take a look at the hal_radio_reset() function, where the radio registers are configured in order to put the radio in a Bluetooth compliant mode. 

    While this example is only designed to send advertise packets, the procedure to receive packets is very similar, and most of the radio registers should be identical whether you are in transmit or receive mode. 

    So I would recommend you start by having a look at this example. You could always test it out in C, and then try to rewrite it in assembly later (or just use it as a reference for your own assembly implementation), but as I said before it is very limited what help we can provide if you are writing applications in assembly. 
    Is there any particular reason you are using assembly over C?

    Best regards
    Torbjørn

Children
  • Thank you for quick answer.

    Sure I have looked into other sources before writing this code. To be exact Zephyr source code.

    The code you propose does not help much:

    1) It is a transmitter, not receiver

    2) It uses interrupts/shorts, not polling

    3) It does not use for ADDDRESS EVENT

    4) It configures timer/clock source.

    Is there any particular reason you are using assembly over C?

    To minimize code size.

    The questions I still have:

    1. Does radio require any HFCLK / LFCLOCK, any other clock generators.

    2. Do you have code that analyses ADDRESS EVENT? i.e. can I write code analyzing it (not using interrupts/SHORTs)?

    Does it really work (set when address received)? May be we have another case for ERRATA?

  • Hi 

    piner said:
    To minimize code size.

    How much flash do you have available? 

    The nRF52832 chip in the pine watch has 512kB of flash for code, and unless you are already using all but a couple of kilobytes of flash for other things I would strongly discourage writing your project in assembly. 

    piner said:
    1. Does radio require any HFCLK / LFCLOCK, any other clock generators.

    Yes. You need to start the external high frequency crystal for the radio to work properly. You can configure the radio without this running, but you have to wait for the external HFCLK to be started before enabling the radio in TX or RX mode. 

    The LF clock is not needed to use the radio, but is usually used for timing purposes by other parts of the application. 

    piner said:
    2. Do you have code that analyses ADDRESS EVENT? i.e. can I write code analyzing it (not using interrupts/SHORTs)?

    Not that I can think off.

    Most RX application don't really worry about the address event, since you need to wait for the END event before the payload content is received, and the CRC code is verified. 

    I would suggest you do the same: Rather than wait for the ADDRESS event to occur just wait for the END event. Once the END event is received you can check the CRC status, and if that is valid you can read the payload and process the packet. 

    piner said:
    Does it really work (set when address received)? May be we have another case for ERRATA?

    The nRF52832 is getting quite old at this point, and has been used by countless customers in various products, so I doubt this is a hardware issue. 

    Rather I suspect there is something wrong with the radio configuration. 

    If you try to set the BALEN field in the PCNF1 register to 2 you should probably see the ADDRESS event occur occasionally, even if the rest of the radio registers are not correctly configured. The reason for this is that a short radio address will lead to false address matches, caused by random noise on the receiver occasionally matching the configured address. 

    Best regards
    Torbjørn

  • > Yes. You need to start the external high frequency crystal for the radio to work properly.

    Thank you. After starting HFXO I see RADIO input.

    Also looking into documentation I found following paragraph:

    "The HFXO must be running to use the RADIO, NFC module or the calibration mechanism associated with
    the 32.768 kHz RC oscillator."

    Though it is in section "19 CLOCK — Clock control", I suppose better would be to add similar passage into section "23 RADIO — 2.4 GHz Radio".

  • Hi 

    Good to hear you got it working Slight smile

    I can make a request if we can add a note in the radio chapter to mention the HFXO requirement, but I can't make any promises ;)

    Regards
    Torbjørn

Related