I have a small circuit withy dsPIC30F4012, sometimes it works ok but sometimes without any reason randomly resets back to start of the program.
Powered by 3V MCLR has 10k resistor
Some settings:
_FOSC(CSW_FSCM_OFF & FRC_PLL4 & CSW_ON_FSCM_OFF & CSW_FSCM_OFF);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_OFF & MCLR_DIS & PWRT_OFF & BORV20);
_FGS(CODE_PROT_OFF & GWRP_OFF);
#define TMR1_PERIOD 7369
{
TMR1 = 0; /* clear timer1 register */
PR1 = TMR1_PERIOD; /* set period1 register */
T1CONbits.TCS = 0; /* set internal clock source */
IPC0bits.T1IP = 4; /* set priority level */
IFS0bits.T1IF = 0; /* clear interrupt flag */
IEC0bits.T1IE = 1; /* enable interrupts */
SRbits.IPL = 3; /* enable CPU priority levels 4-7 */
T1CONbits.TON = 1; /* start the timer */
}
/****** START OF INTERRUPT SERVICE ROUTINES *********/
void __attribute__((__interrupt__, __shadow__, __no_auto_psv__ )) _T1Interrupt(void)
{
Timer1 ++;
Timer2 ++;
Timer3 ++;
Timer4 ++;
MainCounter++;
IFS0bits.T1IF = 0; /* clear interrupt flag */
return;
}
RESET the processor can be invoked for the following reasons: start power supply, reset signal input /MCLR or WDT overflow.
Be careful: Before switching the prescaler between Timer0 and WDT Modules are recommended TMR0 and WDT reset, otherwise it may be accidental (unintentional) reset the processor.
Check it out.
Related
I am having a lot of trouble when it comes to flash erasing on the dsPIC33EP64GP503 and I am hoping someone on here will be able help.
I am wanting to store a data struct in the flash program memory of the device. I am having trouble when it comes to erasing the flash though. I need to erase it and re-write it when the data changes.
I am padding the rest of the page with 0s so it can be safely erased.
I can write to the same memory location of the struct. When doing a flash write onto the start of the struct, the byStructValid turns into 0x11 (I know this is all very bad, because it is writing double word. But I am just trying to get the flash operations working first), however when I do an erase nothing happens. Is someone able to figure out what I am doing wrong?
I initialised the struct with 0xFF's and tried to perform a flash write. This was successful as the CAN message I received showed the data changed from 0xFF to 0x11.
I then tried to do a flash erase, but nothing happened. The device just carried on as normal. I don't have access to debug so it is hard to fully understand what is going on during this time.
I have tried moving the struct location around, so that it is on an 'even' page boundary (as specified in the datasheet) but this hasn't worked either.
I have also tried using an assembly version of the erase function, provided by the datasheet, this also doesn't work. The device just carries on as though there was no command for flash erase.
Below are some snippets of code that I have been using.
Any help would be greatly appreciated, thank you.
Note: I am unable to use the debugger. I use CAN messages to periodically send ‘debug’ messages, which contain data that is read from the flash location. This is so I can see if the write/erases are working.
#define MEMORY_USER_CALIBRATION_LOC 0x006000
typedef struct
{
byte byStructValid;
byte abyStructData[3];
}stFlashStruct_t;
volatile const __prog__ stFlashStruct_t stFlashStruct __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC))) =
{
.byStructValid = 0xFF,
.abyStructData = {50, 10, 20},
};
const byte padding[_FLASH_PAGE*2 - sizeof(stFlashStruct_t)] __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC + sizeof(stFlashStruct_t)))) = {0};
//FLASH Write
void FLASH_WriteDoubleWord(dword address, dword data[2])
{
word INTCON2Save;
word i;
//set WREN and ERASE settings for operation
NVMCON = 0x4001;
TBLPAG = 0xFA;
//set address to erase
NVMADR = address & 0xFFFF;
NVMADRU = (address >> 16) & 0x3F;
for (i = 0; i < 2; i++)
{
__builtin_tblwtl(i*2, data[i] & 0xFFFF);
__builtin_tblwth(i*2, (data[i] >> 16) & 0xFF);
}
//save the interrupt register
INTCON2Save = INTCON2;
// Disable interrupts for NVM unlock
__builtin_disable_interrupts();
__builtin_write_NVM();
// Start write cycle
while(NVMCONbits.WR == 1);
//restore interrupts
INTCON2 = INTCON2Save;
}
//FLASH Erase
void FLASH_ErasePageC(dword dwAddress)
{
word INTCON2Save;
//set WREN and ERASE settings for operation
NVMCON = 0x4003;
//set address to erase
NVMADRU = (dwAddress >> 16) & 0x3F;
NVMADR = dwAddress & 0xFFFF;
//save the interrupt register
INTCON2Save = INTCON2;
__builtin_disable_interrupts();
// Disable interrupts for NVM unlock
__builtin_write_NVM();
// Start write cycle
while(NVMCONbits.WR == 1);
//restore interrupts
INTCON2 = INTCON2Save;
}
byte temp_flash_write(void)
{
dword new_data[2] = {0x1111, 0x1111};
FLASH_WriteDoubleWord(&stCustomerCalibration, new_data);
return 0;
}
Your "dsPIC33 Flash Erase broken" issue is one of not understanding just how badly the Run Time Flash Programming (RTFP) method is described in the Microchip dsPIC33EP64GP503 data sheet and family reference manuals.
This post will not explain how any of this works. It does work but is really hard to comprehend.
What will be hard for you is that a program flash word can only be written one time after an erase. Writing to the same program flash word a second time will corrupt it and the next time it is read an ECC trap error will assert.
Attached is example code that allocates a 1024 instruction word page at address 0x6000. Declares a structure at the start of that page that is 2 instruction words in size. The code then erases that page then writes different data to the first 2 instruction words in that page.
/*
* File: main.c
* Author: Dan1138
*
* Description:
* Example for Run Time Self Programming (RTSP).
* This is very limited, useful as a test bench but not much more.
*
* Created on December 10, 2022, 2:05 PM
*/
/* Define the system oscillator frequency this code must configure */
#define FSYS (7372800ul)
#define FCY (FSYS/2ul)
// DSPIC33EP64GP503 Configuration Bit Settings
// 'C' source line config statements
// FICD
#pragma config ICS = PGD1 // ICD Communication Channel Select bits (Communicate on PGEC1 and PGED1)
#pragma config JTAGEN = OFF // JTAG Enable bit (JTAG is disabled)
// FPOR
#pragma config ALTI2C1 = OFF // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25 // Watchdog Window Select bits (WDT Window is 25% of WDT period)
// FWDT
#pragma config WDTPOST = PS32768 // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128 // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)
// FOSC
#pragma config POSCMD = NONE // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = ON // OSC2 Pin Function bit (OSC2 is general purpose digital I/O pin)
#pragma config IOL1WAY = OFF // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSECMD // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled)
// FOSCSEL
#pragma config FNOSC = FRC // Oscillator Source Selection (Internal Fast RC (FRC))
#pragma config IESO = ON // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)
// FGS
#pragma config GWRP = OFF // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF // General Segment Code-Protect bit (General Segment Code protect is Disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <libpic30.h>
#define MEMORY_USER_CALIBRATION_LOC (_FLASH_PAGE * 24)
typedef struct
{
uint8_t byStructValid;
uint8_t abyStructData[3];
} stFlashStruct_t;
volatile const __prog__ __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC))) union
{
uint16_t words[_FLASH_PAGE]; /* reserve the entire erase page. Note only the low 16-bits of the instruction word can be accessed with this method. */
struct {
stFlashStruct_t stFlashStruct; /* calibration structure */
};
} CalSpace =
{
.stFlashStruct.byStructValid = 0xFF,
.stFlashStruct.abyStructData = {50, 10, 20},
};
int main(void)
{
volatile stFlashStruct_t ReadBack;
/*
* application initialization
*/
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint(); /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();
/* Erase 1024 instruction words starting at address MEMORY_USER_CALIBRATION_LOC */
NVMCON = 0x4003;
NVMADR = __builtin_tbloffset(&CalSpace);
NVMADRU = __builtin_tblpage(&CalSpace);
__builtin_disi(5); // Disable interrupts for NVM unlock
__builtin_write_NVM(); // Start write cycle
while(NVMCONbits.WR == 1);
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint(); /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();
/* Update data in structure to be written */
ReadBack.byStructValid = 1;
ReadBack.abyStructData[0] = 2;
ReadBack.abyStructData[1] = 3;
ReadBack.abyStructData[2] = 4;
/* Write 2 instruction words starting at address MEMORY_USER_CALIBRATION_LOC */
NVMCON = 0x4001; // Set WREN and word program mode
TBLPAG = 0xFA; // write latch upper address
NVMADR = __builtin_tbloffset(&CalSpace.stFlashStruct);
NVMADRU = __builtin_tblpage(&CalSpace);
__builtin_tblwtl(0,*((uint16_t *)(&ReadBack)+0)); // load low 16-bits of first instruction word
__builtin_tblwth(0,0x00); // make high 8-bits of first instruction word zero
__builtin_tblwtl(2,*((uint16_t *)(&ReadBack)+1)); // load low 16-bits of second instruction word
__builtin_tblwth(2,0x00); // make high 8-bits of second instruction word zero
__builtin_disi(5); // Disable interrupts for NVM unlock sequence
__builtin_write_NVM(); // initiate write
while(NVMCONbits.WR == 1);
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint(); /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();
/*
* Application process loop
*/
for(;;)
{
Nop();
Nop();
Nop();
__delay_ms(100);
}
}
Following this post I managed to setup my Nucleo board with two SPI devices & working interrupts with 1ms periodic 6 bytes payload transmission. My idea was to trigger the two SPI modules together as to have them run in parallel but something is preventing me from achieving that:
expected: SPI1 & SPI2 sequences are 99% overlapped, only dephased by a couple of system clocks
observed: the first bytes are overlapping as expected but then the first SPI module that was called (SPI1) seems to take precedence and complete its transmission before allowing SPI2 to terminate his. If SPI2 is called first then it will finish first.
Here are my main code pieces:
volatile uint8_t t[6] = {0x50, 0x60, 0x70, 0x80, 0x90, 0x10};
volatile uint8_t r[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
volatile uint8_t transmit_count1 = 6, transmit_count2 = 6, transmit_count3 = 6;
volatile uint8_t transmit_index1 = 0, transmit_index2 = 0, transmit_index3 = 0;
void do_SPI_ISR(){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // SS1
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // SS2
LL_SPI_Enable(SPI1);
LL_SPI_Enable(SPI2);
transmit_index1 = transmit_index2 = transmit_index3 = 0;
transmit_count1 = transmit_count2 = transmit_count3 = 6;
LL_SPI_EnableIT_TXE(SPI1); // enable SPI1 TX interrupt
LL_SPI_EnableIT_TXE(SPI2); // enable SPI2 TX interrupt
LL_SPI_TransmitData8(SPI1, t[transmit_index1]);
LL_SPI_TransmitData8(SPI2, t[transmit_index2]);
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET){
// SS are set HIGH by interrupts, remain here until that happens for both lines
}
}
void SPI1_ISR_callback(){
if (transmit_index1 < transmit_count1 - 1){
transmit_index1 ++;
LL_SPI_TransmitData8(SPI1, t[transmit_index1]);
} else {
LL_SPI_DisableIT_TXE(SPI1);
transmit_index1 = 0;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
LL_SPI_Disable(SPI1);
}
}
void SPI2_ISR_callback(){
if (transmit_index2 < transmit_count2 - 1){
transmit_index2 ++;
LL_SPI_TransmitData8(SPI2, t[transmit_index2]);
} else {
LL_SPI_DisableIT_TXE(SPI2);
transmit_index2 = 0;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
LL_SPI_Disable(SPI2);
}
}
I did not tune anything regarding interrupt priorities, both SPIs have 0/0 priority. I was assuming that both interrupts would fire in turn and trigger bytes transmission but it's not the case, maybe some interrupt event constantly fire on SPI1, thus preventing SPI2 fire his? I tried removing all error & receive interrupts but that didn't change the outcome.
Edit, more code:
void SPI1_IRQHandler(void)
{
/* USER CODE BEGIN SPI1_IRQn 0 */
if (LL_SPI_IsActiveFlag_TXE(SPI1)){
SPI1_ISR_callback();
}
/* USER CODE END SPI1_IRQn 0 */
/* USER CODE BEGIN SPI1_IRQn 1 */
/* USER CODE END SPI1_IRQn 1 */
}
/**
* #brief This function handles SPI2 global interrupt.
*/
void SPI2_IRQHandler(void)
{
/* USER CODE BEGIN SPI2_IRQn 0 */
if (LL_SPI_IsActiveFlag_TXE(SPI2)){
SPI2_ISR_callback();
}
/* USER CODE END SPI2_IRQn 0 */
/* USER CODE BEGIN SPI2_IRQn 1 */
/* USER CODE END SPI2_IRQn 1 */
}
Edit 2 (25/05/2020), with TXE flag managed from main app and interrupts disabled:
Corresponding code:
void do_SPI_ISR(){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // SS1
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // SS2
LL_SPI_Enable(SPI1);
LL_SPI_Enable(SPI2);
transmit_index1 = transmit_index2 = transmit_index3 = 0;
transmit_count1 = transmit_count2 = transmit_count3 = 6;
//LL_SPI_EnableIT_TXE(SPI1); // enable SPI1 TX interrupt
//LL_SPI_EnableIT_TXE(SPI2); // enable SPI2 TX interrupt
LL_SPI_TransmitData8(SPI1, t[transmit_index1]);
LL_SPI_TransmitData8(SPI2, t[transmit_index2]);
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET){
if (LL_SPI_IsActiveFlag_TXE(SPI1)){
SPI1_ISR_callback();
}
if (LL_SPI_IsActiveFlag_TXE(SPI2)){
SPI2_ISR_callback();
}
}
}
Any help much appreciated
Actually I'm using a PIC24FJ128GB204 and I've have problems with DeepSleep.
My device is composed by 4 buttons and several LED (a colored torch). Have a button that make device Sleep until I want to use it, same button wakes up my device.
Consumption will all LED are off is 10mA.
I've tried Sleep mode, simply function that goes in basic sleep and than wakeup after selected pin is asserted. Measuring consumption in Sleep mode I've 2.50mA. Working very well.
I've started to work with DeepSleep, since I don't need any code retention and just need to keep my device in lowest possible consumption state (but avoiding to use a slide power switch). I've used Datasheet example codes to implement my function. As result I can enter in this state and than I've 0.45mA as consumption.
I've set an INT0 (as datasheet suggested) to wake up my device and associated it to correct wakeup PIN.
Problems starts now:
When I press wakeup button, my consumption goes to 10mA as normal, but I can't light ON any led. Seems that my device is not responsive.
If I press again Sleep button, my device goes in Sleep mode and not DeepSleep since my consumption back to 2.50mA. Again, if I wake up my device, it wakes up but are not responsive. Doesn't metter how much time I try again, but my device never go again to DeepSleep untill I power off and on again my device.
I've performed some test but can't understand what happen. Maybe after DeepSleep device should be manually reset (tried without success) or maybe some configuration bit need to be set again. Or maybe configuration bits are uncorrect?
Here's interested parts of code:
CONFIGURATION
// CONFIG4
#pragma config DSWDTPS = DSWDTPS3 // Deep Sleep Watchdog Timer Postscale Select bits (1: 256 (8.3 mS))
#pragma config DSWDTOSC = LPRC // DSWDT Reference Clock Select (DSWDT uses LPRC as reference clock)
#pragma config DSBOREN = ON // Deep Sleep BOR Enable bit (DSBOR Enabled)
#pragma config DSWDTEN = OFF // Deep Sleep Watchdog Timer Enable (DSWDT Disabled)
//#pragma config DSSWEN = OFF // DSEN Bit Enable (Deep Sleep operation is always disabled)
#pragma config DSSWEN = ON // DSEN Bit Enable (Deep Sleep is controlled by the register bit DSEN)
#pragma config PLLDIV = DIVIDE2 // USB 96 MHz PLL Prescaler Select bits (Oscillator input divided by 2 (8 MHz input))
#pragma config I2C1SEL = DISABLE // Alternate I2C1 enable bit (I2C1 uses SCL1 and SDA1 pins)
#pragma config IOL1WAY = ON // PPS IOLOCK Set Only Once Enable bit (Once set, the IOLOCK bit cannot be cleared)
// CONFIG3
#pragma config WPFP = WPFP0 // Write Protection Flash Page Segment Boundary (Page 0 (0x00))
#pragma config SOSCSEL = ON // SOSC Selection bits (SOSC circuit selected)
#pragma config WDTWIN = PS25_0 // Window Mode Watchdog Timer Window Width Select (Watch Dog Timer Window Width is 25 percent)
#pragma config PLLSS = PLL_PRI // PLL Secondary Selection Configuration bit (PLL is fed by the Primary oscillator)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset Enable)
#pragma config WPDIS = WPDIS // Segment Write Protection Disable (Disabled)
#pragma config WPCFG = WPCFGDIS // Write Protect Configuration Page Select (Disabled)
#pragma config WPEND = WPENDMEM // Segment Write Protection End Page Select (Write Protect from WPFP to the last page of memory)
// CONFIG2
#pragma config POSCMD = HS // Primary Oscillator Select (HS Oscillator Enabled)
#pragma config WDTCLK = LPRC // WDT Clock Source Select bits (WDT uses LPRC)
#pragma config OSCIOFCN = ON // OSCO Pin Configuration (OSCO/CLKO/RA3 functions as port I/O (RA3))
#pragma config FCKSM = CSECME // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Clock switching is enabled, Fail-Safe Clock Monitor is enabled)
//#pragma config FCKSM = CSDCMD // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Clock switching and Fail-Safe Clock Monitor are disabled)
#pragma config FNOSC = PRIPLL // Initial Oscillator Select (Primary Oscillator with PLL module (XTPLL,HSPLL, ECPLL))
#pragma config ALTRB6 = APPEND // Alternate RB6 pin function enable bit (Append the RP6/ASCL1/PMPD6 functions of RB6 to RA1 pin functions)
#pragma config ALTCMPI = CxINC_RX // Alternate Comparator Input bit (C1INC, C2INC and C3INC are on RB9 )
#pragma config WDTCMX = WDTCLK // WDT Clock Source Select bits (WDT clock source is determined by the WDTCLK Configuration bits)
#pragma config IESO = OFF // Internal External Switchover (Disabled)
// CONFIG1
#pragma config WDTPS = PS1024 // Watchdog Timer Postscaler Select (1:1,024)
#pragma config FWPSA = PR128 // WDT Prescaler Ratio Select (1:128)
#pragma config WINDIS = OFF // Windowed WDT Disable (Standard Watchdog Timer)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config ICS = PGx3 // Emulator Pin Placement Select bits (Emulator functions are shared with PGEC3/PGED3)
#pragma config LPCFG = OFF // Low power regulator control (Disabled - regardless of RETEN)
//#pragma config LPCFG = ON // Low power regulator control (Low voltage regulator controlled by RETEN bit)
#pragma config GWRP = OFF // General Segment Write Protect (Write to program memory allowed)
#pragma config GCP = OFF // General Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF // JTAG Port Enable (Disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
TURNOFF FUNCTION
void TurnOff(void)
{
T1CONbits.TON = 0;
IEC0bits.T1IE = 0;
/* turn off */
OC1CON1bits.OCM = 0;
OC2CON1bits.OCM = 0;
OC3CON1bits.OCM = 0;
OC4CON1bits.OCM = 0;
OC5CON1bits.OCM = 0;
// OC6CON1bits.OCM = 0;
if (!USB_BUS_SENSE)
{
USBMaskInterrupts();
USBModuleDisable();
OS_ENTER_CRITICAL();
T2CONbits.TON = 0;
IEC0bits.T2IE = 0;
TRISA = 0xffff;
TRISB = 0xffff;
TRISC = 0xffff;
// I2C1CONLbits.I2CEN = 0;
//
// SPI1CON1Lbits.SPIEN = 0;
// SPI2CON1Lbits.SPIEN = 0;
// SPI3CON1Lbits.SPIEN = 0;
//
// U1MODEbits.UARTEN = 0;
// U2MODEbits.UARTEN = 0;
// U3MODEbits.UARTEN = 0;
// U4MODEbits.UARTEN = 0;
//
// DMACONbits.DMAEN = 0;
//
// U1CONbits.USBEN = 0;
// PMD1 = 0xffff;
// PMD2 = 0xffff;
// PMD3 = 0xffff;
// PMD4 = 0xffff;
// PMD5 = 0xffff;
// PMD6 = 0xffff;
// PMD7 = 0xffff;
// PMD8 = 0xffff;
WDTDisable();
LPAppState = OFF_ST;
CNInit();
Nop();
Nop();
OS_EXIT_CRITICAL();
//#ifndef DEBUG_PENNA
{
// ENTRATA IN SLEEP MODE(pag 164)
// TEST 1
// DSCONbits.DSEN = 1;
// DSCONbits.DSEN = 1;
// __asm__ volatile("pwrsav #0");
// TEST 2 non funziona anche se c'è scritto così sul manuale (pag 164)
// __asm__ volatile("disi #7");
// __asm__ volatile("mov #8000, w2");
// __asm__ volatile("mov w2, DSCON");
// __asm__ volatile("mov w2, DSCON");
// __asm__ volatile("nop");
// __asm__ volatile("nop");
// __asm__ volatile("nop");
// __asm__ volatile("PWRSAV #0");
// TEST 3
DSCONbits.DSEN = 1;
DSCONbits.DSEN = 1;
__asm__ volatile("nop");
__asm__ volatile("nop");
__asm__ volatile("nop");
__asm__ volatile("PWRSAV #0");
// TEST 4 - LOW VOLTAGE (pag. 420) [provato sia con CONFIG LPCFG=1 e 0, l'effetto si ha con 1 anche se da manuale c'è scritto il contrario]
// RCONbits.RETEN = 1;
// __asm__ volatile("PWRSAV #0");
}
//#endif
USBDeviceInit();
}
WDTEnable();
T2CONbits.TON = 1;
IEC0bits.T2IE = 1;
}
INTERRUPT DECLARATION
//------------------------------------------------
/**
void INTERRUPT_Initialize (void)
*/
void INTERRUPT_Initialize(void)
{
// INT0I: INT0 - External Interrupt 0
// Priority: 1
IPC0bits.INT0IP = 1;
}
/**
Section: External Interrupt Handlers
*/
void __attribute__((weak)) EX_INT0_CallBack(void)
{
// Add your custom callback code here
// Verifico se il dispositivo è uscito dal Deep Sleep (pag.165 datasheet)
if (RCONbits.DPSLP == 1)
{
// Risveglio da deep sleep
RCONbits.DPSLP = 0;
DSCONbits.RELEASE = 0;
}
}
/**
Interrupt Handler for EX_INT0 - INT0
*/
void __attribute__((interrupt, no_auto_psv)) _INT0Interrupt(void)
{
//***User Area Begin->code: INT0 - External Interrupt 0***
EX_INT0_CallBack();
//***User Area End->code: INT0 - External Interrupt 0***
EX_INT0_InterruptFlagClear();
}
/**
Section: External Interrupt Initializers
*/
/**
void EXT_INT_Initialize(void)
Initializer for the following external interrupts
INT0
*/
void EXT_INT_Initialize(void)
{
/*******
* INT0
* Clear the interrupt flag
* Set the external interrupt edge detect
* Enable the interrupt, if enabled in the UI.
********/
EX_INT0_InterruptFlagClear();
EX_INT0_PositiveEdgeSet();
EX_INT0_InterruptEnable();
}
When I press wakeup button, my consumption goes to 10mA as normal, but
I can't light ON any led. Seems that my device is not responsive
Your problem is here:
TRISA = 0xffff;
TRISB = 0xffff;
TRISC = 0xffff;
You set the pins to input before entering deep sleep, but I don't see anywhere in your code where you set the pins up after you exit sleep so they are still acting as inputs and thus you won't be able to light an LED.
I have the issue with FMC controller when interfacing 64MB IS42S16400J-7BLI.
I'm using the CubeMX to set base configuration
static void MX_FMC_Init(void)
{
FMC_SDRAM_TimingTypeDef SdramTiming;
/** Perform the SDRAM1 memory initialization sequence
*/
hsdram1.Instance = FMC_SDRAM_DEVICE;
/* hsdram1.Init */
hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_11;
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
/* SdramTiming */
SdramTiming.LoadToActiveDelay = 2;
SdramTiming.ExitSelfRefreshDelay = 7;
SdramTiming.SelfRefreshTime = 4;
SdramTiming.RowCycleDelay = 7;
SdramTiming.WriteRecoveryTime = 3;
SdramTiming.RPDelay = 2;
SdramTiming.RCDDelay = 2;
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
{
Error_Handler();
}
}
and config the memory
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef* hsdram, FMC_SDRAM_CommandTypeDef* Command)
{
__IO uint32_t tmpmrd = 0;
/* Step 3: Configure a clock configuration enable command */
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 4: Insert 100 ms delay */
HAL_Delay(100);
/* Step 5: Configure a PALL (precharge all) command */
Command->CommandMode = FMC_SDRAM_CMD_PALL;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 6 : Configure a Auto-Refresh command */
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 4;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 7: Program the external memory mode register */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = tmpmrd;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 8: Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
}
The memory and micro are connected according to the schematic
I can use only 8bit of addressing. In this configuration everything is perfect, i.e. I can read/write values and observe them in debug window. It limits me though to only 8MB of memory.
When I modify in settings 8bits up to 9/10/11bits to have more memory available it starts malfunctioning,i.e. garbage in some memory area.
I made customized board, but the same issue you going find on the STM32F429-disco board. So I reject rather the connections. I tried to play with the time delays like "Row to column delay" and increase all delays possible, but not luck. Any help would be appreciated.
From IS42S16400J-7BLI datasheet:
Internally configured as a quad-bank DRAM with a synchronous
interface. Each 16,777,216-bit bank is organized as 4,096 rows by 256
columns by 16 bits.
So, you should use 8 bit in ColumnBitsNumber. And you'll get 8 Mbytes (64 MBits/8) of memory.
I developed a simple program to produce PWM waveform on dsPIC33EV256GM002 but I can't disable it. I used PWM1 and PWM2 and I would generate PWM waveform on PWM1L1 pin (pin 26 on DIP package) maintain PWM1H1 (pin 25 on DIP package) as digital I/O.
Teorically the PWM register setting:
IOCON1bits.PENL = 1; /* PWM1L is controlled by PWM module /
IOCON1bits.PENH = 0; / PWM1H is controlled by GPIO module */
should do that but, using and oscilloscope, I noticed the PWM waveform on PWM1H1 pin, with opposite value (when PWM1L is 1 PWM1H is 0 and veceversa) even if it should be a digital I/O.
Did you find any similar problem ?
Thank you very much for your help and cooperation
regards
I used the following code:
TRISBbits.TRISB10 = 0; /* Set as a digital output */
TRISBbits.TRISB11 = 0; /* Set as a digital output */
TRISBbits.TRISB12 = 0; /* Set as a digital output */
TRISBbits.TRISB13 = 0; /* Set as a digital output */
TRISBbits.TRISB14 = 0; /* Set as a digital output */
TRISBbits.TRISB15 = 0; /* Set as a digital output */
LATBbits.LATB10 = 0; /* Set as a digital output */
LATBbits.LATB11 = 0; /* Set as a digital output */
LATBbits.LATB12 = 0; /* Set as a digital output */
LATBbits.LATB13 = 0; /* Set as a digital output */
LATBbits.LATB14 = 0; /* Set as a digital output */
LATBbits.LATB15 = 0; /* Set as a digital output */
PORTBbits.RB10=0;
PORTBbits.RB11=0;
PORTBbits.RB12=0;
PORTBbits.RB13=0;
PORTBbits.RB14=0;
PORTBbits.RB15=0;
PTPER = 4000;
/*~~~~~~~~~~ PWM1 Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
IOCON1bits.PENL = 1; /* PWM1L is controlled by PWM module */
IOCON1bits.PENH = 0; /* PWM1H is controlled by GPIO module */
IOCON1bits.PMOD = 0; /* Select Independent Output PWM mode */
PDC1 = 500; /* Initial Duty cycle */
DTR1 = 0; /* Deadtime setting */
ALTDTR1 = 0; /* Deadtime setting */
PHASE1 = 0; /* No phase shift */
/*~~~~~~~~~~~ PWM2 Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
IOCON2bits.PENH = 1; /* PWM2H is controlled by PWM module */
IOCON2bits.PENL = 0; /* PWM2L is controlled by GPIO module */
IOCON2bits.PMOD = 0; /* Select Independent Output PWM mode */
PDC2 = 2000; /* Initial Duty cycle */
DTR2 = 0; /* Deadtime setting */
ALTDTR2 = 0; /* Deadtime setting */
PHASE2 = 0; /* */
PTCONbits.PTEN = 1; /* Enable the PWM Module */
The problem was related to the write protection of IOCONxbits register.
I added the following line:
_FDEVOPT( PWMLOCK_OFF );
and this fixed the problem.
I faced same problem with dspic33ev32GP002 and changed configuration bits like so:
// FDEVOPT
#pragma config PWMLOCK = OFF
This worked for me.