Hi NoahXu,
I ported sw project to S12ZVML31 some time ago, but I didn't follow the AN5330. I would like to also highlight, that I didn't work with EFP project, but with AN5327SW.
Here are some hints for project modifications, that might be useful for you:
- I would like to recommend creating new bareboard project for S12ZVML31 as a source project for mc9s12zvml31.h and mc9s12zvml31.c files.
- The AN5327 wouldn’t fit into 4kB of RAM. So we have to optimize the code, for example by removing the FreeMASTER
- #include "freemaster.h"
- FMSTR_Init();
- FMSTR_Poll();
- FMSTR_Recorder();
- Whole TSA table definition starting from FMSTR_TSA_TABLE_BEGIN(S12ZVM_PMSM) and ends by FMSTR_TSA_TABLE_LIST_END()
- At MC9S12ZVML128_PMSM.c comment-out lines:
- At motor_structure.h comment out:
- Edit the S12zvm.prm linker file (you may look at mc9s12zvml31.prm in S12ZVML31 source project)
- New RAM range will be: RAM = READ_WRITE 0x001000 TO 0x001FFF; //S12ZVML31 range
- New ROM range will be: ROM = READ_ONLY 0xFF8000 TO 0xFFFDFF; //S12ZVML31 range
- Link to S12ZVML31 MCU
- Copy the mc9s12zvml31.h and mc9s12zvml31.c from S12ZVML31 source project to the AN5327 project
- Now you may either edit appropriate c and h files and replace all includes to the new header files (clean way) or you may backup the mc9s12zvml128 version c and h files and rename mc9s12zvml31.h and mc9s12zvml31.c files as mc9s12zvml128.h and mc9s12zvml128.c (fast way)
- If you choose the fast way in the previous step, do not forget to edit the new version of mc9s12zvml128.c and modify the line with the header file include
- You may implement dual step alignment in in the StateAlign() function:
/*+++++++++++++++ dual state alignment improvement +++++++++++++++ */
//Old code:
// drvFOC.uDQReq.f16Arg1 = drvFOC.alignVoltage;
// drvFOC.uDQReq.f16Arg2 = FRAC16(0);
//New code:
if (drvFOC.alignCntr>(tU16)(drvFOC.alignCntrInit*ALIGN_D_FACTOR))
{
drvFOC.uDQReq.f16Arg1 = FRAC16(0);
drvFOC.uDQReq.f16Arg2 = drvFOC.alignVoltage;
}
else
{
drvFOC.uDQReq.f16Arg1 = drvFOC.alignVoltage;
drvFOC.uDQReq.f16Arg2 = FRAC16(0);
}
/*+++++++++++++++ dual state alignment improvement end +++++++++++++++ */
- Since S12ZVML31 applications are mostly LIN based and do not use external oscilator, the clock init needs to be modified to PEI mode. For example:
void cpmu_init(void)
{
// Wait for stable supply after power up
while (GDUF_GLVLSF)
GDUF_GLVLSF = 1;
CPMUSYNR = 0x00;
CPMUPOSTDIV_POSTDIV = 0;
CPMUREFDIV = 0;
//CPMUSYNR = 0xF1; // 100MHz VCO output
CPMUSYNR = 0x67; // 80MHz VCO output
CPMUIFLG = 0xFF; // clear all flags, especially LOCKIF and OSCIF
// CPMUREFDIV_REFDIV = 3; // 4MHz => 1MHz
// CPMUREFDIV_REFFRQ = 0; // 0 for 1MHz - 2MHz
// CPMUSYNR_SYNDIV = 49; // 100 MHz VCO output
// CPMUSYNR_VCOFRQ = 3;
// CPMUPOSTDIV_POSTDIV = 0; // 100MHz
//
// CPMUOSC_OSCE = 1;
//
CPMUHTCTL_VSEL = 0; //Voltage Access Select Bit
CPMUHTCTL_HTE = 1; //High Temperature Sensor/Bandgap Voltage Enable Bit
//
// // Wait for oscillator to start up (UPOSC=1) and PLL to lock (LOCK=1).
// while (CPMUIFLG_UPOSC == 0) {};
while (CPMUIFLG_LOCK == 0) {};
while(CPMUCLKS != 0b10000000) // After writing CPMUCLKS register, it is strongly recommended to read
{ // back CPMUCLKS register to make sure that write of PLLSEL,
// RTIOSCSEL, COPOSCSEL0 and COPOSCSEL1 was successful.
CPMUCLKS = 0b10000000;
/* ||||||||-------- COPOSCSEL0 - COP Clock Select 0
|||||||--------- RTIOSCSEL - RTI Clock Select
||||||---------- PCE - COP Enable During Pseudo Stop Bit
|||||----------- PRE - RTI Enable During Pseudo Stop Bit
||||------------ COPOSCSEL1 - COP Clock Select 1
|||------------- CSAD - COP in Stop Mode ACLK Disable
||-------------- PSTP - Pseudo Stop Bit
|--------------- PLLSEL - PLL Select Bit
*/
}
CPMURFLG = 0x60; //Clear PORF and LVRF
}
- You may implement also improved startup in focSlowLoop() function:
/*++++++++++++ Improved motor startup code update ++++++++++++*/
// Speed FO control mode
// Obsolete code:
// if(cntrState.usrControl.FOCcontrolMode == speedControl)
// drvFOC.currentLoop.pIDQReq->f16Arg2 = GFLIB_ControllerPIpAW(drvFOC.pospeControl.wRotElErr,&drvFOC.speedPI);
// New code:
if(cntrState.usrControl.FOCcontrolMode == speedControl)
{
if(pos_mode == sensorless1)
{
// In Speed control and sensorless mode, FOC Outer Loop (Speed Loop & Field Weakening) output is interconnected with FOC Inner Loop (Current Loop) input
drvFOC.currentLoop.pIDQReq->f16Arg1 = FRAC16(0.0);
drvFOC.currentLoop.pIDQReq->f16Arg2 = GFLIB_ControllerPIpAW(drvFOC.pospeControl.wRotElErr,&drvFOC.speedPI);
}
else
{
// In Speed control and force/tracking mode, required d-axis current is set to Start-up current and q-axis current is set to 0
drvFOC.currentLoop.pIDQReq->f16Arg1 = drvFOC.pospeOpenLoop.iQUpperLimit;
drvFOC.currentLoop.pIDQReq->f16Arg2 = FRAC16(0.0);
}
}
/*++++++++++++ Improved motor startup code update end ++++++++++++*/
- If you use your own design with different transistors, you may also reach issue with dead-time (the time delay between we disable the top transistor and enabling the bottom transistor or in the opposite way).
For editing, go to pmf_init() function in pmf.c file and increase the dead time value in PMFDTMA register. I tried for example value 60 (0.6us) instead of 20 (0.2us). The right value must be set according measurement on all three phases on target pcb (plus some margin).
After building project, you may edit the debug Configuration. Here is described fast way by editing the current debug Configuration.
- Go to Target Settings and edit the Connection


- Select S12ZVML31 Target type

Of course, you may create your own Debug Configuration instead of it.
I hope it helps you.
Best regards
RadekS