mitxela.com forum
Welcome. Please log in or register.

Beken BK3231
brainstorm Posted: 17 Jul 2020, 02:07 PM
Avatar
@braincode

Member
Posts: 7
Joined: 16-July 20
This is a continuation on my ramblings from this thread comment, I didn't want to steal the OP's thunder on the GamePad:

https://mitxela.com/forum/topic/mocute-051-bluetooth-gamepad-bk3231-change-hid-profile-from-keyboard-gamepad#1594910340

After squinting at the BK3231 datasheet (asserting PPROG pin high to be able to talk with the SPI pins):

https://pdfhost.io/v/3r1I3HggE_BK3231_Bluetooth_HID_SoCpdf.pdf

And with this Arduino sketch connected with the mess of wires:


#include <SPI.h>
const int cs=10;
const int pprog=11;
uint32_t res;

void setup() {
Serial.begin(9600);
//SPI.setClockDivider(SPI_CLOCK_DIV128); // The SPI main clock is 16 MHz
pinMode(cs, OUTPUT);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE3);
digitalWrite(cs, LOW);
digitalWrite(pprog, HIGH);
res = SPI.transfer16(0x0);
digitalWrite(cs, HIGH);
Serial.println(res, BIN);
digitalWrite(pprog, LOW);
SPI.end();
}

void loop() {}


I'm getting the following readings on the oscillosope:

(User posted image)

(User posted image)


Would anybody want to join me on the quest to dump the internal flash? ;)

Last edit by brainstorm at 19 Jul 2020, 12:07 PM

-------------
[top]
mit Posted: 18 Jul 2020, 11:07 AM
Avatar
yeah whatever

Admin
Posts: 272
Joined: 4-May 16
Nice work. I'm not sure I'll be able to help with this, but I'd be keen to hear more if you get any further.

-------------
[top]
brainstorm Posted: 19 Jul 2020, 01:07 PM
Avatar
@braincode

Member
Posts: 7
Joined: 16-July 20
Thanks Mitxela! Yes you can help a ton by peer reviewing my steps and thoughts! :)

At the moment I'm a bit confused by the datasheet (I just reuploaded the PDF so that viewers are not faced with allaboutcircuits user/pass screen):

https://pdfhost.io/v/3r1I3HggE_BK3231_Bluetooth_HID_SoCpdf.pdf

At the memory organization section, there is this paragraph towards the end:

===
By setting PPROG-pin to 1, the internal FLASH program memory can be written with four GPIO as a SPI slave.
To access the FLASH memory **with internal program**, please refer to MFC section for detail.
===

Which seems to imply that the MFC procedure does not apply for "non-internal programs", i.e communicating from outside as I'm doing? That would rule out the MFC steps outlined on the gamepad thread (see below for screenshot)?

Then there's the SPI section of the datasheet. I guess that the right way to read some data from other memory regions via SPI would be sth like (pseudocode):


SPI.transfer(0x00950000); // Address of SPI peripheral
res = SPI.transfer(0x0);
(configure reasonable SPI params via bit flips on "res")
SPI.transfer(&res, 0x0); // Send SPI config


But after I configured the SPI parameters, I don't see any straightforward way to exfiltrate internal flash program memory by reading 0x2 SPI_DATA register on a loop.

Which leaves me to perhaps focus on poking MFC instead via SPI on the described 7 steps from that section, even if the program is running outside the MCU?:

(User posted image)


(see the rest of the registers on the PDF itself)

How would you approach this?

Last edit by brainstorm at 19 Jul 2020, 01:07 PM

-------------
[top]
mit Posted: 19 Jul 2020, 01:07 PM
Avatar
yeah whatever

Admin
Posts: 272
Joined: 4-May 16
It sounds like the MFC is just for self-programming the flash from the internal program, like you surmised. It's fairly typical to have that sort of elaborate mechanism to prevent accidental writes.

Looking at the other thread I expect the registers for the SPI are also only for use by the internal program, and aren't going to be helpful for dumping the flash.

By the sound of it, when the PPROG pin is enabled, the chip starts to behave as a dumb SPI flash chip. The datasheet doesn't give any details about the protocol, but many SPI flash chips behave in the same way. You could try finding a library for an SPI flash chip and seeing if it works.

Another thing - in your scope picture, the MOSI line looks wrong. That shape it has, where each high bit is followed by an exponential decay, suggests one of the pins isn't configured correctly. Possibly you need to set it as output in the arduino code?


-------------
[top]
brainstorm Posted: 20 Jul 2020, 02:07 PM
Avatar
@braincode

Member
Posts: 7
Joined: 16-July 20
Thanks for the pointers!

I just reviewed the setup and simplified the connections a bit. I had another FTDI UART connected via USB in parallel with the Arduino board that I didn't really need. Now that MOSI signal is square:

(User posted image)


Anyway, before trying an arbitrary SPI flash library, is there an easy way to determine if the thing I'm talking to (while PPROG is high) is a SPI flash and of which sort?

Do you know some discovery library or device like the JTAGulator but for SPI?

Last edit by brainstorm at 25 Jul 2020, 01:07 AM

-------------
[top]
brainstorm Posted: 25 Jul 2020, 01:07 AM
Avatar
@braincode

Member
Posts: 7
Joined: 16-July 20
For now I went for SPIMemory (https://github.com/Marzogh/SPIMemory/blob/master/examples/TestFlash/TestFlash.ino) with minor modifications (assert PPROG):


(...)
else if (commandNo == 1) {
printLine();
Serial.println(F(" Function 1 : Get JEDEC ID "));
printLine();
printLine();
uint8_t b1, b2, b3;

//pinMode(PPROG, OUTPUT);
digitalWrite(PPROG, HIGH); // Free up BK3231 SPI bus from MCU app code


uint32_t JEDEC = flash.getJEDECID();


digitalWrite(PPROG, LOW); // Return BK3231 SPI bus to MCU app code control

//uint16_t ManID = flash.getManID();
b1 = (JEDEC >> 16);
b2 = (JEDEC >> 8);
b3 = (JEDEC >> 0);
clearprintBuffer();
sprintf(printBuffer, "Manufacturer ID: %02xh\nMemory Type: %02xh\nCapacity: %02xh", b1, b2, b3);
Serial.println(printBuffer);
clearprintBuffer();
sprintf(printBuffer, "JEDEC ID: %04xh", JEDEC);
Serial.println(printBuffer);
printLine();
printNextCMD();


But I doubt this thing has JEDEC ID nor it seems straightforward to read all flash via command "10":


11:09:52.974 -> -----------------------------------------------------------------------------------------------------------------------------------
11:09:52.974 -> Winbond Flash
11:09:52.974 -> SPIMemory library test v3.2.0
11:09:53.008 -> ----------------------------------------------------------------------------------------------------------------------------------
11:09:53.008 -> Marzogh
11:09:53.008 -> 24.11.2015
11:09:53.043 -> ----------------------------------------------------------------------------------------------------------------------------------
11:09:53.043 -> (Please make sure your Serial monitor is set to 'No Line Ending')
11:09:53.043 -> *****************************************************************
11:09:53.076 ->
11:09:53.076 -> # Please pick from the following commands and type the command number into the Serial console #
11:09:53.076 -> For example - to write a byte of data, you would have to use the Write Byte function - so type '3' into the serial console.
11:09:53.111 -> --------------------------------
11:09:53.111 ->
11:09:53.111 -> 1. getID
11:09:53.111 -> '1' gets the JEDEC ID of the chip
11:09:53.111 -> 2. writeByte [page] [offset] [byte]
11:09:53.111 -> '2' followed by '100' and then by '20' and then by '224' writes the byte 224 to page 100 position 20
11:09:53.146 -> 3. readByte [page] [offset]
11:09:53.146 -> '3' followed by '100' and then by '20' returns the byte from page 100 position 20
11:09:53.146 -> 4. writeWord [page] [offset]
11:09:53.146 -> '4' followed by '55' and then by '35' and then by '633' writes the int 633 to page 5 position 35
11:09:53.146 -> 5. readWord [page] [offset]
11:09:53.146 -> '5' followed by '200' and then by '30' returns the int from page 200 position 30
11:09:53.146 -> 6. writeStr [page] [offset] [inputString]
11:09:53.179 -> '6' followed by '345' and then by '65' and then by 'Test String 1!' writes the String 'Test String 1! to page 345 position 65
11:09:53.179 -> 7. readStr [page] [offset] [outputString]
11:09:53.179 -> '7' followed by '2050' and then by '73' reads the String from page 2050 position 73 into the outputString
11:09:53.179 -> 8. writePage [page]
11:09:53.179 -> '8' followed by '33' writes bytes from 0 to 255 sequentially to fill page 33
11:09:53.179 -> 9. readPage [page]
11:09:53.214 -> '9' followed by 33 reads page 33
11:09:53.214 -> 10. readAllPages
11:09:53.214 -> '10' reads all 4096 pages and outputs them to the serial console
11:09:53.214 -> This function is to extract data from a flash chip onto a computer as a text file
11:09:53.214 -> Refer to 'Read me.md' in the library for details
11:09:53.214 -> 11. eraseSector
11:09:53.214 -> '11' followed by '3' erases a 4KB sector (Sector 0) containing the page 3
11:09:53.214 -> 12. eraseBlock32K
11:09:53.214 -> '12' followed by '132' erases a 32KB sector (Sector 1) containing the page 132
11:09:53.248 -> 13. eraseBlock64K
11:09:53.248 -> '13' followed by '543' erases a 64KB sector (Sector 2) containing the page 543
11:09:53.248 -> 14. eraseChip
11:09:53.248 -> '14' erases the entire chip
11:09:53.248 -> ----------------------------------------------------------------------------------------------------------------------------------
11:09:59.007 -> ----------------------------------------------------------------------------------------------------------------------------------
11:09:59.041 -> Function 1 : Get JEDEC ID
11:09:59.041 -> ----------------------------------------------------------------------------------------------------------------------------------
11:09:59.041 -> ----------------------------------------------------------------------------------------------------------------------------------
11:09:59.041 -> Manufacturer ID: 00h
11:09:59.074 -> Memory Type: 00h
11:09:59.074 -> Capacity: 00h
11:09:59.074 -> JEDEC ID: 0000h
11:09:59.074 -> ----------------------------------------------------------------------------------------------------------------------------------
11:09:59.074 -> Please type the next command. Type 0 to get the list of commands



So the return is all 0's for this one... I'll keep poking at it.

I wonder if there's some sort of non-writing (safe) SPI "fuzzer" out there for this kind of discovery tasks?

Or in the absence of that, which sequence of SPI commands would one issue?

Last edit by brainstorm at 25 Jul 2020, 04:07 AM

-------------
[top]
brainstorm Posted: 25 Jul 2020, 06:07 AM
Avatar
@braincode

Member
Posts: 7
Joined: 16-July 20
Naively sending incrementing commands:


#include <SPI.h>
const int NSS=10;
const int PPROG=2;
int32_t res;

void setup() {
Serial.begin(115200);
//SPI.setClockDivider(SPI_CLOCK_DIV128); // The SPI main clock is 16 MHz
pinMode(NSS, OUTPUT);

SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE1);

digitalWrite(NSS, LOW);
digitalWrite(PPROG, HIGH); // Free up SPI bus from MCU app code

}

void loop() {
for (int i=0; i<300; i++) {
SPI.transfer(i);
delay(1);
res = SPI.transfer(0);
delay(1);
Serial.println(res, HEX);
}

digitalWrite(PPROG, LOW); // Give back control to the MCU app code
digitalWrite(NSS, HIGH);
SPI.end();
}


Returns all 0's... a validation that SPI is still working and I've not gone wrong with the wiring? ;)


(User posted image)


(User posted image)


Last edit by brainstorm at 25 Jul 2020, 07:07 AM

-------------
[top]

Sign in to post a reply.