@@ -117,7 +117,7 @@ Axis::Axis(char axis,volatile Control_t* control) :CommandHandler("axis", CLSID_
117117 {
118118 driverChooser = ClassChooser<MotorDriver>(axis1_drivers);
119119 setInstance (0 );
120- this ->flashAddresses = AxisFlashAddresses ({ADR_AXIS1_CONFIG , ADR_AXIS1_MAX_SPEED , ADR_AXIS1_MAX_ACCEL , ADR_AXIS1_MAX_SLEWRATE_DRV ,
120+ this ->flashAddresses = AxisFlashAddresses ({ADR_AXIS1_CONFIG , ADR_AXIS1_MAX_SPEED , ADR_AXIS1_MAX_ACCEL ,
121121 ADR_AXIS1_ENDSTOP , ADR_AXIS1_POWER , ADR_AXIS1_DEGREES ,ADR_AXIS1_EFFECTS1 ,ADR_AXIS1_EFFECTS2 ,ADR_AXIS1_ENC_RATIO ,
122122 ADR_AXIS1_SPEEDACCEL_FILTER ,ADR_AXIS1_POSTPROCESS1 ,
123123 ADR_AXIS1_EQ1 ,ADR_AXIS1_EQ2 ,ADR_AXIS1_EQ3 ,
@@ -128,7 +128,7 @@ Axis::Axis(char axis,volatile Control_t* control) :CommandHandler("axis", CLSID_
128128 {
129129 driverChooser = ClassChooser<MotorDriver>(axis2_drivers);
130130 setInstance (1 );
131- this ->flashAddresses = AxisFlashAddresses ({ADR_AXIS2_CONFIG , ADR_AXIS2_MAX_SPEED , ADR_AXIS2_MAX_ACCEL , ADR_AXIS2_MAX_SLEWRATE_DRV ,
131+ this ->flashAddresses = AxisFlashAddresses ({ADR_AXIS2_CONFIG , ADR_AXIS2_MAX_SPEED , ADR_AXIS2_MAX_ACCEL ,
132132 ADR_AXIS2_ENDSTOP , ADR_AXIS2_POWER , ADR_AXIS2_DEGREES ,ADR_AXIS2_EFFECTS1 ,ADR_AXIS2_EFFECTS2 , ADR_AXIS2_ENC_RATIO ,
133133 ADR_AXIS2_SPEEDACCEL_FILTER ,ADR_AXIS2_POSTPROCESS1 ,
134134 ADR_AXIS2_EQ1 ,ADR_AXIS2_EQ2 ,ADR_AXIS2_EQ3 ,
@@ -138,7 +138,7 @@ Axis::Axis(char axis,volatile Control_t* control) :CommandHandler("axis", CLSID_
138138 else if (axis == ' Z' )
139139 {
140140 setInstance (2 );
141- this ->flashAddresses = AxisFlashAddresses ({ADR_AXIS3_CONFIG , ADR_AXIS3_MAX_SPEED , ADR_AXIS3_MAX_ACCEL , ADR_AXIS3_MAX_SLEWRATE_DRV ,
141+ this ->flashAddresses = AxisFlashAddresses ({ADR_AXIS3_CONFIG , ADR_AXIS3_MAX_SPEED , ADR_AXIS3_MAX_ACCEL ,
142142 ADR_AXIS3_ENDSTOP , ADR_AXIS3_POWER , ADR_AXIS3_DEGREES ,ADR_AXIS3_EFFECTS1 ,ADR_AXIS3_EFFECTS2 ,ADR_AXIS3_ENC_RATIO ,
143143 ADR_AXIS3_SPEEDACCEL_FILTER ,ADR_AXIS3_POSTPROCESS1 ,
144144 ADR_AXIS3_EQ1 ,ADR_AXIS3_EQ2 ,ADR_AXIS3_EQ3 ,
@@ -207,9 +207,6 @@ void Axis::registerCommands(){
207207 registerCommand (" handsoff" , Axis_commands::handsoff, " Hands-off enable" , CMDFLAG_GET | CMDFLAG_SET );
208208 registerCommand (" handsoff_speed" , Axis_commands::handsoff_speed, " Hoff speed thrld (deg/s)" , CMDFLAG_GET | CMDFLAG_SET );
209209 registerCommand (" handsoff_accel" , Axis_commands::handsoff_accel, " Hoff accel std dev thrld (float, val/1000)" , CMDFLAG_GET | CMDFLAG_SET );
210-
211- registerCommand (" maxSlewRateDrv" , Axis_commands::maxSlewRateDrv, " Max driver torque in counts/ms" ,CMDFLAG_GET );
212- registerCommand (" calibrate_maxSlewRateDrv" , Axis_commands::calibrate_maxSlewRateDrv, " Start driver slewRate calib" , CMDFLAG_GET );
213210}
214211
215212/*
@@ -241,13 +238,6 @@ void Axis::restoreFlash(){
241238 pulseErrLed ();
242239 }
243240
244- // save the max torque for the slew rate
245- if (Flash_Read (flashAddresses.maxSlewRateDrv , &value)){
246- this ->maxSlewRate_Driver = value;
247- }else {
248- pulseErrLed ();
249- }
250-
251241
252242 uint16_t endstopRawValue, power;
253243 if (Flash_Read (flashAddresses.endstop , &endstopRawValue)) {
@@ -332,7 +322,6 @@ void Axis::saveFlash(){
332322 Flash_Write (flashAddresses.config , Axis::encodeConfToInt (this ->conf ));
333323 Flash_Write (flashAddresses.maxSpeed , this ->maxSpeedDegS );
334324 Flash_Write (flashAddresses.maxAccel , (uint16_t )(this ->maxTorqueRateMS ));
335- Flash_Write (flashAddresses.maxSlewRateDrv , (uint16_t )(this ->maxSlewRate_Driver ));
336325
337326 Flash_Write (flashAddresses.endstop , effectRatio | (endstopStrength << 8 ));
338327 Flash_Write (flashAddresses.power , power);
@@ -446,29 +435,6 @@ void Axis::prepareForUpdate(){
446435 startForceFadeIn (0 , 1.0 );
447436 }
448437
449- // Check for pending slew rate calibration result
450- if (this ->awaitingSlewCalibration ){
451- // If driver reports calibration finished, retrieve measured value and persist
452- if (!drv->isSlewRateCalibrationInProgress ()){
453- // Get value from drv
454- this ->maxSlewRate_Driver = drv->getDrvSlewRate ();
455-
456- // If the driver's max slew rate is lowest thant current max flew rate, cap the value and send the new value to the UI
457- if (this ->maxSlewRate_Driver < this ->maxTorqueRateMS ) {
458- this ->maxTorqueRateMS = this ->maxSlewRate_Driver ;
459- CommandHandler::broadcastCommandReply (CommandReply (this ->maxTorqueRateMS ), (uint32_t )Axis_commands::slewrate, CMDtype::get);
460- }
461-
462- // Broadcast a friendly completion message and the numeric value
463- CommandHandler::broadcastCommandReply (CommandReply (" Slew rate calibration complete" ,0 ), (uint32_t )Axis_commands::calibrate_maxSlewRateDrv, CMDtype::get);
464- CommandHandler::broadcastCommandReply (CommandReply (this ->maxSlewRate_Driver ), (uint32_t )Axis_commands::maxSlewRateDrv, CMDtype::get);
465-
466-
467- this ->awaitingSlewCalibration = false ;
468- }
469- }
470-
471-
472438 this ->updateMetrics (angle);
473439 this ->updateHandsOffState ();
474440
@@ -512,33 +478,44 @@ void Axis::setDrvType(uint8_t drvtype)
512478 {
513479 return ;
514480 }
515- cpp_freertos::CriticalSection::Enter ();
516- MotorDriver* drv = driverChooser.Create ((uint16_t )drvtype);
517- this ->drv .reset (drv);
518- if (drv == nullptr )
481+
482+ // Create the driver outside of the critical section to avoid FreeRTOS issues (semaphore take with interrupts disabled)
483+ MotorDriver* drv_new = driverChooser.Create ((uint16_t )drvtype);
484+
485+ if (drv_new == nullptr )
519486 {
520- cpp_freertos::CriticalSection::Exit ();
521487 return ;
522488 }
489+
490+ // Pre-initialization outside of critical section
491+ if (!drv_new->hasIntegratedEncoder ()){
492+ drv_new->setEncoder (this ->enc );
493+ }
494+ drv_new->setupDriver ();
495+
496+ // Use critical section only for atomic replacement of the driver pointer
497+ MotorDriver* old_drv_ptr = nullptr ;
498+ cpp_freertos::CriticalSection::Enter ();
499+ old_drv_ptr = this ->drv .release (); // Detach the old driver safely
500+ this ->drv .reset (drv_new); // Attach the new driver
523501 this ->conf .drvtype = drvtype;
524- this -> maxTorqueRateMS = drv-> getDrvSlewRate ();
502+ cpp_freertos::CriticalSection::Exit ();
525503
526- // Pass encoder to driver again
527- if (! this -> drv -> hasIntegratedEncoder ()) {
528- this -> drv -> setEncoder ( this -> enc ) ;
504+ // Delete the old driver outside of the critical section to avoid blocking destructors or FreeRTOS issues
505+ if (old_drv_ptr != nullptr ) {
506+ delete old_drv_ptr ;
529507 }
530508
531- drv-> setupDriver ();
509+ // Perform SPI communications (start/suspend) outside of the critical section
532510 if (!tud_connected ())
533511 {
534512 control->usb_disabled = false ;
535513 this ->usbSuspend ();
536514 }
537515 else
538516 {
539- drv ->startMotor ();
517+ drv_new ->startMotor ();
540518 }
541- cpp_freertos::CriticalSection::Exit ();
542519}
543520
544521
@@ -694,13 +671,13 @@ void Axis::calculateMechanicalEffects(bool ffb_on){
694671 // Always active damper
695672 if (damperIntensity != 0 ){
696673 float speedFiltered = (metric.current .speed ) * (float )damperIntensity * AXIS_DAMPER_RATIO ;
697- mechanicalEffectTorque -= damperFilter.process (clip<float , int32_t >(speedFiltered, -internalFxClip, internalFxClip ));
674+ mechanicalEffectTorque -= damperFilter.process (clip<float , int32_t >(speedFiltered, -INTERNAL_FX_CLIP , INTERNAL_FX_CLIP ));
698675 }
699676
700677 // Always active inertia
701678 if (inertiaIntensity != 0 ){
702679 float accelFiltered = metric.current .accel * (float )inertiaIntensity * AXIS_INERTIA_RATIO ;
703- mechanicalEffectTorque -= inertiaFilter.process (clip<float , int32_t >(accelFiltered, -internalFxClip, internalFxClip ));
680+ mechanicalEffectTorque -= inertiaFilter.process (clip<float , int32_t >(accelFiltered, -INTERNAL_FX_CLIP , INTERNAL_FX_CLIP ));
704681 }
705682
706683 // Always active friction. Based on effectsCalculator implementation
@@ -719,7 +696,7 @@ void Axis::calculateMechanicalEffects(bool ffb_on){
719696 }
720697 int8_t sign = speed >= 0 ? 1 : -1 ;
721698 float force = (float )frictionIntensity * rampupFactor * sign * INTERNAL_AXIS_FRICTION_SCALER * 32 ;
722- mechanicalEffectTorque -= frictionFilter.process (clip<float , int32_t >(force, -internalFxClip, internalFxClip ));
699+ mechanicalEffectTorque -= frictionFilter.process (clip<float , int32_t >(force, -INTERNAL_FX_CLIP , INTERNAL_FX_CLIP ));
723700 }
724701
725702}
@@ -828,7 +805,7 @@ int32_t Axis::calculateEndstopTorque(){
828805 return 0 ;
829806 }
830807 float endstopTorque = clipDirection*metric.current .posDegrees - (float )this ->degreesOfRotation /2.0 ; // degress of rotation counts total range so multiply by 2
831- endstopTorque *= (float )endstopStrength * endstopGain ; // Apply endstop gain for stiffness.
808+ endstopTorque *= (float )endstopStrength * ENDSTOP_GAIN ; // Apply endstop gain for stiffness.
832809 endstopTorque *= -clipDirection;
833810
834811 return clip<int32_t ,int32_t >(endstopTorque,-0x7fff ,0x7fff );
@@ -1155,35 +1132,10 @@ CommandStatus Axis::command(const ParsedCommand& cmd,std::vector<CommandReply>&
11551132 case Axis_commands::slewrate:
11561133 {
11571134 if (cmd.type == CMDtype::get){
1158- // If driver has a more restrictive calibrated value, update the axis limit
1159- if (maxSlewRate_Driver < this ->maxTorqueRateMS ) {
1160- this ->maxTorqueRateMS = maxSlewRate_Driver;
1161- }
11621135 replies.emplace_back (this ->maxTorqueRateMS );
11631136 }else if (cmd.type == CMDtype::set){
1164- this ->maxTorqueRateMS = clip<uint32_t ,uint32_t >(cmd.val , 0 , maxSlewRate_Driver);
1165- }
1166- }
1167- break ;
1168-
1169- case Axis_commands::calibrate_maxSlewRateDrv:
1170- {
1171- if (cmd.type == CMDtype::get){
1172- // Start calibration on driver and set awaiting flag if start is OK
1173- if (drv->startSlewRateCalibration ()) {
1174- this ->awaitingSlewCalibration = true ;
1175- } else {
1176- // Inform user that calibration can't started
1177- CommandHandler::broadcastCommandReply (CommandReply (" Slew rate calibration unsupported" ,1 ), (uint32_t )Axis_commands::calibrate_maxSlewRateDrv, CMDtype::get);
1178- }
1179- replies.emplace_back (1 ); // ack
1137+ this ->maxTorqueRateMS = cmd.val ;
11801138 }
1181- break ;
1182- }
1183-
1184- case Axis_commands::maxSlewRateDrv:
1185- if (cmd.type == CMDtype::get) {
1186- replies.emplace_back (maxSlewRate_Driver);
11871139 }
11881140 break ;
11891141
@@ -1248,14 +1200,6 @@ CommandStatus Axis::command(const ParsedCommand& cmd,std::vector<CommandReply>&
12481200 if (this ->getEncoder () != nullptr ){
12491201 cpr = this ->getEncoder ()->getCpr ();
12501202 }
1251- // TODO: For TMC4671 drivers, CPR reporting might be inconsistent. Investigate if a prescale is needed or if the UI should handle the readout correction.
1252- // #ifdef TMC4671DRIVER // CPR should be consistent with position. Maybe change TMC to prescale to encoder count or correct readout in UI
1253- // TMC4671 *tmcdrv = dynamic_cast<TMC4671 *>(this->drv.get()); // Special case for TMC. Get the actual encoder resolution
1254- // if (tmcdrv && tmcdrv->hasIntegratedEncoder())
1255- // {
1256- // cpr = tmcdrv->getEncCpr();
1257- // }
1258- // #endif
12591203 replies.emplace_back (cpr);
12601204 }else {
12611205 return CommandStatus::ERR ;
0 commit comments