"ALL" you need to do is pass the standard sanity checklist and it will work:
Add to these, adjust to suit your perspectives, then print and pin them on your forehead for future reference.
When in trouble, regroup, shorten battle lines, tactically withdraw and concentrate forces on the known areas of attack - aka get the minimum possible system going that does not fail, turn off any code not needed, disable any peripherals etc that you don't need, discard as much as you can of even what you do "need" until you get back to a stable state. THEN advance one change at a time. Be aware that if you make 3 changes a b c in order and a and b work OK and c doesn't then eg a+c may produce a combined fault between them - it may not be just c that is at fault.
If you do not show what is on every pin on your circuit diagram then you are abusing those who seek to help you and risking fooling yourself*.
If you have set a programmatically or initialisation alterable state on any pin then you need to say what you have done as otherwise you are abusing those who seek to help you and risking fooling yourself*.
Go through the datasheet and confirm that EVERY pin is connected to something valid based on it's logical state. Write down what you have done on the circuit diagram and associated notes.
Describe ALL programmatically or initialisation settable actions you have taken. Datasheet default is assumed for anything you do not say you have set. Stating what the datasheet default is in each case helps people help you and helps you not fool yourself.
Every ground pin should be grounded.
Every Vdd pin should be connected to Vdd.
EVERY input should be connected to a known defined state by a resistance path no higher than what is legally allowed by the data sheet. (Limiting case if not otherwise specified is (offset voltages + bias currents x Resistor path + termination point voltage) all set to the worsts case value and polarity in each case should always place the pin in a valid voltage range. (An internal pullup or pulldown qualifies as a known state as long as you do actually implement it).
Every control pin state must be known and set to a level that specifies a state that is acceptable to you in the overall configuration that you have chosen.
Any operating interrupt generating times must produce known and knowable outcomes.
Known: eg if you have a watchdog timer interrupting operation it must be either prevented from acting by program or hardware action OR it must produce a valid outcome when it acts.
Knowable: If you have a live interrupt it's vector must be set and it must go to valid code whose outcome is acceptable.
Brownout interrupts must be set so power supplies used are valid.
Know what is in data registers - either by bulk setting during startup or by explicit setting that is an unavoidable part of a routine OR know that it does not matter in a given case. If bulk setting at startup be sure this is a valid reason to use the register with confidence subsequently.
No ESD conditions.
IC not damaged.
Power supply not spiky / noisy / brownoutable.
"Too hard" and "can't understand"are not conditions understood by a microcontroller, or Murphy. If a peripheral or register has options that you cannot master with confidence then to be certain of outcomes you MUST select some other option for that peripheral or register that you are certain [tm] that you do understand fully. eg if there is a timer that you are not master of, disable it. If you use an interrupt vector, understand it completely. If you don't and cannot or do not want to spend the time DO NOT GUESS.- disable it at this stage until you get the system stable.
ALL the above constitutes a minumum degree of rigour when programming and implementing even the most trivial microcontroller systems. If you cannot or will not do all the above on every occasion then you are not doing the minimum that it takes to do the job properly.