L'impression de caractères variables sur UART ne fonctionne pas, les constantes fonctionnent correctement

9

J'ai un problème assez étrange avec XC8 sur un microcontrôleur PIC18F27K40. Sur un PIC16F1778 cela fonctionne . J'ai défini:

void uart_putch(unsigned char byte) {
    while (!PIR3bits.TX1IF);
    TX1REG = byte;
}

Lorsque, dans ma mainboucle, j'appelle uart_putch('a');, cela fonctionne bien. Cependant, lorsque je définis const char c = 'a';et appelle uart_putch(c);, cela ne fonctionne pas. Il imprime quelque chose, mais pas un a- je pense que ce sont des 0x00personnages dont je tire hexdump -x /dev/ttyUSB0. Ce n'est pas un problème avec le port série de mon ordinateur; J'ai regardé avec une lunette et le signal est différent (gauche fonctionne, droite non):

entrez la description de l'image ici

Le code est simple:

void main(void) {
    init(); // Sets up ports and UART control registers
    while (1) {
        uart_putch('a'); // or c
    }
}

Ce qui ne fonctionne pas non plus est en utilisant l' une des fonctions de chaîne ( puts, printf, etc.), qui je pense est lié - donc dans cette question que je fait un exemple de travail minimal avec des caractères.

L'assembly généré lorsque j'utilise une variable ca:

_c:
    db  low(061h)
    global __end_of_c

_main:
    ; ...
    movlw   low((_c))
    movwf   tblptrl
    if  1   ;There is more than 1 active tblptr byte
    movlw   high((_c))
    movwf   tblptrh
    endif
    if  1   ;There are 3 active tblptr bytes
    movlw   low highword((_c))
    movwf   tblptru
    endif
    tblrd   *
    movf    tablat,w
    call    _putch

Et avec une constante, il a dans le _mainbloc:

    movlw   (061h)&0ffh 
    call    _putch

J'utilise le compilateur MPLAB XC8 C V1.41 (24 janvier 2017), avec la prise en charge partielle de la version 1.41.

Les parties pertinentes de mon Makefile:

CC:=xc8
CFLAGS:=-I. --chip=18F27K40 -Q -Wall

SRC:=main.c uart.c
DEP:=uart.h
PRS:=$(subst .c,.p1,$(SRC))
OBJ:=main.hex

all: $(OBJ)

$(OBJ): $(PRS)
    $(CC) $(CFLAGS) $^

$(PRS): %.p1: %.c $(DEP)
    $(CC) $(CFLAGS) -o$@ --pass1 $<

Toute aide pour le faire fonctionner serait très appréciée.


la source
1
Définissez votre uart_putch comme "uart_putch (const char & c)". C'est ce qu'on appelle "passer par référence".
Rohat Kılıç
1
@ RohatKılıç C'est du C ++
TisteAndii
1
@tcrosley Je voulais inclure cela, désolé. Cela ne fait aucune différence (ne fonctionne toujours pas). J'ai essayé tous unsigned char, char, const unsigned charet const char.
1
Dans votre définition de putch (), que se passe-t-il si vous renommez l'argument à la byteTxplace? Je crains que cela bytene soit défini ailleurs comme un type de données. (On dirait que cela générerait un diagnostic du compilateur, mais clairement quelque chose d'étrange se passe ici.) Et comme un autre test, se putch(0x61)comporte-t-il de la même manière que putch('a')? Je me demande si l'instruction de lecture de table lit des données 8 bits ou 16 bits. Le registre PIC W n'est que de 8 bits, non?
MarkU
2
@MarkU j'ai donc essayé un PIC16F1778 et là la même chose fonctionne bien. (ce qui en fait un problème beaucoup moins grave pour moi car je suis bien avec l'une ou l'autre puce, mais je serais toujours intéressé de savoir comment faire fonctionner le 18F27K40 ..)

Réponses:

3

Votre programme va bien, c'est un bug sur le PIC18F27K40.

Voir http://ww1.microchip.com/downloads/en/DeviceDoc/80000713A.pdf

Utilisez XC8 compilier V1.41 et mplabx IDE, sélectionnez XC8 Global options / XC8 linker et sélectionnez "Additional options", puis ajoutez +nvmregdans la zone Errata et tout ira bien.

Extrait du document lié, mots clés en gras:

TBLRD requiert une valeur NVMREG pour pointer vers la mémoire appropriée

Les révisions affectées au silicium des dispositifs PIC18FXXK40 nécessitent de manière incorrecte que les NVMREG<1:0>bits du NVMCONregistre soient définis pour l' TBLRDaccès aux différentes régions de mémoire. Le problème est plus apparent dans les programmes C compilés lorsque l'utilisateur définit un type const et que le compilateur utilise des TBLRDinstructions pour récupérer les données de la mémoire Flash du programme (PFM). Le problème est également apparent lorsque l'utilisateur définit un tableau dans la RAM pour lequel le complice crée un code de démarrage, exécuté auparavant main(), qui utilise des TBLRDinstructions pour initialiser la RAM à partir de PFM.

Ian Munro
la source
2

les caractères const sont stockés dans la mémoire du programme (flash), et il semble que le compilateur voit que vous ne l'utilisez pas comme variable (car il ne change jamais) et l'optimise dans la mémoire du programme, que vous utilisiez const ou non.

Essayez de le déclarer comme volatile char c= 'a';. Cela le forcera à être stocké dans SRAM plutôt que flash.

Pourquoi est-ce important?

Sur les PIC18, l'utilisation de la directive db (dataoctet pour stocker un octet dans la mémoire du programme) avec un nombre impair d'octets (comme dans votre cas) le remplira automatiquement avec des zéros. Ce comportement diffère de celui du PIC16, c'est probablement pourquoi il fonctionne sur l'un mais pas sur l'autre. Pour cette raison, les chaînes ou les caractères stockés dans la mémoire flash ne fonctionneront pas non plus avec les fonctions de chaîne standard, telles que strcpy ou printf. Stocker quelque chose dans la mémoire du programme n'est pas automatiquement sécurisé.

Sur la base de l'assemblage, il est assez clair que le chargement des 8 octets est incorrect. Ce qui est 0x00, donc il envoie correctement 0x00 (comme vous l'avez bien confirmé).

Il peut être difficile de prédire ce que vous obtiendrez avec la quantité folle d'optimisation du compilateur de nos jours, donc je ne sais pas si cela fonctionnera. l'astuce volatile devrait fonctionner, mais si vous voulez vraiment le stocker en flash, essayez ceci:

TXREG = data & 0xff;

ou peut-être

TXREG = data & 0x0ff;

Je sais qu'en théorie, cela ne devrait rien faire. Mais nous essayons de changer la sortie d'assembly du compilateur pour faire ce que nous voulons, et non pas en quelque sorte mais pas vraiment ce que nous voulons.

Dans le Guide de l'utilisateur MPASM:

entrez la description de l'image ici

Je recommande également de le vérifier vous - même , ainsi que code_pack, dans le PDF. Page 65.

métacolline
la source