Цитата(Jenya7 @ Jan 20 2015, 13:50)

тут у меня unsigned char потому что это касается UART я передаю данные 8 бит.
А складываете вы их всегда в массив unsigned char? И берете всегда из массива unsigned char? Эта функция по идее считает CRC чего угодно. Вот и передавать ей надо "указатель на что угодно", т.е void const *, а внутри заводите уже временную переменную типа "указатель на байт" и присваивайте ей переданный указатель с явным приведением типа. Это позволит написать
Код
typedef struct { ...... } message_t;
message_t Message = {.....};
Checksum = MessageChecksum(&Message, sizeof(Message));
избежав явного приведения типа (unsigned char const *)&Message в большинстве точек вызова. А это разгружает исходник, делая его более легкочитаемым.
Цитата(Jenya7 @ Jan 20 2015, 13:50)

или все равно привести к uint32_t?
Привести к uint32_t что? Вы передает
указатель. От того, на какой тип этот указатель указывает его размер не изменится. А вот если размер ваших сообщений по спецификации протокола не может превышать 255 или 65535 байт, то параметр len имеет смысл делать uint_fast8_t или uint_fast16_t.
Цитата(Jenya7 @ Jan 20 2015, 13:50)

uint_fastXX_t это если я захочу перенести код на AVR

Не обязательно AVR. Вы можете захотеть его перенести на 16- 32- или 64-битную архитектуру, которая умеет делать арифметику с числами 8- или 16-битной разрядности (MSP430 или персоналку). И чтобы этот код и на другой архитектуре тоже был оптимальным без перелопачивания тысяч строк кода, имеет смысл сразу писать его грамотно (или хотя бы стараться писать грамотно).