TL;DR:
On your distribution system:
- create a public/private keypair.
- ship the public key with the first firmware release.
- create an update package.
- use HMAC to create a secure hash of the package.
- sign the hash using your private key.
- distribute the package and the signature.
On the device:
- check the hash to determine integrity.
- check the signature to determine authenticity.
First, you generate a keypair on your build system. You will have a public and a private keys. Put the public key on the original firmware of the shipped devices. This is the initial release. Keep the private key on secure storage, ideally inside a disconnected computer (with no network access).
When you release an update, you must use the private key created earlier to sign the update package. You can add the package to a zip file, together with a text file containing the signature you generated earlier. Send the file to the microcontroller.
After receiving the zip file, the microcontroller will decompress both the signature and the update, run a signature check and compare the resulting signature with the signature in the zip file. If they are the same, the package integrity is assured and it knows you (and not someone else) created the package.
If you don't have enough memory for unzip and check, you must create a special file format containing both the signature and the update. You can even implement SHA256HMAC on a microcontroller.
As Mike Scott said, after sending the update, you must have some process in place to atomically replace the current firmware with the new one. I've seen a system that creates two partitions on the storage, and use one for the current firmware and another for updates. After the update is applied and checked, a flag is set on the bootloader to indicate which partition to load. And you can change the bootloader to indicate which partition you will load during boot.