Hallo,
seit kurzem schlage ich mich mit einem STM32 (STM32F103C8T8) herum und
der tut inzwischen auch einigermaßen was er soll, aber jetzt habe ich
ein Problem bei dem ich nicht weiter komme:
Die IOs GPIOA4-7 verwende ich als Datenleitungen zum ansteuern eines
LCDs, die Steuerleitungen des LCDs habe ich an GPIOC13-15 angeschlossen.
Funktioniert soweit auch hervorragend.
Nun wollte ich die CAN-Schnittstelle an GPIOA11-12 in Betrieb nehmen und
habe das Problem, dass ich jedes mal, wenn der Controller die
Datenrichtung der Datenleitungen umschalten soll in der
HardFaultException lande, nehme ich nur die Pin-Konfiguration für die
CAN-PINs:
// Configure CAN pin: RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Configure CAN pin: TX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
aus dem Programm, funktioniert zwar meine CAN-Schnittstelle nicht, dafür
bekomme ich aber auch keinen HardFault mehr. Konfiguriere ich die
CAN-Pins wieder und initialisiere die CAN:
/* CAN register init */
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = ENABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_5tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
CAN_InitStructure.CAN_Prescaler = 4; // CLK=64MHz/2
CAN_Init(CAN1, &CAN_InitStructure);
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber=0;
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
/* transmit */
TxMessage.StdId = 0x321;
TxMessage.ExtId = 0x01;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* CAN1 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
kann ich danach die Datenrichtung meines LCD-Ports nicht mehr anfassen.
Als IDE verwende ich Crossworks, Jtag-Adapter ist ein Olimex
ARM-USB-OCD.
Falls irgendjemand einen Tipp hat, warum ich an der Stelle auf die
Schnauze falle, bin für jeden Rat dankbar.
Vielen Dank und sorry für den vielen (Quell-) Text.
Ray
Ist im richtigen Programm denn auch die Reihenfolge eingehalten (erst
jeweiliges Peripheral clock enable und dann erst Peripheral
konfigurieren)? Am besten immer den auf ein Minimum reduzierten, aber
kompletten Sourcecode posten. Dann erübrigen sich viele Rückfragen.
(Viel mehr werde ich wohl leider nicht "helfen" können, da ich selbst
gerade erst starte...)
Lutz schrieb:> Ist im richtigen Programm denn auch die Reihenfolge eingehalten (erst> jeweiliges Peripheral clock enable und dann erst Peripheral> konfigurieren)?
jein, zuerst werden alle GPIOs auf floating input gesetzt (sollten sie
zwar schon sein, aber ...)
dann wird der Systemclock (PLL) angeworfen und anschliessend alle
Peripherie-Clocks gesetzt, nun NVIC, GPIOs und ADC und Timer und CAN
konfiguriert.
Hallo,
ich habe jetzt etwas herum geschaut und festgestellt, dass Crossworks
den call_stack zur Verfügung stellt, die letzte aufgerufene Funktion
war:
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage)
und
dort steht der PC auf -> Disassembler
RxMessage->Data[3] = (uint8_t)0xFF &
(CANx->sFIFOMailBox[FIFONumber].RDLR >> 24);
793B ldrb r3, [r7, #4]
68BA ldr r2, [r7, #8]
EA4F1303 mov.w r3, r3, lsl #4
4413 add r3, r2
F50373DC add.w r3, r3, #0x1B8
-> 681B ldr r3, [r3, #0]
EA4F6313 mov.w r3, r3, lsr #24
B2DA uxtb r2, r3
683B ldr r3, [r7, #0]
739A strb r2, [r3, #14]
sehe ich das recht, dass hier gerade das 4.Byte aus dem Receive-FIFO
kopert werden soll (kann leider [noch] kein Assembler)? Kann es sein,
dass die CAN-Hardware im selbem Moment den FIFO neu beschreibt und es
daher zu einem Zugriffskonflikt kommt?
Lutz schrieb:> Schon komisch, da ja CAN_Receive in Deinem geposteten Code gar nicht> vorkommt ...
Naja ich wollte jetzt nicht die ganzen libs von ST mit posten, da im
geposteten Code aber ein Interrupt für CAN initialisiert wird, ergibt es
sich fast schon von selbst, dass es dazu auch eine passende
Interrupt-Routine gibt - auch schön brav aus den Beispielen von ST
übernommen. Da ich im Moment aber keine Zeit für weitere Fehlersuche
habe, ist das Ganze erst einmal auf Eis gelegt, bis ich wieder etwas
Luft und Lust habe.
Jackie73 schrieb:> Hi Ray@h,> an was für ein Projekt arbeitest du gerade?>> Reine Interesse mit CAN und LCD hört sich interesant an :)
Eigentlich ein PWM-Controller der über CAN eingestellt werden kann - so
ein einfaches Display (2x16) ist immer schön, wenn man ein paar
Statusausgaben haben will. Jeder Teil für sich funktioniert auch, nur
sobald CAN mit etwas anderem laufen soll, wird es instabil und früher
oder später landet der Controller im
HardFault (default) Handler (Endlosschleife).
Bye