See also Abstraction or HAL
A hardware abstraction is software that provides access to hardware in a way that hides details that might otherwise make using the hardware difficult. Typically, access is provided via an interface that allows devices that share a level of compatibility to be accessed via the same software interface even though the devices provide different hardware interfaces. A hardware abstraction can support the development of cross-platform applications.
Early software was developed without a hardware abstraction which required a developer to understand multiple devices in order to provide compatibility. With hardware abstraction, the software leverages the abstraction to access significantly different hardware via the same interface. The abstraction (often implemented in the operating system) which then generates hardware-dependent instructions. This allows software to be compatible with all devices supported by the abstraction.
Consider the joystick device, of which there are many physical implementations. It could be accessible via an application programming interface (API) that support many different joysticks to support common operations such as moving, firing, configuring sensitivity and so on. A Joystick abstraction hides details (e.g., register format, I2C address) so that a programmer using the abstraction, does not need to understand the details of the device's physical interface. This also allows code reuse since the same code can process standardized messages from any kind of implementation which supplies the joystick abstraction. For example, a "nudge forward" can be from a potentiometer or from a capacitive touch sensor that recognizes "swipe" gestures, as long as they both provide a signal related to "movement".
As physical limitations may vary with hardware, an API can do little to hide that, other than by assuming a "least common denominator" model. Thus, certain deep architectural decisions from the implementation may become relevant to users of a particular instantiation of an abstraction.
A good metaphor is the abstraction of transportation. Both bicycling and driving a car are transportation. They both have commonalities (e.g., you must steer) and physical differences (e.g., use of feet). One can always specify the abstraction "drive to" and let the implementor decide whether bicycling or driving a car is best. The "wheeled terrestrial transport" function is abstracted and the details of "how to drive" are encapsulated.