Author Topic: EEVblog #1144 - Padauk Programmer Reverse Engineering  (Read 88164 times)

0 Members and 1 Guest are viewing this topic.

Offline alvieboy

  • Contributor
  • Posts: 6
  • Country: pt
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #825 on: January 22, 2020, 03:14:49 pm »
Hi all,

I am working on a interrupt-based, timing sensitive project to be implemented on a PFS154 controller. For this project I needed very fast interrupt response, and I needed to evaluate if the interrupt processing, which include pin sampling, could sustain the expected interrupt rate.

This was not easy to test using software, so I wrote a VHDL simulation model for PDK14 (PFS154).  The model should work with any HDL VHDL simulation engine, such as GHDL or Modelsim.

Not every PDK14 opcodes are implemented as of now, but should be fairly easy to implement the missing ones. I have also a PDK15 implementation but it's currently lagging behind.

The simulation model includes GPIO, basic T16 support, Timer2 and Timer3, and PWMG0. It should support all the clock sources for sysclk and for the timers.

You can find the VHDL model here:

https://github.com/free-pdk/fppa-pdk-emulator-vhdl

There is a basic example inside "examples/test" you can run. See the README file inside that folder for details.

I sincerly hope this can be useful to anyone as it is for me. Let me know if you find any issues, or have any feature request.

Best,
Alvaro Lopes
 
The following users thanked this post: I wanted a rude username

Offline tim_

  • Regular Contributor
  • *
  • Posts: 83
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #826 on: January 22, 2020, 06:17:18 pm »
I saw it today. Looks like massive work! Is it synthesizable? This could be the foundation for an open-source in-circuit emulator based on any cheap FPGA board. It would ease development for the OTP variants a lot.

I wonder, what is so peculiar about the PFS154 interrupts? Since every instruction is executed in one or two cycles, the interrupts should be fairly quick and with low jitter?
 

Offline alvieboy

  • Contributor
  • Posts: 6
  • Country: pt
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #827 on: January 22, 2020, 08:40:18 pm »
I saw it today. Looks like massive work! Is it synthesizable? This could be the foundation for an open-source in-circuit emulator based on any cheap FPGA board. It would ease development for the OTP variants a lot.
As of now, it is not synthesizable. Mainly because there are a few open questions regading the microcontroller implementation (see the toplevel README, I have a few questions there that need to be answered).
Quote
I wonder, what is so peculiar about the PFS154 interrupts? Since every instruction is executed in one or two cycles, the interrupts should be fairly quick and with low jitter?
They are quick... but it's hard to understand if you can keep up the pace when the interrupt sources come at only a few microsseconds apart. Simulating this at a lower level allows you to test several scenarios and evaluate whether your design will work or not. What I can tell you is, my first version which was implemented in "C" and built with SDCC was *not* able to keep pace. I found this during simulation, and simulation helped me optimize the (now in assembly) code.

There is something peculiar about how SDCC generates the interrupt handler, though. I ended up with the following sequence which was non-optimal (in addition to the goto statement due to memory location, I presume)

pushaf
mov a, p
pushaf
// Interrupt code
popaf
mov p, a
popaf
reti

I did not require modification of A for the most important part of the interrupt routine. And definitely not using "p". 6 less instructions to execute, 750ns saved. Quite important when you have 3 us between interrupts, and you need to serve them quickly because you need to sample pins from within the interrupt routine.

Alvaro
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 200
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #828 on: January 23, 2020, 01:40:14 pm »
I saw it today. Looks like massive work! Is it synthesizable? This could be the foundation for an open-source in-circuit emulator based on any cheap FPGA board. It would ease development for the OTP variants a lot.
As of now, it is not synthesizable. Mainly because there are a few open questions regading the microcontroller implementation (see the toplevel README, I have a few questions there that need to be answered).
Quote
I wonder, what is so peculiar about the PFS154 interrupts? Since every instruction is executed in one or two cycles, the interrupts should be fairly quick and with low jitter?
They are quick... but it's hard to understand if you can keep up the pace when the interrupt sources come at only a few microsseconds apart. Simulating this at a lower level allows you to test several scenarios and evaluate whether your design will work or not. What I can tell you is, my first version which was implemented in "C" and built with SDCC was *not* able to keep pace. I found this during simulation, and simulation helped me optimize the (now in assembly) code.

There is something peculiar about how SDCC generates the interrupt handler, though. I ended up with the following sequence which was non-optimal (in addition to the goto statement due to memory location, I presume)

pushaf
mov a, p
pushaf
// Interrupt code
popaf
mov p, a
popaf
reti

I did not require modification of A for the most important part of the interrupt routine. And definitely not using "p". 6 less instructions to execute, 750ns saved. Quite important when you have 3 us between interrupts, and you need to serve them quickly because you need to sample pins from within the interrupt routine.

Alvaro

You also can get rid of the 2 extra cycles from the GOTO statement in case you manually instruct SDCC to place your interrupt code directly to the right position.

Here my example code how to setup a naked interrupt (without pushf/popf) which places the code at int vector location directly:

void naked_interrupt(void) __naked
{
  __asm
      .area NAKEDINT (ABS)   ;place following code in a new segment 'NAKEDINT' with absolute positioning '(ABS)'
      .org  0x0020           ;set position to 0x0010  (multiplied by 2 since SDCC expects byte pos here)

      ;Interrupt code        ;your interrupt code which takes care of A, flags and virtual 'p' register (RAM location of 1 word @0x0000)
      nop
      nop
      nop

      reti                   ;last instruction must be 'reti' to return from interrupt

      .area CODE             ;switch back to normal segment 'CODE' for following code
  __endasm;
}


EDIT: To make it work I needed to place the naked interrupt in an extra file which needs to be given to the linker before the file which contains main. Then there was still a problem since SDCC PDK compiler always creates code for an interrupt vector when it finds the main() function in a source file.

So following code will work:

nakedint.c
void naked_interrupt(void) __naked
{
  __asm
      .area   HEADER(ABS)      ;place following code in the segment 'HEADER' with absolute positioning '(ABS)'
      .org  0x0020             ;set position to 0x0010  (multiplied by 2 since SDCC expects byte pos here)
      .org  0x0020             ;3 times .org seems to confuse SDCC so it will place later HEADER section with int vector @0x000F
      .org  0x0020             ;this seems to be a bug in SDCC but I did not find any other way to avoid SDCC PDK compiler to place the interrupt vector
      nop                      ;this dummy instruction is located at 0x000F and will be overwritten later from SDCC interrupt vector placement (will become 'reti')

      .area   HOME             ;we place code in 'HOME' area which now begins @0x0010 (the correct interrupt vector location)

      ;Interrupt code          ;your interrupt code which takes care of A, flags and virtual 'p' register (RAM location of 1 word @0x0000)
      nop
      nop
      nop

      reti                     ;last instruction must be 'reti' to return from interrupt
  __endasm;
}


main.c

unsigned char _sdcc_external_startup(void)
{
  return 0;
}

void main(void)
{
  for( ;; );
}



commands to compile:
sdcc -mpdk14 -c nakedint.c -o nakedint.rel
sdcc -mpdk14 -c main.c -o main.rel
sdcc -mpdk14 nakedint.rel main.rel -o testnakedint.ihx


JS
« Last Edit: January 23, 2020, 04:28:31 pm by js_12345678_55AA »
Easy PDK programmer and more: https://free-pdk.github.io
 

Offline alvieboy

  • Contributor
  • Posts: 6
  • Country: pt
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #829 on: February 01, 2020, 04:18:58 pm »
Restrictions on INTEGS bit manipulation

All,
Is anyone aware of any restriction for bit manipulating INTEGS ?

Let me tell you what I am experiencing. Part is PFS154-S16.

I have a complex interrupt routine that triggers on PA0 edges, but the edge detection changes due to the nature of the algorithm I am using.
For this particular part of the interrupt, PA0 rising edge is being used, PB0 also used as both edges, and T16 is also used as rising edge. This gives a INTEGS value of 0b000_0_00_01., i.e., all bits are zero except for bit 0 (selecting [1:0] as "01" as required for rising edge interrupt).

At some point in the algorithm I need to enable both edges interrupt on PA0, and I need to do this from the interrupt routine (and when processing an PA0 interrupt - also the interrupt is acked immediatly at ISR entrance). For that purpose I manipulate only the bit0 of INTEGS, setting it to '0' to select both edge interrupt. This is done in assembly using:

        set0 _integs, #0  // Activate interrupt on both edges

So far so good, I can see the interruptions coming in when edge changes, either rising or falling.

Now, at another point in the algorithm I need to re-enable only rising edge interrupts (also from within the interrupt routine, and while processing PA0 falling edge interrupt). But when I do this:

        set1 _integs, #0  // Activate interrupt on rising edge only

I lose both rising and falling interrupts. I see interrupts from other sources coming in, but never from PA0.

After some experimentation, I found out that this below does work, though:

        mov a, #1
        mov _integs, a  // Activate interrupt on rising edge only

So this leads me to believe that there are some restrictions regarding bit manipulation of INTEGS register.

Does anyone have any insight on this ?

Best,
Alvaro
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 200
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #830 on: February 02, 2020, 01:00:32 pm »
Hi,

Have you set the other bit to 0 before (e.g.  set0 _integs, #1)?

Have you tried to read back the value after using set1 ?

Or.... To setup PA / PB in INTEGS register 2 bits are required to set F/R/B. Maybe the logic inside of the PADAUK CPU is not working correct when changing only one bit out of the 2 bit value.

JS
Easy PDK programmer and more: https://free-pdk.github.io
 

Offline piotr_go

  • Contributor
  • Posts: 9
  • Country: pl
    • My Projects
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #831 on: February 15, 2020, 02:47:29 pm »
Hi again.
I have 2 questions.

1. I can't read input when PADIER = 0. Tested with PFS154.
Is there some kind of bug, or I'm missing something in the documentation?
Code: [Select]
__sfr __at(0x03) clkmd;
__sfr __at(0x0d) padier;
__sfr __at(0x0e) pbdier;
__sfr __at(0x10) pa;
__sfr __at(0x11) pac;
__sfr __at(0x12) paph;

unsigned char _sdcc_external_startup(void){
return 0;
}

void main(void){
paph = (1<<5); // Enable pull-high
pa   = 0; // HI
pac  = (1<<0); // Enable output
padier = 0;//(1<<5); // Enable PA5 wake up event

while(1){
if((pa&(1<<5))) pa |= (1<<0);
else pa &= ~(1<<0);
}
}

2. I got strange 2x speed difference between PFS154 and PMS150C.
Both set to 0x80 in IHRCR. PMS150C is 2 times slower (pwm speed and instruction execution time).
I need to set IHRCR really high (0xDA) to get the same results. Is it normal?
Is there a IHRCR factory calibration value for PMS150C in memory?
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 200
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #832 on: February 17, 2020, 10:38:45 am »
Hi again.
I have 2 questions.

1. I can't read input when PADIER = 0. Tested with PFS154.
Is there some kind of bug, or I'm missing something in the documentation?

No bug. Just like it is. If you want to use a pin as digital input you have to enable the digital input pin in PxDIER = "Port x Digital Input Enable Register".

On PFS154 default value after reset is 0xFF (all pins input), on PFS173 default value is 0 (no pins input).
So any application using a digital pin as input should always set PxDIER for this pin.

2. I got strange 2x speed difference between PFS154 and PMS150C.
Both set to 0x80 in IHRCR. PMS150C is 2 times slower (pwm speed and instruction execution time).
I need to set IHRCR really high (0xDA) to get the same results. Is it normal?
Is there a IHRCR factory calibration value for PMS150C in memory?
Also nothing strange here. This is just how the ICs are manufactured (big variance from batch to batch from IC to IC).
Most production lots of PMS150C I bought need a much higher value in IHRCR than PFS154.
Only the flash based ICs (PFSxxx) do have a factory calibration value for IHRCR (@16MHz, @5.0V, @20°C).

Since variation of ICs is so big you always should include a tuning procedure after writing.
EasyPDK programmer and PADAUK_WRITER both support IHRCR calibration. You can find code examples how to use calibration inside of the release of EasyPDK programmer.


Have fun,

JS
Easy PDK programmer and more: https://free-pdk.github.io
 

Offline piotr_go

  • Contributor
  • Posts: 9
  • Country: pl
    • My Projects
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #833 on: February 17, 2020, 11:43:10 am »
No bug. Just like it is. If you want to use a pin as digital input you have to enable the digital input pin in PxDIER = "Port x Digital Input Enable Register".
Thank you for answer.
I thought PxC register is input/output switch and PxDIER is for wake up enable. There is nothing about input in bit definitions.

"Enable PA7~PA3 wake up event. 1 / 0 : enable / disable.
These bits can be set to low to disable wake up from PA7~PA3 toggling."

There is also nothing about it in "IO Pins" chapter.

"...all the pins can be independently set into two states output or input by configuring the data
registers (pa), control registers (pac) and pull-high registers (paph)......
If user wants to read the pin state, please notice that it should be set to input mode before
reading the data port....
When PMS15A/PMS150C is put in power-down or power-save mode, every pin can be
used to wake-up system by toggling its state. Therefore, those pins needed to wake-up system must be set to
input mode and set the corresponding bits of registers padier to high."

Only after analyzing "Hardware diagram of IO buffer", the reader may state that the description is incorrect.
The behavior of the chip also does not match the mentioned diagram. Read is always HI when PxDIER is LOW. If there is an AND gate, the read should be LOW.
Padauk put this AND gate in wrong place. It's a bug.

Also nothing strange here. This is just how the ICs are manufactured (big variance from batch to batch from IC to IC).

Exactly 2x speed difference looked too suspicious, so I asked.
« Last Edit: February 17, 2020, 01:42:23 pm by piotr_go »
 

Offline js_12345678_55AA

  • Regular Contributor
  • *
  • Posts: 200
  • Country: ht
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #834 on: February 17, 2020, 02:16:49 pm »
No bug. Just like it is. If you want to use a pin as digital input you have to enable the digital input pin in PxDIER = "Port x Digital Input Enable Register".
Thank you for answer.
I thought PxC register is input/output switch and PxDIER is for wake up enable. There is nothing about input in bit definitions.

"Enable PA7~PA3 wake up event. 1 / 0 : enable / disable.
These bits can be set to low to disable wake up from PA7~PA3 toggling."

There is also nothing about it in "IO Pins" chapter.

"...all the pins can be independently set into two states output or input by configuring the data
registers (pa), control registers (pac) and pull-high registers (paph)......
If user wants to read the pin state, please notice that it should be set to input mode before
reading the data port....
When PMS15A/PMS150C is put in power-down or power-save mode, every pin can be
used to wake-up system by toggling its state. Therefore, those pins needed to wake-up system must be set to
input mode and set the corresponding bits of registers padier to high."

Only after analyzing "Hardware diagram of IO buffer", the reader may state that the description is incorrect.
The behavior of the chip also does not match the mentioned diagram. Read is always HI when PxDIER is LOW. If there is an AND gate, the read should be LOW.
Padauk put this AND gate in wrong place. It's a bug.

I also learned it the hard way... spending a lot of time why PFS173 input pin sampling was not working... which was caused by default reset value of 0x00 in PxDIER on PFS173 vs. 0xFF on all other ICs I tried before (e.g. PMS150C/PFS154/PMS154B/...). PADAUK "fixes" this in their always inserted init code (MOV A, 0xFF , MOV PADIER, A) on PFS173.

JS
Easy PDK programmer and more: https://free-pdk.github.io
 

Offline gaganchd2000

  • Contributor
  • Posts: 5
  • Country: in
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #835 on: February 20, 2020, 02:37:49 am »
Hi
I am using PMS171B chip which Has ADC. I want to read the analog on one of the pins. first I tried to use Code generator feature of the IDE. On compilation I get this error.   "ADCC can't be 0x80 (Enable, 0x0:??)"

Expert can you please help and let me know what is the reason for error.
here is the standard code generated by IDE.


      // 1   :   All Assembly
      mov      A, 80h;
      mov      ADCC, A;         //   $ ADCC   Enable, PB0;  ( error is here)
      set1   AD_Start;
      .wait1   AD_Done;
      mov      a, ADCR;
      mov      buf[0], a;

 

Offline greenpossum

  • Contributor
  • Posts: 15
  • Country: au
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #836 on: February 22, 2020, 08:28:43 pm »
Thanks for the code. I seem to have an endianess problem somewhere.
I am using linux, but the IDE doesnt work with wine.
So I used windows to make and convert the file. Somehow bytes got swapped  :palm:

Just to mention that I installed Padauk's FPPA IDE 0.88 under Wine 3.7 on openSUSE Leap 15.1 and so far what I tested seems to work. I cloned Jay Carlson's bike light project from his Github repo and built it and it generated OBJ files. Or course when I tried to debug the program it couldn't find an ICE. I also ran Writer.exe and it started but it couldn't find a programmer on USB.

I hope this helps someone in case they need a working Padauk IDE on Linux to experiment with or whatever.

I don't actually have any Padauk MCUs, ICE, or programmer, I'm just playing around. Waiting for some module manufacturer like Elecrow to make and sell the open source Easy PDK programmer .

Sounds exciting. Great work, guys.
 

Offline gaganchd2000

  • Contributor
  • Posts: 5
  • Country: in
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #837 on: February 24, 2020, 09:32:59 pm »
Finally fix the issue myself. Was configuring incompatible values.
 

Offline tim_

  • Regular Contributor
  • *
  • Posts: 83
  • Country: de
Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
« Reply #838 on: February 26, 2020, 06:16:43 pm »
There is an article on Digitimes about our favourite MCU manufacturer:

https://www.digitimes.com/news/a20200225PD209.html

Quote
Taiwan-based MCU maker Padauk Technology expects its shipments of MCU products to grow by over 20% on year to reach 1.3 billion units in 2020, according to company Tang Tsan-bih.

Despite growing concerns about the stability of related supply chain caused by the coronavirus outbreak, Tang said that he believes demand for MCUs will remain strong, particularly from sectors including 5G base stations, servers and other cooling fan systems.

Boasting a group of strong supply chain partners, including Magnachip Semiconductor and Powerchip Semiconductor Manufacturing (PSMC) for wafer foundry and Greatek Electronics for IC backend services as well as inventories of needed components for up to three months, Padauk is readied to support product roll-outs of its clients, Tang stated.

For individual product category, shipments of 8-bit MCUs for BLDC (brushless DC) motors will account for about 30% of its totals sales in 2020, up from 23% a year earlier, Tang revealed.

Meanwhile, the company is also expected to see its shipments of MCUs for TWS (true wireless stereo) devices expand significantly in 2020, having shipped about 20 million units to the sector in 2019, according to an estimate of industry sources.

The sources also estimated that Padauk will see its 2020 revenues grow over 10% from the NT$522 million (US$17.17 million) it recorded a year ago.

Shares of the MCU maker is scheduled to debut on Taiwan's OTC securities market in the second half of March.

So they sell 1.3 billion units on 17.17 million revenue. That means their average selling price is just $0.013 USD! They must sell plenty of $0.01 USD microcontrollers... Also, 10% YoY ASP erosion. These guys are playing with fire - exactly the opposite of what every other company would do.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf