Software interrupts may be used to finish off an interrupt task at a lower priority. Timing critical code is often given a high interrupt priority to avoid too much latency. Once the timing critical part is finished, there may be additional tasks that may be too timing critical for the main loop, but are not so critical as to hold-up other high-priority interrupts. Triggering a lower-priority software interrupt can accomplish this.
For example, suppose you have multiple stepper motors each with their own timer. The timer interrupts are given a high-priority to minimize step jitter. The most timing critical task may be as simple as setting or clearing a step pulse or advancing the phase outputs. There may be additional functionality required such as calculation of acceleration ramps, sensor processing, etc. Since this needs to be processed every step, it may not be appropriate to process this from main() as the main loop timing may be too long. These additional tasks may be processed by a lower-priority software interrupt so as not to increase the latency of the other high-priority stepper channels.
What are the difference between a software interrupt and a function?
A function gets called immediately from wherever it is called and does not change current interrupt priority level if called from a interrupt. A software interrupt is an interrupt trigger that will cause that interrupt to be called when it's priority comes up. If a function call were inserted at the end of a high-priority interrupt, the function would be contained within that high-priority. By triggering the lower-priority software interrupt and then returning from the high-priority interrupt, the functionality gets called at the new (lower) priority.